From: jcorgan Date: Thu, 3 Aug 2006 04:51:51 +0000 (+0000) Subject: Houston, we have a trunk. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;ds=sidebyside;h=5d69a524f81f234b3fbc41d49ba18d6f6886baba;p=debian%2Fgnuradio Houston, we have a trunk. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5 --- 5d69a524f81f234b3fbc41d49ba18d6f6886baba diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..d1fb4ddc --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +Eric Blossom Most of the guts +Matt Ettus ongoing code, ideas, bugfixes, the USRP +John Gilmore ideas, bug fixes, financial support +Stephane Fillod SIMD speed ups, lots of other good stuff +Chuck Swiger hf stuff, enthusiasm ;) +Ramakrishnan Muthukrishnan Debian pkgs + misc stuff +Martin Dudok van Heel lots of stuff +Bob McGwier N4HY wisdom, code, bugfixes. +Krzysztof Kamieniecki bugfixes +Andrew Thomas Beck bugfixes +Joshua Lackey Original GMSK implementation. +Johnathan Corgan Goertzel, squelch, adaptive filtering, misc. diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..2237a4ab --- /dev/null +++ b/ChangeLog @@ -0,0 +1,20 @@ +# +# Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..54caf7c1 --- /dev/null +++ b/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..883a490a --- /dev/null +++ b/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2001,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + bootstrap \ + configure \ + config.h.in + +SUBDIRS = @subdirs@ diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 00000000..2259cac0 --- /dev/null +++ b/Makefile.common @@ -0,0 +1,40 @@ +# -*- Makefile -*- +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# includes +grincludedir = $(includedir)/gnuradio + +# swig includes +swigincludedir = $(grincludedir)/swig + +# Install this stuff in the appropriate subdirectory +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +grpythondir = $(pythondir)/gnuradio +grpyexecdir = $(pyexecdir)/gnuradio + +# swig flags +SWIGPYTHONFLAGS = -fvirtual -python -modern + +# gnuradio-core library link command +GNURADIO_CORE_LIBS = -L$(top_srcdir)/gnuradio-core/src/lib/.libs -lgnuradio-core -lfftw3f -lm diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..d93a0dd6 --- /dev/null +++ b/NEWS @@ -0,0 +1,15 @@ +------------------------------------------------------- +Copying information: + +Copyright (C) 2001, Free Software Foundation, Inc. + + Permission is granted to anyone to make or distribute verbatim copies + of this document as received, in any medium, provided that the + copyright notice and this permission notice are preserved, + thus giving the recipient permission to redistribute in turn. + + Permission is granted to distribute modified versions + of this document, or of portions of it, + under the above conditions, provided also that they + carry prominent notices stating who last changed them. + diff --git a/README b/README new file mode 100644 index 00000000..dfc0ac8d --- /dev/null +++ b/README @@ -0,0 +1,190 @@ +# +# Copyright 2001,2002,2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +------------------------------------------------------------------------------- + + IMPORTANT + +------------------------------------------------------------------------------- + +GNU Radio is now broken up into several packages. You're looking at +the gnuradio-core. You'll probably want some or all of these too. +Build and install them in the order listed here: + + gnuradio-core # main library + gnuradio-examples # examples + gr-audio-alsa # support for sounds cards using ALSA (prefered under GNU/Linux) + gr-audio-oss # support for sounds cards using OSS + gr-audio-jack # support for JACK Audio Connection Kit + gr-audio-windows # support for sounds cards using Windows Wave + gr-comedi # support for DAQ cards using COMEDI + gr-wxgui # GUI framework built on wxPython + usrp # non-GNU Radio specific portion of usrp + gr-usrp # glues usrp into GNU Radio + mc4020 # GNU/Linux driver for Measurement Computing PCI-DAS4020/12 A/D board + gr-mc4020 # the glue that ties the mc4020 driver into GNU Radio + + +------------------------------------------------------------------------------- + + KNOWN INCOMPATIBILITIES + + + GNU Radio triggers bugs in g++ 3.3 for X86. DO NOT USE GCC 3.3. + gcc 3.2 and 3.4 are known to work well. + +------------------------------------------------------------------------------- + +Prerequisites (you may already have these): + +(1) 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. + + +(2) 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. + + +(3) Python 2.3 or later http://www.python.org + +Python 2.3 or later is now required. If your distribution splits +python into a bunch of separate RPMS including python-devel or +libpython you'll most likely need those too. + + +(4) Numeric python library http://numeric.scipy.org + +Provides a high performance array type for Python. + + +(5) The Boost C++ Libraries http://www.boost.org + +We use the Smart Pointer library. Fedore Core 2 has a package for +this, boost-devel-1.31.0-7. Otherwise download the source and follow +the build instructions. They're a bit different from the normal +./configure && make + + +(6) cppunit 1.9.14 or later. http://cppunit.sourceforge.net + +Unit testing framework for C++. + + +(7) Simple Wrapper Interface Generator. http://www.swig.org + +These versions are known to work: + 1.3.23, 1.3.24, 1.3.25, 1.3.27, 1.3.28, 1.3.29 + +---------------------------------------------------------------- + +For the impatient, just do the following: + + $ ./configure + $ make + $ make check + $ make install + +If it doesn't work, fix it and send us a patch... + + +See http://www.gnu.org/software/gnuradio/ for an overview. +The project is hosted at http://savannah.gnu.org/projects/gnuradio/ + + +If you've got doxygen installed and provide the --enable-doxygen +configure option, the build process creates documentation for the +class hierarchy etc. Point your browser at +gnuradio-core/doc/html/index.html + + +To run the examples you'll need to set PYTHONPATH. +Note that the python version number in the path needs to match your +installed version of python. + + $ export PYTHONPATH=/usr/local/lib/python2.3/site-packages + +You may want to add this to your ~/.bash_profile + + + +---------------------------------------------------------------- + + Notes on building GNU Radio from the CVS repository + +---------------------------------------------------------------- + +If you're building from the CVS repository YOU MUST BE PLAYING BY THE +RULES THAT THE OTHER DEVELOPERS ARE USING. This is especially true +with regard to the versions of the tools below... + +Ensure that you've got THESE VERSIONS of the following tools: + + autoconf 2.57 or later + automake 1.7.4 or later + libtool 1.5 or later + swig 1.3.{23,24,25,27,28,29} + +If you're using earlier versions than these, don't expect the system +to build. Get these versions or something later. They're available +at any of the GNU mirrors. + +Then, check out a copy of GNU Radio. + +See http://www.gnu.org/software/gnuradio for directions on anonymous +access to the CVS repository. + +Then in the top level directory, execute + + $ ./bootstrap + +This builds configure from configure.ac and also builds all the +Makefile.in's from the Makefile.am's. + +Then carry on as usual: + + $ ./configure + $ make + $ make check + $ make install + + +For the easiest way to build from CVS, see +http://comsec.com/wiki?HowtoBuildFromCVS + + + +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: + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/local/lib + $ make CPPFLAGS="-I$HOME/local/include" + diff --git a/bootstrap b/bootstrap new file mode 100755 index 00000000..7df375ee --- /dev/null +++ b/bootstrap @@ -0,0 +1,29 @@ +#!/bin/sh + +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + + +rm -fr config.cache autom4te*.cache + +aclocal -I config +autoconf +autoheader +libtoolize --automake +automake --add-missing diff --git a/config.guess b/config.guess new file mode 100755 index 00000000..52c01be4 --- /dev/null +++ b/config.guess @@ -0,0 +1,1465 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-11-11' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[345]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 00000000..a4aba165 --- /dev/null +++ b/config.sub @@ -0,0 +1,1587 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-11-13' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ms1 \ + | msp430 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m32c) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | ms1-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + m32c-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 00000000..fd33c622 --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1,66 @@ +# +# Copyright 2001,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install m4 macros in this directory +m4datadir = $(datadir)/aclocal + +# List your m4 macros here +m4macros = \ + acx_pthread.m4 \ + bnv_have_qt.m4 \ + cppunit.m4 \ + gr_as.m4 \ + gr_boost.m4 \ + gr_check_createfilemapping.m4 \ + gr_check_usrp.m4 \ + gr_check_mc4020.m4 \ + gr_check_shm_open.m4 \ + gr_doxygen.m4 \ + gr_gprof.m4 \ + gr_libgnuradio_core_extra_ldflags.m4 \ + gr_no_undefined.m4 \ + gr_omnithread.m4 \ + gr_pwin32.m4 \ + gr_python.m4 \ + gr_require_mc4020.m4 \ + gr_scripting.m4 \ + gr_set_md_cpu.m4 \ + gr_swig.m4 \ + gr_sysv_shm.m4 \ + gr_x86_64.m4 \ + lf_cc.m4 \ + lf_cxx.m4 \ + lf_warnings.m4 \ + lf_x11.m4 \ + mkstemp.m4 \ + onceonly.m4 \ + pkg.m4 \ + usrp_fusb_tech.m4 \ + usrp_libusb.m4 \ + usrp_sdcc.m4 + + +# Don't install m4 macros anymore +# m4data_DATA = $(m4macros) + +EXTRA_DIST = $(m4macros) diff --git a/config/acx_pthread.m4 b/config/acx_pthread.m4 new file mode 100644 index 00000000..d318ab01 --- /dev/null +++ b/config/acx_pthread.m4 @@ -0,0 +1,190 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# pthread: Linux, etcetera +# --thread-safe: KAI C++ + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthread or + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: threads are created detached by default + # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + AC_MSG_CHECKING([for joinable pthread attribute]) + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_UNDETACHED;], + ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) + fi + if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then + AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, + [Define to the necessary symbol if this constant + uses a non-standard name on your system.]) + fi + AC_MSG_RESULT(${ok}) + if test x"$ok" = xunknown; then + AC_MSG_WARN([we do not know how to create joinable pthreads]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/config/bnv_have_qt.m4 b/config/bnv_have_qt.m4 new file mode 100644 index 00000000..1469bfbf --- /dev/null +++ b/config/bnv_have_qt.m4 @@ -0,0 +1,404 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/bnv_have_qt.html +dnl +AC_DEFUN([BNV_HAVE_QT], +[ + dnl THANKS! This code includes bug fixes by: + dnl Tim McClarren. + + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PATH_X]) + AC_REQUIRE([AC_PATH_XTRA]) + + AC_MSG_CHECKING(for Qt) + + AC_ARG_WITH([Qt-dir], + [ --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the + installation instructions of Trolltech. Header + files are in DIR/include, binary utilities are + in DIR/bin and the library is in DIR/lib]) + AC_ARG_WITH([Qt-include-dir], + [ --with-Qt-include-dir=DIR + Qt header files are in DIR]) + AC_ARG_WITH([Qt-bin-dir], + [ --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR]) + AC_ARG_WITH([Qt-lib-dir], + [ --with-Qt-lib-dir=DIR The Qt library is in DIR]) + AC_ARG_WITH([Qt-lib], + [ --with-Qt-lib=LIB Use -lLIB to link with the Qt library]) + if test x"$with_Qt_dir" = x"no" || + test x"$with_Qt_include-dir" = x"no" || + test x"$with_Qt_bin_dir" = x"no" || + test x"$with_Qt_lib_dir" = x"no" || + test x"$with_Qt_lib" = x"no"; then + # user disabled Qt. Leave cache alone. + have_qt="User disabled Qt." + else + # "yes" is a bogus option + if test x"$with_Qt_dir" = xyes; then + with_Qt_dir= + fi + if test x"$with_Qt_include_dir" = xyes; then + with_Qt_include_dir= + fi + if test x"$with_Qt_bin_dir" = xyes; then + with_Qt_bin_dir= + fi + if test x"$with_Qt_lib_dir" = xyes; then + with_Qt_lib_dir= + fi + if test x"$with_Qt_lib" = xyes; then + with_Qt_lib= + fi + # No Qt unless we discover otherwise + have_qt=no + # Check whether we are requested to link with a specific version + if test x"$with_Qt_lib" != x; then + bnv_qt_lib="$with_Qt_lib" + fi + # Check whether we were supplied with an answer already + if test x"$with_Qt_dir" != x; then + have_qt=yes + bnv_qt_dir="$with_Qt_dir" + bnv_qt_include_dir="$with_Qt_dir/include" + bnv_qt_bin_dir="$with_Qt_dir/bin" + bnv_qt_lib_dir="$with_Qt_dir/lib" + # Only search for the lib if the user did not define one already + if test x"$bnv_qt_lib" = x; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # Use cached value or do search, starting with suggestions from + # the command line + AC_CACHE_VAL(bnv_cv_have_qt, + [ + # We are not given a solution and there is no cached value. + bnv_qt_dir=NO + bnv_qt_include_dir=NO + bnv_qt_lib_dir=NO + if test x"$bnv_qt_lib" = x; then + bnv_qt_lib=NO + fi + BNV_PATH_QT_DIRECT + if test "$bnv_qt_dir" = NO || + test "$bnv_qt_include_dir" = NO || + test "$bnv_qt_lib_dir" = NO || + test "$bnv_qt_lib" = NO; then + # Problem with finding complete Qt. Cache the known absence of Qt. + bnv_cv_have_qt="have_qt=no" + else + # Record where we found Qt for the cache. + bnv_cv_have_qt="have_qt=yes \ + bnv_qt_dir=$bnv_qt_dir \ + bnv_qt_include_dir=$bnv_qt_include_dir \ + bnv_qt_bin_dir=$bnv_qt_bin_dir \ + bnv_qt_LIBS=\"$bnv_qt_LIBS\"" + fi + ])dnl + eval "$bnv_cv_have_qt" + fi # all $bnv_qt_* are set + fi # $have_qt reflects the system status + if test x"$have_qt" = xyes; then + QT_CXXFLAGS="-I$bnv_qt_include_dir" + QT_DIR="$bnv_qt_dir" + QT_LIBS="$bnv_qt_LIBS" + # If bnv_qt_dir is defined, utilities are expected to be in the + # bin subdirectory + if test x"$bnv_qt_dir" != x; then + if test -x "$bnv_qt_dir/bin/uic"; then + QT_UIC="$bnv_qt_dir/bin/uic" + else + # Old versions of Qt don't have uic + QT_UIC= + fi + QT_MOC="$bnv_qt_dir/bin/moc" + else + # Or maybe we are told where to look for the utilities + if test x"$bnv_qt_bin_dir" != x; then + if test -x "$bnv_qt_bin_dir/uic"; then + QT_UIC="$bnv_qt_bin_dir/uic" + else + # Old versions of Qt don't have uic + QT_UIC= + fi + QT_MOC="$bnv_qt_bin_dir/moc" + else + # Last possibility is that they are in $PATH + QT_UIC="`which uic`" + QT_MOC="`which moc`" + fi + fi + # All variables are defined, report the result + AC_MSG_RESULT([$have_qt: + QT_CXXFLAGS=$QT_CXXFLAGS + QT_DIR=$QT_DIR + QT_LIBS=$QT_LIBS + QT_UIC=$QT_UIC + QT_MOC=$QT_MOC]) + else + # Qt was not found + QT_CXXFLAGS= + QT_DIR= + QT_LIBS= + QT_UIC= + QT_MOC= + AC_MSG_RESULT($have_qt) + fi + AC_SUBST(QT_CXXFLAGS) + AC_SUBST(QT_DIR) + AC_SUBST(QT_LIBS) + AC_SUBST(QT_UIC) + AC_SUBST(QT_MOC) + + #### Being paranoid: + if test x"$have_qt" = xyes; then + AC_MSG_CHECKING(correct functioning of Qt installation) + AC_CACHE_VAL(bnv_cv_qt_test_result, + [ + cat > bnv_qt_test.h << EOF +#include +class Test : public QObject +{ +Q_OBJECT +public: + Test() {} + ~Test() {} +public slots: + void receive() {} +signals: + void send(); +}; +EOF + + cat > bnv_qt_main.$ac_ext << EOF +#include "bnv_qt_test.h" +#include +int main( int argc, char **argv ) +{ + QApplication app( argc, argv ); + Test t; + QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) ); +} +EOF + + bnv_cv_qt_test_result="failure" + bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out" + AC_TRY_EVAL(bnv_try_1) + bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"` + if test x"$bnv_err_1" != x; then + echo "$bnv_err_1" >&AC_FD_CC + echo "configure: could not run $QT_MOC on:" >&AC_FD_CC + cat bnv_qt_test.h >&AC_FD_CC + else + bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out" + AC_TRY_EVAL(bnv_try_2) + bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"` + if test x"$bnv_err_2" != x; then + echo "$bnv_err_2" >&AC_FD_CC + echo "configure: could not compile:" >&AC_FD_CC + cat bnv_qt_test.$ac_ext >&AC_FD_CC + else + bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out" + AC_TRY_EVAL(bnv_try_3) + bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"` + if test x"$bnv_err_3" != x; then + echo "$bnv_err_3" >&AC_FD_CC + echo "configure: could not compile:" >&AC_FD_CC + cat bnv_qt_main.$ac_ext >&AC_FD_CC + else + bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out" + AC_TRY_EVAL(bnv_try_4) + bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out` + if test x"$bnv_err_4" != x; then + echo "$bnv_err_4" >&AC_FD_CC + else + bnv_cv_qt_test_result="success" + fi + fi + fi + fi + ])dnl AC_CACHE_VAL bnv_cv_qt_test_result + AC_MSG_RESULT([$bnv_cv_qt_test_result]); + if test x"$bnv_cv_qt_test_result" = "xfailure"; then + # working Qt was not found + QT_CXXFLAGS= + QT_DIR= + QT_LIBS= + QT_UIC= + QT_MOC= + have_qt=no + AC_MSG_WARN([Failed to find matching components of a complete + Qt installation. Try using more options, + see ./configure --help.]) + fi + + rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \ + bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \ + bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out + fi +]) + +dnl Internal subroutine of BNV_HAVE_QT +dnl Set bnv_qt_dir bnv_qt_include_dir bnv_qt_bin_dir bnv_qt_lib_dir bnv_qt_lib +dnl Copyright 2001 Bastiaan N. Veelo +AC_DEFUN([BNV_PATH_QT_DIRECT], +[ + ## Binary utilities ## + if test x"$with_Qt_bin_dir" != x; then + bnv_qt_bin_dir=$with_Qt_bin_dir + fi + ## Look for header files ## + if test x"$with_Qt_include_dir" != x; then + bnv_qt_include_dir="$with_Qt_include_dir" + else + # The following header file is expected to define QT_VERSION. + qt_direct_test_header=qglobal.h + # Look for the header file in a standard set of common directories. + bnv_include_path_list=" + /usr/include + `ls -dr /usr/include/qt* 2>/dev/null` + `ls -dr /usr/lib/qt*/include 2>/dev/null` + `ls -dr /usr/local/qt*/include 2>/dev/null` + `ls -dr /opt/qt*/include 2>/dev/null` + " + for bnv_dir in $bnv_include_path_list; do + if test -r "$bnv_dir/$qt_direct_test_header"; then + bnv_dirs="$bnv_dirs $bnv_dir" + fi + done + # Now look for the newest in this list + bnv_prev_ver=0 + for bnv_dir in $bnv_dirs; do + bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/$qt_direct_test_header | sed s/'#define QT_VERSION'//` + if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then + bnv_qt_include_dir=$bnv_dir + bnv_prev_ver=$bnv_this_ver + fi + done + fi dnl Found header files. + + # Are these headers located in a traditional Trolltech installation? + # That would be $bnv_qt_include_dir stripped from its last element: + bnv_possible_qt_dir=`dirname $bnv_qt_include_dir` + if test -x $bnv_possible_qt_dir/bin/moc && + ls $bnv_possible_qt_dir/lib/libqt* > /dev/null; then + # Then the rest is a piece of cake + bnv_qt_dir=$bnv_possible_qt_dir + bnv_qt_bin_dir="$bnv_qt_dir/bin" + bnv_qt_lib_dir="$bnv_qt_dir/lib" + # Only look for lib if the user did not supply it already + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # There is no valid definition for $QTDIR as Trolltech likes to see it + bnv_qt_dir= + ## Look for Qt library ## + if test x"$with_Qt_lib_dir" != x; then + bnv_qt_lib_dir="$with_Qt_lib_dir" + # Only look for lib if the user did not supply it already + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # Normally, when there is no traditional Trolltech installation, + # the library is installed in a place where the linker finds it + # automatically. + # If the user did not define the library name, try with qt + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib=qt + fi + qt_direct_test_header=qapplication.h + qt_direct_test_main=" + int argc; + char ** argv; + QApplication app(argc,argv); + " + # See if we find the library without any special options. + # Don't add top $LIBS permanently yet + bnv_save_LIBS="$LIBS" + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + bnv_qt_LIBS="$LIBS" + bnv_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="-I$bnv_qt_include_dir" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Success. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Try the multi-threaded version + echo "Non-critical error, please neglect the above." >&AC_FD_CC + bnv_qt_lib=qt-mt + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Success. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Try the OpenGL version + echo "Non-critical error, please neglect the above." >&AC_FD_CC + bnv_qt_lib=qt-gl + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Succes. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Maybe a library version I don't know about? + echo "Non-critical error, please neglect the above." >&AC_FD_CC + # Look for some Qt lib in a standard set of common directories. + bnv_dir_list=" + `echo $bnv_qt_includes | sed ss/includess` + /lib + /usr/lib + /usr/local/lib + /opt/lib + `ls -dr /usr/lib/qt* 2>/dev/null` + `ls -dr /usr/local/qt* 2>/dev/null` + `ls -dr /opt/qt* 2>/dev/null` + " + for bnv_dir in $bnv_dir_list; do + if ls $bnv_dir/libqt*; then + # Gamble that it's the first one... + bnv_qt_lib="`ls $bnv_dir/libqt* | sed -n 1p | + sed s@$bnv_dir/lib@@ | sed s/[.].*//`" + bnv_qt_lib_dir="$bnv_dir" + break + fi + done + # Try with that one + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Succes. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # Leave bnv_qt_lib_dir defined + ]) + ]) + ]) + ]) + if test x"$bnv_qt_lib_dir" != x; then + bnv_qt_LIBS="-l$bnv_qt_lib_dir $LIBS" + else + bnv_qt_LIBS="$LIBS" + fi + LIBS="$bnv_save_LIBS" + CXXFLAGS="$bnv_save_CXXFLAGS" + fi dnl $with_Qt_lib_dir was not given + fi dnl Done setting up for non-traditional Trolltech installation +]) diff --git a/config/cppunit.m4 b/config/cppunit.m4 new file mode 100644 index 00000000..0991d51e --- /dev/null +++ b/config/cppunit.m4 @@ -0,0 +1,80 @@ +dnl +dnl AM_PATH_CPPUNIT(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([AM_PATH_CPPUNIT], +[ + +AC_ARG_WITH(cppunit-prefix,[ --with-cppunit-prefix=PFX Prefix where CppUnit is installed (optional)], + cppunit_config_prefix="$withval", cppunit_config_prefix="") +AC_ARG_WITH(cppunit-exec-prefix,[ --with-cppunit-exec-prefix=PFX Exec prefix where CppUnit is installed (optional)], + cppunit_config_exec_prefix="$withval", cppunit_config_exec_prefix="") + + if test x$cppunit_config_exec_prefix != x ; then + cppunit_config_args="$cppunit_config_args --exec-prefix=$cppunit_config_exec_prefix" + if test x${CPPUNIT_CONFIG+set} != xset ; then + CPPUNIT_CONFIG=$cppunit_config_exec_prefix/bin/cppunit-config + fi + fi + if test x$cppunit_config_prefix != x ; then + cppunit_config_args="$cppunit_config_args --prefix=$cppunit_config_prefix" + if test x${CPPUNIT_CONFIG+set} != xset ; then + CPPUNIT_CONFIG=$cppunit_config_prefix/bin/cppunit-config + fi + fi + + AC_PATH_PROG(CPPUNIT_CONFIG, cppunit-config, no) + cppunit_version_min=$1 + + AC_MSG_CHECKING(for Cppunit - version >= $cppunit_version_min) + no_cppunit="" + if test "$CPPUNIT_CONFIG" = "no" ; then + no_cppunit=yes + else + CPPUNIT_CFLAGS=`$CPPUNIT_CONFIG --cflags` + CPPUNIT_LIBS=`$CPPUNIT_CONFIG --libs` + cppunit_version=`$CPPUNIT_CONFIG --version` + + cppunit_major_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + cppunit_minor_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + cppunit_micro_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + cppunit_major_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + cppunit_minor_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + cppunit_micro_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + cppunit_version_proper=`expr \ + $cppunit_major_version \> $cppunit_major_min \| \ + $cppunit_major_version \= $cppunit_major_min \& \ + $cppunit_minor_version \> $cppunit_minor_min \| \ + $cppunit_major_version \= $cppunit_major_min \& \ + $cppunit_minor_version \= $cppunit_minor_min \& \ + $cppunit_micro_version \>= $cppunit_micro_min ` + + if test "$cppunit_version_proper" = "1" ; then + AC_MSG_RESULT([$cppunit_major_version.$cppunit_minor_version.$cppunit_micro_version]) + else + AC_MSG_RESULT(no) + no_cppunit=yes + fi + fi + + if test "x$no_cppunit" = x ; then + ifelse([$2], , :, [$2]) + else + CPPUNIT_CFLAGS="" + CPPUNIT_LIBS="" + ifelse([$3], , :, [$3]) + fi + + AC_SUBST(CPPUNIT_CFLAGS) + AC_SUBST(CPPUNIT_LIBS) +]) + + + diff --git a/config/gr_as.m4 b/config/gr_as.m4 new file mode 100644 index 00000000..a0695473 --- /dev/null +++ b/config/gr_as.m4 @@ -0,0 +1,34 @@ +# Figure out how to run the assembler. -*- Autoconf -*- + +# serial 2 + +# Copyright 2001 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# I just copy and renamed this from automake-1.6.3 so we should work +# under both 1.4-p6 and later. -eb + +# GR_PROG_AS +# ---------- +AC_DEFUN([GR_PROG_AS], +[# By default we simply use the C compiler to build assembly code. +AC_REQUIRE([AC_PROG_CC]) +: ${CCAS='$(CC)'} +# Set ASFLAGS if not already set. +: ${CCASFLAGS='$(CFLAGS)'} +AC_SUBST(CCAS) +AC_SUBST(CCASFLAGS)]) diff --git a/config/gr_atsc.m4 b/config/gr_atsc.m4 new file mode 100644 index 00000000..e409667a --- /dev/null +++ b/config/gr_atsc.m4 @@ -0,0 +1,36 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_ATSC],[ + AC_CONFIG_SRCDIR([gr-atsc/src/lib/atsc.i]) + + AC_CONFIG_FILES([\ + gr-atsc/Makefile \ + gr-atsc/doc/Makefile \ + gr-atsc/src/Makefile \ + gr-atsc/src/lib/Makefile \ + gr-atsc/src/python/Makefile \ + gr-atsc/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_atsc], [chmod +x gr-atsc/src/python/run_tests]) + + subdirs="$subdirs gr-atsc" +]) diff --git a/config/gr_audio_alsa.m4 b/config/gr_audio_alsa.m4 new file mode 100644 index 00000000..2675ec9c --- /dev/null +++ b/config/gr_audio_alsa.m4 @@ -0,0 +1,41 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_ALSA],[ + AC_CONFIG_SRCDIR([gr-audio-alsa/src/audio_alsa.i]) + + succeeded=yes + PKG_CHECK_MODULES(ALSA, alsa >= 0.9,[],[succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS $ALSA_LIBS" + + AC_CONFIG_FILES([\ + gr-audio-alsa/Makefile \ + gr-audio-alsa/src/Makefile \ + gr-audio-alsa/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_alsa], [chmod +x gr-audio-alsa/src/run_tests]) + subdirs="$subdirs gr-audio-alsa" + else + AC_MSG_RESULT([failed: $ALSA_PKG_ERRORS]) + failed="$failed gr-audio-alsa" + fi +]) diff --git a/config/gr_audio_jack.m4 b/config/gr_audio_jack.m4 new file mode 100644 index 00000000..628ce034 --- /dev/null +++ b/config/gr_audio_jack.m4 @@ -0,0 +1,41 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_JACK],[ + AC_CONFIG_SRCDIR([gr-audio-jack/src/audio_jack.i]) + + succeeded=yes + PKG_CHECK_MODULES(JACK, jack >= 0.8,[],[succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS $JACK_LIBS" + + AC_CONFIG_FILES([\ + gr-audio-jack/Makefile \ + gr-audio-jack/src/Makefile \ + gr-audio-jack/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_jack], [chmod +x gr-audio-jack/src/run_tests]) + subdirs="$subdirs gr-audio-jack" + else + AC_MSG_RESULT([failed: $JACK_PKG_ERRORS]) + failed="$failed gr-audio-jack" + fi +]) diff --git a/config/gr_audio_oss.m4 b/config/gr_audio_oss.m4 new file mode 100644 index 00000000..c8dfebeb --- /dev/null +++ b/config/gr_audio_oss.m4 @@ -0,0 +1,45 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_OSS],[ + AC_CONFIG_SRCDIR([gr-audio-oss/src/audio_oss.i]) + + succeeded=yes + + dnl needed for NetBSD + dnl FIXME: conditionalize on NetBSD platform + dnl AC_HAVE_LIBRARY(ossaudio,[],[succeeded=no]) + + AC_CHECK_HEADER(sys/soundcard.h,[],[succeeded=no]) + if test $succeeded = yes; then + + AC_CONFIG_FILES([\ + gr-audio-oss/Makefile \ + gr-audio-oss/src/Makefile \ + gr-audio-oss/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_oss], [chmod +x gr-audio-oss/src/run_tests]) + subdirs="$subdirs gr-audio-oss" + else + AC_MSG_RESULT([failed: $OSS_PKG_ERRORS]) + failed="$failed gr-audio-oss" + fi +]) diff --git a/config/gr_audio_osx.m4 b/config/gr_audio_osx.m4 new file mode 100644 index 00000000..2ddb4b38 --- /dev/null +++ b/config/gr_audio_osx.m4 @@ -0,0 +1,38 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_OSX],[ + AC_CONFIG_SRCDIR([gr-audio-osx/src/audio_osx.i]) + + succeeded=yes + MACOSX_AUDIOUNIT([],[succeeded=no]) + if test $succeeded = yes; then + AC_CONFIG_FILES([\ + gr-audio-osx/Makefile \ + gr-audio-osx/src/Makefile \ + gr-audio-osx/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_osx], [chmod +x gr-audio-osx/src/run_tests]) + subdirs="$subdirs gr-audio-osx" + else + failed="$failed gr-audio-osx" + fi +]) diff --git a/config/gr_audio_portaudio.m4 b/config/gr_audio_portaudio.m4 new file mode 100644 index 00000000..2ad3719c --- /dev/null +++ b/config/gr_audio_portaudio.m4 @@ -0,0 +1,43 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_PORTAUDIO],[ + AC_CONFIG_SRCDIR([gr-audio-portaudio/src/audio_portaudio.i]) + + succeeded=yes + #PKG_CHECK_MODULES(PORTAUDIO, portaudio-2.0 >= 19,[],[succeeded=no]) + AC_HAVE_LIBRARY([portaudio], [], [succeeded=no]) + AC_CHECK_HEADER([portaudio.h], [], [succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS -lportaudio" + + AC_CONFIG_FILES([\ + gr-audio-portaudio/Makefile \ + gr-audio-portaudio/src/Makefile \ + gr-audio-portaudio/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_portaudio], [chmod +x gr-audio-portaudio/src/run_tests]) + subdirs="$subdirs gr-audio-portaudio" + else + AC_MSG_RESULT([failed: $PORTAUDIO_PKG_ERRORS]) + failed="$failed gr-audio-portaudio" + fi +]) diff --git a/config/gr_audio_windows.m4 b/config/gr_audio_windows.m4 new file mode 100644 index 00000000..d0a445e9 --- /dev/null +++ b/config/gr_audio_windows.m4 @@ -0,0 +1,39 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_WINDOWS],[ + AC_CONFIG_SRCDIR([gr-audio-windows/src/audio_windows.i]) + + succeeded=yes + AC_HAVE_LIBRARY(winmm,[],[succeeded=no]) + + if test $succeeded = yes; then + AC_CONFIG_FILES([\ + gr-audio-windows/Makefile \ + gr-audio-windows/src/Makefile \ + gr-audio-windows/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_windows], [chmod +x gr-audio-windows/src/run_tests]) + subdirs="$subdirs gr-audio-windows" + else + failed="$failed gr-audio-windows" + fi +]) diff --git a/config/gr_boost.m4 b/config/gr_boost.m4 new file mode 100644 index 00000000..b1751c06 --- /dev/null +++ b/config/gr_boost.m4 @@ -0,0 +1,111 @@ +dnl +dnl Copyright 2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl This tries to do the "right thing" to locate the boost include files. +dnl If the user explicitly specified --with-boost-include-dir= +dnl we believe them and use it. Otherwise, +dnl +dnl We look for boost/shared_ptr.hpp in the "normal places". That is, +dnl wherever AC_CHECK_HEADER looks. If the boost includes are in /usr/local/include +dnl this step will find them. +dnl +dnl Otherwise, we check to see if the boost stuff was installed in a version-specific +dnl directory under /usr/local/include. These look like: /usr/local/include/boost-1_33_1 +dnl If there's more than one version installed, we select the +dnl lexicographically greatest one. +dnl +dnl If none of these work, we bail. + +AC_DEFUN([GR_REQUIRE_BOOST_INCLUDES], +[ + AC_LANG_PUSH(C++) + gr_boost_include_dir= + AC_ARG_WITH([boost-include-dir], + AC_HELP_STRING([--with-boost-include-dir=], + [path to boost c++ include files]), + [ + # "yes" and "no" are bogus answers + if test x"$with_boost_include_dir" == xyes || + test x"$with_boost_include_dir" == xno; then + gr_boost_include_dir= + else + gr_boost_include_dir=$with_boost_include_dir + fi + ]) + echo "gr_boost_include_dir = $gr_boost_include_dir" + if test x$gr_boost_include_dir != x; then + # + # If the user specified a directory, then we use it + # + OLD_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -I$gr_boost_include_dir" + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS="-I$gr_boost_include_dir"], + [AC_MSG_ERROR( + [Failed to locate boost/shared_ptr.hpp. +Try using --with-boost-include-dir=, +E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])]) + CPPFLAGS=$OLD_CPPFLAGS + else + # + # Otherwise we check in the default places + # + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS=""], + [ # Nope, look for latest version if any in $prefix/include/boost-* + + # Wipe out cached value. KLUDGE: AC should have API for this + unset AS_TR_SH([ac_cv_header_boost/shared_ptr.hpp]) + + boost_last_match(){ + #echo "boost_last_match: [$]*" + pattern="[$]1" + shift + if test "[$]pattern" = "[$]1" + then + LM='' + else + shift `expr [$]# - 1` + LM=[$]1 + fi + #echo "LM(1)='[$]LM'" + } + + pattern="/usr/local/include/boost-*" + boost_last_match "$pattern" $pattern + #echo "LM(2)='$LM'" + + OLD_CPPFLAGS=$CPP_FLAGS + CPPFLAGS="$CPPFLAGS -I$LM" + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS="-I$LM"], + [AC_MSG_ERROR( + [Failed to locate boost/shared_ptr.hpp. +Try using --with-boost-include-dir=, +E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])]) + CPPFLAGS=$OLD_CPPFLAGS + ]) + + fi + unset boost_last_match LM + AC_LANG_POP + AC_SUBST(BOOST_CFLAGS) +]) diff --git a/config/gr_check_createfilemapping.m4 b/config/gr_check_createfilemapping.m4 new file mode 100644 index 00000000..9cb94f57 --- /dev/null +++ b/config/gr_check_createfilemapping.m4 @@ -0,0 +1,52 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +dnl AC_DEFUN([GR_CHECK_CREATEFILEMAPPING], +dnl [ +dnl AC_CHECK_FUNCS([CreateFileMapping]) +dnl ]) + +AC_DEFUN([GR_CHECK_CREATEFILEMAPPING],[ + AC_MSG_CHECKING([for CreateFileMapping function]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + HANDLE handle; + int size; + char seg_name[[1024]]; + handle = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + size, // buffer size + seg_name); // name of mapping object + return 0; +} +],[HAVE_CREATEFILEMAPPING=yes + AC_DEFINE(HAVE_CREATEFILEMAPPING,[1],[Define if you have the CreateFilemapping function(win32).])], + [HAVE_CREATEFILEMAPPING=no]) + + AC_MSG_RESULT($HAVE_CREATEFILEMAPPING) + AM_CONDITIONAL(HAVE_CREATEFILEMAPPING, test x$HAVE_CREATEFILEMAPPING = xyes) +]) + + diff --git a/config/gr_check_mc4020.m4 b/config/gr_check_mc4020.m4 new file mode 100644 index 00000000..0c4318ef --- /dev/null +++ b/config/gr_check_mc4020.m4 @@ -0,0 +1,37 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_CHECK_MC4020],[ + AC_MSG_CHECKING([for mc4020 A/D driver include file]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + return 0; +} +],[HAVE_MC4020=yes + AC_DEFINE(HAVE_MC4020,[1],[Define if you have a Measurement Computing PCI-DAS4020/12 A/D])], + [HAVE_MC4020=no]) + + AC_MSG_RESULT($HAVE_MC4020) + AM_CONDITIONAL(HAVE_MC4020, test x$HAVE_MC4020 = xyes) +]) + diff --git a/config/gr_check_shm_open.m4 b/config/gr_check_shm_open.m4 new file mode 100644 index 00000000..27c9ee6c --- /dev/null +++ b/config/gr_check_shm_open.m4 @@ -0,0 +1,29 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_CHECK_SHM_OPEN], +[ + SHM_OPEN_LIBS="" + save_LIBS="$LIBS" + AC_SEARCH_LIBS([shm_open], [rt], [SHM_OPEN_LIBS="$LIBS"]) + AC_CHECK_FUNCS([shm_open]) + LIBS="$save_LIBS" + AC_SUBST(SHM_OPEN_LIBS) +]) diff --git a/config/gr_check_usrp.m4 b/config/gr_check_usrp.m4 new file mode 100644 index 00000000..b818a690 --- /dev/null +++ b/config/gr_check_usrp.m4 @@ -0,0 +1,32 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl Check for Universal Software Radio Peripheral + +AC_DEFUN([GR_CHECK_USRP],[ + PKG_CHECK_MODULES(USRP, usrp >= 0.2, + [HAVE_USRP=yes + AC_DEFINE(HAVE_USRP,[1],[Define if you have a USRP])], + [HAVE_USRP=no]) + + AM_CONDITIONAL(HAVE_USRP, test x$HAVE_USRP = xyes) +]) + diff --git a/config/gr_comedi.m4 b/config/gr_comedi.m4 new file mode 100644 index 00000000..89ee30fd --- /dev/null +++ b/config/gr_comedi.m4 @@ -0,0 +1,41 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_COMEDI],[ + AC_CONFIG_SRCDIR([gr-comedi/src/comedi.i]) + + succeeded=yes + PKG_CHECK_MODULES(COMEDI, comedilib >= 0.7,[],[succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS $COMEDI_LIBS" + + AC_CONFIG_FILES([\ + gr-comedi/Makefile \ + gr-comedi/src/Makefile \ + gr-comedi/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_comedi], [chmod +x gr-comedi/src/run_tests]) + subdirs="$subdirs gr-comedi" + else + AC_MSG_WARN([$COMEDI_PKG_ERRORS]) + failed="$failed gr-comedi" + fi +]) diff --git a/config/gr_doxygen.m4 b/config/gr_doxygen.m4 new file mode 100644 index 00000000..82aea350 --- /dev/null +++ b/config/gr_doxygen.m4 @@ -0,0 +1,59 @@ +dnl +dnl Copyright 2003,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_CHECK_DOXYGEN],[ + AC_ARG_ENABLE(doxygen, [ --enable-doxygen enable documentation generation with doxygen (no)]) + AC_ARG_ENABLE(dot, [ --enable-dot use 'dot' to generate graphs in doxygen (auto)]) + AC_ARG_ENABLE(html-docs, [ --enable-html-docs enable HTML generation with doxygen (yes)], [], [ enable_html_docs=yes]) + AC_ARG_ENABLE(latex-docs, [ --enable-latex-docs enable LaTeX doc generation with doxygen (no)], [], [ enable_latex_docs=no]) + + if test "x$enable_doxygen" = xyes; then + AC_PATH_PROG(DOXYGEN, doxygen, , $PATH) + if test x$DOXYGEN = x; then + if test "x$enable_doxygen" = xyes; then + AC_MSG_ERROR([could not find doxygen]) + fi + enable_doc=no + generate_docs= + else + enable_doc=yes + generate_docs=docs + AC_PATH_PROG(DOT, dot, , $PATH) + fi + else + enable_doc=no + fi + + AM_CONDITIONAL(DOC, test x$enable_doc = xyes) + + if test x$DOT = x; then + if test "x$enable_dot" = xyes; then + AC_MSG_ERROR([could not find dot]) + fi + enable_dot=no + else + enable_dot=yes + fi + AC_SUBST(enable_dot) + AC_SUBST(enable_html_docs) + AC_SUBST(enable_latex_docs) + AC_SUBST(generate_docs) +]) diff --git a/config/gr_error_correcting_codes.m4 b/config/gr_error_correcting_codes.m4 new file mode 100644 index 00000000..84d5560e --- /dev/null +++ b/config/gr_error_correcting_codes.m4 @@ -0,0 +1,38 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_ERROR_CORRECTING_CODES],[ + AC_CONFIG_SRCDIR([gr-error-correcting-codes/src/lib/ecc.i]) + + AC_CONFIG_FILES([\ + gr-error-correcting-codes/Makefile \ + gr-error-correcting-codes/src/Makefile \ + gr-error-correcting-codes/src/lib/Makefile \ + gr-error-correcting-codes/src/lib/libecc/Makefile \ + gr-error-correcting-codes/src/lib/libecc/mld/Makefile \ + gr-error-correcting-codes/src/lib/libecc/tests/Makefile \ + gr-error-correcting-codes/src/python/Makefile \ + gr-error-correcting-codes/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_error_correcting_codes], [chmod +x gr-error-correcting-codes/src/python/run_tests]) + + subdirs="$subdirs gr-error-correcting-codes" +]) diff --git a/config/gr_fortran.m4 b/config/gr_fortran.m4 new file mode 100644 index 00000000..345936fa --- /dev/null +++ b/config/gr_fortran.m4 @@ -0,0 +1,31 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_FORTRAN],[ + dnl if you want to generate a different table of interpolator taps, you need fortran. + dnl we default to off, since almost no one wants to do this. + AC_ARG_ENABLE(fortran, [ --enable-fortran enable fortran (no)], [], [enable_fortran=no]) + AM_CONDITIONAL(ENABLE_FORTRAN, test "x$enable_fortran" = xyes) + + if test "x$enable_fortran" = xyes + then + AC_PROG_F77 + AC_F77_LIBRARY_LDFLAGS + fi +]) diff --git a/config/gr_gnuradio_core.m4 b/config/gr_gnuradio_core.m4 new file mode 100644 index 00000000..661555ea --- /dev/null +++ b/config/gr_gnuradio_core.m4 @@ -0,0 +1,63 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_GNURADIO_CORE],[ + AC_CONFIG_SRCDIR([gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc]) + + AC_CONFIG_FILES([ \ + gnuradio-core/Makefile + gnuradio-core/gnuradio-core.pc \ + gnuradio-core/doc/Doxyfile \ + gnuradio-core/doc/Makefile \ + gnuradio-core/doc/other/Makefile \ + gnuradio-core/doc/xml/Makefile \ + gnuradio-core/src/Makefile \ + gnuradio-core/src/gen_interpolator_taps/Makefile \ + gnuradio-core/src/lib/Makefile \ + gnuradio-core/src/lib/filter/Makefile \ + gnuradio-core/src/lib/g72x/Makefile \ + gnuradio-core/src/lib/general/Makefile \ + gnuradio-core/src/lib/general/gr_prefix.cc \ + gnuradio-core/src/lib/io/Makefile \ + gnuradio-core/src/lib/missing/Makefile \ + gnuradio-core/src/lib/omnithread/Makefile \ + gnuradio-core/src/lib/reed-solomon/Makefile \ + gnuradio-core/src/lib/runtime/Makefile \ + gnuradio-core/src/lib/swig/Makefile \ + gnuradio-core/src/python/Makefile \ + gnuradio-core/src/python/bin/Makefile \ + gnuradio-core/src/python/gnuradio/Makefile \ + gnuradio-core/src/python/gnuradio/blks/Makefile \ + gnuradio-core/src/python/gnuradio/blksimpl/Makefile \ + gnuradio-core/src/python/gnuradio/gr/Makefile \ + gnuradio-core/src/python/gnuradio/gr/run_tests \ + gnuradio-core/src/python/gnuradio/gru/Makefile \ + gnuradio-core/src/python/gnuradio/gruimpl/Makefile \ + gnuradio-core/src/tests/Makefile \ + gnuradio-core/src/utils/Makefile \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_core], [chmod +x gnuradio-core/src/python/gnuradio/gr/run_tests]) + + dnl kludge up initial swig dependency file + AC_CONFIG_COMMANDS([swig_deps], [touch gnuradio-core/src/lib/swig/gnuradio_swig_python.d]) + + subdirs="$subdirs gnuradio-core" +]) diff --git a/config/gr_gnuradio_examples.m4 b/config/gr_gnuradio_examples.m4 new file mode 100644 index 00000000..6ab51a20 --- /dev/null +++ b/config/gr_gnuradio_examples.m4 @@ -0,0 +1,35 @@ +# Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_GNURADIO_EXAMPLES],[ + AC_CONFIG_SRCDIR([gnuradio-examples/README]) + + AC_CONFIG_FILES([\ + gnuradio-examples/Makefile \ + gnuradio-examples/python/Makefile \ + gnuradio-examples/python/audio/Makefile \ + gnuradio-examples/python/digital_voice/Makefile \ + gnuradio-examples/python/gmsk2/Makefile \ + gnuradio-examples/python/mc4020/Makefile \ + gnuradio-examples/python/usrp/Makefile \ + gnuradio-examples/python/multi_usrp/Makefile \ + ]) + + subdirs="$subdirs gnuradio-examples" +]) diff --git a/config/gr_gprof.m4 b/config/gr_gprof.m4 new file mode 100644 index 00000000..cc505088 --- /dev/null +++ b/config/gr_gprof.m4 @@ -0,0 +1,72 @@ +dnl +dnl Copyright 2002 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl FIXME probably need to add linker flag too... + +AC_DEFUN([GR_SET_GPROF],[ + dnl Check for --with-gprof + AC_MSG_CHECKING([whether user wants gprof]) + AC_ARG_WITH(gprof, + [ --with-gprof Turn on gprof profiling], + [], [ with_gprof=no ]) + AC_MSG_RESULT($with_gprof) + + dnl gprof profiling flags for the two main compilers + cc_profiling_flags="-pg" + cxx_profiling_flags="-pg" + ld_profiling_flags="-pg" + if test $with_gprof = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_profiling_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_profiling_flags) + fi + fi +]) + +AC_DEFUN([GR_SET_PROF],[ + dnl Check for --with-prof + AC_MSG_CHECKING([whether user wants prof]) + AC_ARG_WITH(prof, + [ --with-prof Turn on prof profiling], + [], [ with_prof=no ]) + AC_MSG_RESULT($with_prof) + + dnl prof profiling flags for the two main compilers + cc_profiling_flags="-p" + cxx_profiling_flags="-p" + ld_profiling_flags="-p" + if test $with_prof = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_profiling_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_profiling_flags) + fi + fi +]) diff --git a/config/gr_gsm_fr_vocoder.m4 b/config/gr_gsm_fr_vocoder.m4 new file mode 100644 index 00000000..97408e9d --- /dev/null +++ b/config/gr_gsm_fr_vocoder.m4 @@ -0,0 +1,36 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_GSM_FR_VOCODER],[ + AC_CONFIG_SRCDIR([gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i]) + + AC_CONFIG_FILES([\ + gr-gsm-fr-vocoder/Makefile \ + gr-gsm-fr-vocoder/src/Makefile \ + gr-gsm-fr-vocoder/src/lib/Makefile \ + gr-gsm-fr-vocoder/src/lib/gsm/Makefile \ + gr-gsm-fr-vocoder/src/python/Makefile \ + gr-gsm-fr-vocoder/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_gsm], [chmod +x gr-gsm-fr-vocoder/src/python/run_tests]) + + subdirs="$subdirs gr-gsm-fr-vocoder" +]) diff --git a/config/gr_libgnuradio_core_extra_ldflags.m4 b/config/gr_libgnuradio_core_extra_ldflags.m4 new file mode 100644 index 00000000..491f7a04 --- /dev/null +++ b/config/gr_libgnuradio_core_extra_ldflags.m4 @@ -0,0 +1,40 @@ +# Check for (MinGW)win32 extra ld options. -*- Autoconf -*- + +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +dnl +AC_DEFUN([GR_LIBGNURADIO_CORE_EXTRA_LDFLAGS], [ +AC_REQUIRE([AC_PROG_LD]) +# on Mingw32 extra LDFLAGS are required to ease global variable linking +LIBGNURADIO_CORE_EXTRA_LDFLAGS="" + +AC_MSG_CHECKING([whether $LD accepts --enable-runtime-pseudo-reloc]) +if ${LD} --enable-runtime-pseudo-reloc --version >/dev/null 2>&1 +then + # libtool requires the quotes + LIBGNURADIO_CORE_EXTRA_LDFLAGS="\"-Wl,--enable-runtime-pseudo-reloc\"" + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_SUBST(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +]) diff --git a/config/gr_no_undefined.m4 b/config/gr_no_undefined.m4 new file mode 100644 index 00000000..8780fab3 --- /dev/null +++ b/config/gr_no_undefined.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# GR_NO_UNDEFINED() +# +# Detemine whether we need to use the -no-undefined linker flag +# when building shared libraries. +# Sets NO_UNDEFINED to "" or "-no-undefined" +# +# As far as I can tell, we need -no-undefined only when building +# windows DLLs. This occurs when using MinGW and Cygwin. +# +# For now, we stub this out. + +AC_DEFUN([GR_NO_UNDEFINED],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + no_undefined="" + case "${host_os}" in + *mingw* | *cygwin*) + + # on MinGW/Cygwin extra LDFLAGS are required + no_undefined="-no-undefined" + ;; + esac + AC_SUBST(NO_UNDEFINED,[$no_undefined]) +]) diff --git a/config/gr_omnithread.m4 b/config/gr_omnithread.m4 new file mode 100644 index 00000000..7c3150ba --- /dev/null +++ b/config/gr_omnithread.m4 @@ -0,0 +1,51 @@ +# Check for Omnithread (pthread/NT) thread support. -*- Autoconf -*- + +# Copyright 2003 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([GR_OMNITHREAD], +[ + # Check first for POSIX + ACX_PTHREAD( + [ ot_posix="yes" + AC_DEFINE(OMNITHREAD_POSIX,[1],[Define to 1 to enable pthread]) + ],[ + # If no POSIX support found, then check for NT threads + AC_MSG_CHECKING([for NT threads]) + + AC_LINK_IFELSE([ + #include + #include + int main() { InitializeCriticalSection(NULL); return 0; } + ], + [ + ot_nt="yes" + AC_DEFINE(OMNITHREAD_NT,[1],[Define to 1 to enable NT thread]) + ], + [AC_MSG_FAILURE([GNU Radio requires POSIX threads. pthreads not found.])] + ) + AC_MSG_RESULT(yes) + ]) + AM_CONDITIONAL(OMNITHREAD_POSIX, test "x$ot_posix" = xyes) + AM_CONDITIONAL(OMNITHREAD_NT, test "x$ot_nt" = xyes) + + save_LIBS="$LIBS" + AC_SEARCH_LIBS([clock_gettime], [rt], [PTHREAD_LIBS="$PTHREAD_LIBS $LIBS"]) + AC_CHECK_FUNCS([clock_gettime gettimeofday nanosleep]) + LIBS="$save_LIBS" +]) + diff --git a/config/gr_pmt.m4 b/config/gr_pmt.m4 new file mode 100644 index 00000000..573f07dc --- /dev/null +++ b/config/gr_pmt.m4 @@ -0,0 +1,34 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_PMT],[ + AC_CONFIG_SRCDIR([pmt/src/lib/pmt.h]) + + AC_CONFIG_FILES([\ + pmt/Makefile \ + pmt/doc/Makefile \ + pmt/src/Makefile \ + pmt/src/lib/Makefile + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + dnl AC_CONFIG_COMMANDS([run_tests_pmt], [chmod +x pmt/src/python/run_tests]) + + subdirs="$subdirs pmt" +]) diff --git a/config/gr_pwin32.m4 b/config/gr_pwin32.m4 new file mode 100644 index 00000000..5f748afc --- /dev/null +++ b/config/gr_pwin32.m4 @@ -0,0 +1,146 @@ +# Check for (mingw)win32 POSIX replacements. -*- Autoconf -*- + +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + + +AC_DEFUN([GR_PWIN32], +[ +AC_REQUIRE([AC_HEADER_TIME]) +AC_CHECK_HEADERS([sys/types.h fcntl.h io.h]) +AC_CHECK_HEADERS([windows.h]) +AC_CHECK_HEADERS([winioctl.h winbase.h], [], [], [ + #if HAVE_WINDOWS_H + #include + #endif +]) + +AC_CHECK_FUNCS([getopt usleep gettimeofday nanosleep rand srand random srandom sleep sigaction]) +AC_CHECK_TYPES([struct timezone, struct timespec, ssize_t],[],[],[ + #if HAVE_SYS_TYPES_H + # include + #endif + #if TIME_WITH_SYS_TIME + # include + # include + #else + # if HAVE_SYS_TIME_H + # include + # else + # include + # endif + #endif +]) + +dnl Checks for replacements +AC_REPLACE_FUNCS([getopt usleep gettimeofday]) + + +AC_MSG_CHECKING(for Sleep) +AC_TRY_LINK([ #include + #include + ], [ Sleep(0); ], + [AC_DEFINE(HAVE_SSLEEP,1,[Define to 1 if you have win32 Sleep]) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no) + ) + +dnl Under Win32, mkdir prototype in io.h has only one arg +AC_MSG_CHECKING(whether mkdir accepts only one arg) +AC_TRY_COMPILE([#include + #include + #include ], [ + mkdir("") + ], [ AC_MSG_RESULT(yes) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ], + [ AC_MSG_RESULT(no) + ]) + +AH_BOTTOM( +[ +/* Define missing prototypes, implemented in replacement lib */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HAVE_GETOPT +int getopt (int argc, char * const argv[], const char * optstring); +extern char * optarg; +extern int optind, opterr, optopt; +#endif + +#ifndef HAVE_USLEEP +int usleep(unsigned long usec); /* SUSv2 */ +#endif + +#ifndef HAVE_NANOSLEEP +#ifndef HAVE_STRUCT_TIMESPEC +#if HAVE_SYS_TYPES_H +# include /* need time_t */ +#endif +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +static inline int nanosleep(const struct timespec *req, struct timespec *rem) { return usleep(req->tv_sec*1000000+req->tv_nsec/1000); } +#endif + +#if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP) +#ifdef HAVE_WINBASE_H +#include +#include +#endif +/* TODO: what about SleepEx? */ +static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; } +#endif + +#ifndef HAVE_GETTIMEOFDAY +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifndef HAVE_STRUCT_TIMEZONE +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; +#endif +int gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + +#if !defined(HAVE_RANDOM) && defined(HAVE_RAND) +#include +static inline long int random (void) { return rand(); } +#endif + +#if !defined(HAVE_SRANDOM) && defined(HAVE_SRAND) +static inline void srandom (unsigned int seed) { srand(seed); } +#endif + +#ifndef HAVE_SSIZE_T +typedef size_t ssize_t; +#endif + +#ifdef __cplusplus +} +#endif +]) + + +]) diff --git a/config/gr_python.m4 b/config/gr_python.m4 new file mode 100644 index 00000000..760a0f74 --- /dev/null +++ b/config/gr_python.m4 @@ -0,0 +1,116 @@ +dnl +dnl Copyright 2003,2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# PYTHON_DEVEL() +# +# Checks for Python and tries to get the include path to 'Python.h'. +# It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) output variables. +# +AC_DEFUN([PYTHON_DEVEL],[ + AC_REQUIRE([AM_PATH_PYTHON]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + # Check for Python include path + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON" ; then + AC_MSG_ERROR([cannot find Python path]) + fi + + # ask distutils which include path we should use + python_cmd=' +import distutils.sysconfig +import os +path = distutils.sysconfig.get_python_inc(plat_specific=False) +if os.sep == "\\": + path = path.replace("\\", "/") +print path +' + python_path=`$PYTHON -c "$python_cmd"` + AC_MSG_RESULT([$python_path]) + if test -z "$python_path" ; then + AC_MSG_ERROR([cannot find Python include path]) + fi + + AC_SUBST(PYTHON_CPPFLAGS,[-I$python_path]) + + # Check for Python headers usability + python_save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" + AC_CHECK_HEADERS([Python.h], [], + [AC_MSG_ERROR([cannot find usable Python headers])]) + CPPFLAGS="$python_save_CPPFLAGS" + + # Only set this on mingw and cygwin hosts, (only implemented + # for mingw host, for crosscompiling you need to trick this) + + PYTHON_LDFLAGS="" + case $host_os in + *mingw* | *cygwin* ) + AC_MSG_CHECKING([for Python LDFLAGS]) + + python_cmd=' +import distutils.sysconfig +import os +path = distutils.sysconfig.get_config_var("LIBPL") +if path == None: + path = distutils.sysconfig.PREFIX + "/libs" +if os.sep == "\\": + path = path.replace("\\", "/") +print path +' + python_stdlib_path=`$PYTHON -c "$python_cmd"` + + python_version_nodot=`echo $PYTHON_VERSION | sed "s,\.,,"` + libpython_name="python$PYTHON_VERSION" + + # Standard install of python for win32 has libpython24.a + # instead of libpython2.4.a so we check for the library + # without the dot in the version number. + + python_stdlib_filename=`find $python_stdlib_path -type f -name libpython$python_version_nodot.* -print | sed "1q"` + if test -n "$python_stdlib_filename" ; then + libpython_name="python$python_version_nodot" + fi + + PYTHON_LDFLAGS="-L$python_stdlib_path -l$libpython_name" + AC_MSG_RESULT($PYTHON_LDFLAGS) + # Replace all backslashes in PYTHON Paths with forward slashes + AC_MSG_CHECKING([for pythondir]) + pythondir=`echo $pythondir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pythondir) + AC_SUBST([pythondir]) + AC_MSG_CHECKING([for pkgpythondir]) + pkgpythondir=`echo $pkgpythondir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pkgpythondir) + AC_SUBST([pkgpythondir]) + AC_MSG_CHECKING([for pyexecdir]) + pyexecdir=`echo $pyexecdir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pyexecdir) + AC_SUBST([pyexecdir]) + AC_MSG_CHECKING([for pkgpyexecdir]) + pkgpyexecdir=`echo $pkgpyexecdir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pkgpyexecdir) + AC_SUBST([pkgpyexecdir]) + ;; + esac + + AC_SUBST([PYTHON_LDFLAGS]) +]) diff --git a/config/gr_radar.m4 b/config/gr_radar.m4 new file mode 100644 index 00000000..b9a42d65 --- /dev/null +++ b/config/gr_radar.m4 @@ -0,0 +1,36 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_RADAR],[ + AC_CONFIG_SRCDIR([gr-radar/src/python/usrp_rx_radar.py]) + + AC_CONFIG_FILES([\ + gr-radar/Makefile \ + gr-radar/doc/Makefile \ + gr-radar/src/Makefile \ + gr-radar/src/lib/Makefile \ + gr-radar/src/python/Makefile \ + gr-radar/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_radar], [chmod +x gr-radar/src/python/run_tests]) + + subdirs="$subdirs gr-radar" +]) diff --git a/config/gr_radio_astronomy.m4 b/config/gr_radio_astronomy.m4 new file mode 100644 index 00000000..db0ca61f --- /dev/null +++ b/config/gr_radio_astronomy.m4 @@ -0,0 +1,35 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_RADIO_ASTRONOMY],[ + AC_CONFIG_SRCDIR([gr-radio-astronomy/src/lib/ra.i]) + + AC_CONFIG_FILES([\ + gr-radio-astronomy/Makefile \ + gr-radio-astronomy/src/Makefile \ + gr-radio-astronomy/src/lib/Makefile \ + gr-radio-astronomy/src/python/Makefile \ + gr-radio-astronomy/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_astronomy], [chmod +x gr-radio-astronomy/src/python/run_tests]) + + subdirs="$subdirs gr-radio-astronomy" +]) diff --git a/config/gr_require_mc4020.m4 b/config/gr_require_mc4020.m4 new file mode 100644 index 00000000..8a03eeb6 --- /dev/null +++ b/config/gr_require_mc4020.m4 @@ -0,0 +1,33 @@ +dnl +dnl Copyright 2003,2004 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_REQUIRE_MC4020],[ + AC_MSG_CHECKING([for mc4020 A/D driver include file]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + return 0; +} +],[AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([mc4020.h not found.])]) +]) diff --git a/config/gr_scripting.m4 b/config/gr_scripting.m4 new file mode 100644 index 00000000..7f3abdee --- /dev/null +++ b/config/gr_scripting.m4 @@ -0,0 +1,30 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_SCRIPTING],[ + AC_REQUIRE([AC_PROG_LN_S]) + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PROG_LIBTOOL]) + + SWIG_PROG(1.3.23) + SWIG_ENABLE_CXX + SWIG_PYTHON +]) diff --git a/config/gr_set_md_cpu.m4 b/config/gr_set_md_cpu.m4 new file mode 100644 index 00000000..1bb2f341 --- /dev/null +++ b/config/gr_set_md_cpu.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_SET_MD_CPU],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_ARG_WITH(md-cpu, + [ --with-md-cpu=ARCH set machine dependent speedups (auto)], + [cf_with_md_cpu="$withval"], + [cf_with_md_cpu="$host_cpu"]) + + AC_MSG_CHECKING([for machine dependent speedups]) + case "$cf_with_md_cpu" in + x86 | i[[3-7]]86) MD_CPU=x86 MD_SUBCPU=x86 ;; + x86_64) MD_CPU=x86 MD_SUBCPU=x86_64 ;; +# sparc) MD_CPU=sparc ;; + *) MD_CPU=generic ;; + esac + AC_MSG_RESULT($MD_CPU) + AC_SUBST(MD_CPU) + AC_SUBST(MD_SUBCPU) + + AM_CONDITIONAL(MD_CPU_x86, test $MD_CPU = x86) + AM_CONDITIONAL(MD_SUBCPU_x86_64, test $MD_SUBCPU = x86_64) + AM_CONDITIONAL(MD_CPU_generic, test $MD_CPU = generic) +]) + diff --git a/config/gr_swig.m4 b/config/gr_swig.m4 new file mode 100644 index 00000000..a587c6df --- /dev/null +++ b/config/gr_swig.m4 @@ -0,0 +1,85 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# SWIG_PROG([required-version]) +# +# Checks for the SWIG program. If found you can (and should) call SWIG via $(SWIG). +# You can use the optional first argument to check if the version of the available SWIG +# is greater or equal to the value of the argument. It should have the format: +# N[.N[.N]] (N is a number between 0 and 999. Only the first N is mandatory.) +AC_DEFUN([SWIG_PROG],[ + AC_REQUIRE([AC_PROG_MAKE_SET]) + AC_CHECK_PROG(SWIG,swig,[`which swig`]) + if test -z "$SWIG" ; then + AC_MSG_ERROR([Cannot find 'swig' program. SWIG version >= $1 required]) + SWIG=false + elif test -n "$1" ; then + AC_MSG_CHECKING([for SWIG version]) + swig_version=`$SWIG -version 2>&1 | \ + awk '/^SWIG Version [[0-9]+\.[0-9]+\.[0-9]]+.*$/ { split($[3],a,"[[^.0-9]]"); print a[[1]] }'` + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + swig_version=`echo $swig_version | \ + awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null` + swig_required_version=`echo $1 | \ + awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null` + if test $swig_required_version -gt $swig_version ; then + AC_MSG_ERROR([SWIG version >= $1 required]) + fi + else + AC_MSG_ERROR([cannot determine SWIG version]) + fi + fi +]) + +# SWIG_ENABLE_CXX() +# +# Enable swig C++ support. This effects all invocations of $(SWIG). +AC_DEFUN([SWIG_ENABLE_CXX],[ + AC_REQUIRE([SWIG_PROG]) + AC_REQUIRE([AC_PROG_CXX]) + if test "$SWIG" != "false" ; then + SWIG="$SWIG -c++" + fi +]) + +# SWIG_PYTHON([use-shadow-classes]) +# +# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS), +# $(SWIG_PYTHON_LIB) and $(SWIG_PYTHON_OPT) output variables. +# $(SWIG_PYTHON_OPT) contains all necessary swig options to generate +# code for Python. If you need multi module support use +# $(SWIG_PYTHON_LIB) (provided by the SWIG_MULTI_MODULE_SUPPORT() +# macro) to link against the appropriate library. It contains the +# SWIG Python runtime library that is needed by the type check system +# for example. + +AC_DEFUN([SWIG_PYTHON],[ + AC_REQUIRE([SWIG_PROG]) + AC_REQUIRE([PYTHON_DEVEL]) + if test "$SWIG" != "false" ; then + AC_SUBST(SWIG_PYTHON_LIB,[-lswigpy]) +dnl test ! "x$1" = "xno" && swig_shadow=" -shadow" || swig_shadow="" +dnl AC_SUBST(SWIG_PYTHON_OPT,[-python$swig_shadow]) + AC_SUBST(SWIG_PYTHON_OPT,[-python]) + fi + AC_SUBST(SWIG_PYTHON_CPPFLAGS,[$PYTHON_CPPFLAGS]) +]) diff --git a/config/gr_sysv_shm.m4 b/config/gr_sysv_shm.m4 new file mode 100644 index 00000000..5e11e496 --- /dev/null +++ b/config/gr_sysv_shm.m4 @@ -0,0 +1,36 @@ +# Check for IPC System V shm support. -*- Autoconf -*- + +# Copyright 2003 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([GR_SYSV_SHM], +[ + AC_LANG_SAVE + AC_LANG_C + + AC_CHECK_HEADERS([sys/ipc.h sys/shm.h]) + + save_LIBS="$LIBS" + AC_SEARCH_LIBS(shmat, [cygipc ipc], + [ IPC_LIBS="$LIBS" ], + [ AC_MSG_WARN([SystemV IPC support not found. ]) ] + ) + LIBS="$save_LIBS" + + AC_LANG_RESTORE + AC_SUBST(IPC_LIBS) +]) diff --git a/config/gr_usrp.m4 b/config/gr_usrp.m4 new file mode 100644 index 00000000..a51d77ca --- /dev/null +++ b/config/gr_usrp.m4 @@ -0,0 +1,113 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_USRP_HW],[ + AC_CONFIG_SRCDIR([usrp/host/lib/usrp_prims.h]) + + AC_CHECK_PROG([XMLTO],[xmlto],[yes],[]) + AM_CONDITIONAL(HAS_XMLTO, test x$XMLTO = xyes) + + # gnulib. + # FIXME: this needs to fail gracefully and continue, not implemented yet + UTILS_FUNC_MKSTEMP + + succeeded=yes + dnl Checks for library functions. + USRP_LIBUSB([],[succeeded=no]) + USRP_SET_FUSB_TECHNIQUE([],[succeeded=no]) + + dnl check for firmware cross compilation tools + dnl check for SDCC 2.4.0 + USRP_SDCC([2.4.0],[],[succeeded=no]) + + AC_CHECK_FUNCS([getrusage sched_setscheduler],[],[succeeded=no]) + AC_CHECK_FUNCS([sigaction snprintf],[],[succeeded=no]) + + dnl we use these to handle possible byteswapping to and from the USRP. + AC_CHECK_HEADERS([byteswap.h],[],[succeeeded=no]) + AC_C_BIGENDIAN + + if test $succeeded = yes; then + dnl Define where to look for USRP includes + USRP_INCLUDES='-I$(top_srcdir)/host/lib -I$(top_srcdir)/firmware/include' + AC_SUBST(USRP_INCLUDES) + + USRP_DEFINES='' + AC_SUBST(USRP_DEFINES) + + DEFINES="$USRP_DEFINES" + AC_SUBST(DEFINES) + + AC_CONFIG_FILES([ \ + usrp/Makefile \ + usrp/usrp.pc \ + usrp/usrp.iss \ + usrp/doc/Doxyfile \ + usrp/doc/Makefile \ + usrp/doc/other/Makefile \ + usrp/host/Makefile \ + usrp/host/misc/Makefile \ + usrp/host/lib/Makefile \ + usrp/host/lib/std_paths.h \ + usrp/host/swig/Makefile \ + usrp/host/apps/Makefile \ + usrp/firmware/Makefile \ + usrp/firmware/include/Makefile \ + usrp/firmware/lib/Makefile \ + usrp/firmware/src/Makefile \ + usrp/firmware/src/common/Makefile \ + usrp/firmware/src/usrp2/Makefile \ + usrp/fpga/Makefile \ + usrp/fpga/rbf/Makefile \ + ]) + + subdirs="$subdirs usrp" + else + failed="$failed usrp" + fi +]) + +AC_DEFUN([GR_USRP],[ + AC_CONFIG_SRCDIR([gr-usrp/src/usrp1.i]) + + # Don't do gr-usrp if usrp failed + # There *has* to be a better way to check if a value is in a string + succeeded=yes + for dir in $failed + do + if test $dir = usrp; then + succeeded=no + fi + done + + if test $succeeded = yes; then + AC_CONFIG_FILES([\ + gr-usrp/Makefile \ + gr-usrp/src/Makefile \ + gr-usrp/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_usrp], [chmod +x gr-usrp/src/run_tests]) + + subdirs="$subdirs gr-usrp" + else + failed="$failed gr-usrp" + fi +]) diff --git a/config/gr_video_sdl.m4 b/config/gr_video_sdl.m4 new file mode 100644 index 00000000..2f524986 --- /dev/null +++ b/config/gr_video_sdl.m4 @@ -0,0 +1,45 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_VIDEO_SDL],[ + AC_CONFIG_SRCDIR([gr-video-sdl/src/video_sdl.i]) + + succeeded=yes + + dnl Check for SDL + SDL_VERSION=1.2.0 + AM_PATH_SDL($SDL_VERSION,[],[succeeded=no]) + + if test $succeeded = yes; then + AM_CFLAGS="$AM_CFLAGS $SDL_CFLAGS" + AM_LDFLAGS="$AM_LDFLAGS $SDL_LIBS" + + AC_CONFIG_FILES([\ + gr-video-sdl/Makefile \ + gr-video-sdl/src/Makefile \ + gr-video-sdl/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_sdl], [chmod +x gr-video-sdl/src/run_tests]) + subdirs="$subdirs gr-video-sdl" + else + failed="$failed gr-video-sdl" + fi +]) diff --git a/config/gr_wxgui.m4 b/config/gr_wxgui.m4 new file mode 100644 index 00000000..4ff56509 --- /dev/null +++ b/config/gr_wxgui.m4 @@ -0,0 +1,33 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_WXGUI],[ + AC_CONFIG_SRCDIR([gr-wxgui/src/python/stdgui.py]) + + # FIXME: Should we actually check for wxPython, even though + # this is a runtime requirement, not a compile/install time one? + + AC_CONFIG_FILES([ \ + gr-wxgui/Makefile \ + gr-wxgui/src/Makefile \ + gr-wxgui/src/python/Makefile \ + ]) + + subdirs="$subdirs gr-wxgui" +]) diff --git a/config/gr_x86_64.m4 b/config/gr_x86_64.m4 new file mode 100644 index 00000000..3d6f5eae --- /dev/null +++ b/config/gr_x86_64.m4 @@ -0,0 +1,39 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# GR_X86_64() +# +# Checks to see if we're on a x86_64 machine, and if so, ensure +# that libdir ends in "64" +# +AC_DEFUN([GR_X86_64],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + if test "$host_cpu" = "x86_64"; then + AC_MSG_CHECKING([libdir for lib64 suffix]) + t=${libdir##*/lib} + if test "$t" != 64 && test -d /lib64 && ! test -L /lib64; then + libdir=${libdir}64 + AC_MSG_RESULT([no. Setting libdir to $libdir]) + else + AC_MSG_RESULT([yes]) + fi + fi +]) diff --git a/config/lf_cc.m4 b/config/lf_cc.m4 new file mode 100644 index 00000000..f9bd7155 --- /dev/null +++ b/config/lf_cc.m4 @@ -0,0 +1,42 @@ +dnl Autoconf support for C++ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# ------------------------------------------------------------------------- +# Use this macro to configure your C compiler +# When called the macro does the following things: +# 1. It finds an appropriate C compiler. +# If you passed the flag --with-cc=foo then it uses that +# particular compiler +# 2. Check whether the compiler works. +# 3. Checks whether the compiler accepts the -g +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CONFIGURE_CC],[ + dnl Sing the song + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_CPP])dnl + AC_REQUIRE([AC_AIX])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_MINIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl +]) + diff --git a/config/lf_cxx.m4 b/config/lf_cxx.m4 new file mode 100644 index 00000000..8ade1fb2 --- /dev/null +++ b/config/lf_cxx.m4 @@ -0,0 +1,121 @@ +dnl Autoconf support for C++ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# ----------------------------------------------------------------- +# This macro should be called to configure your C++ compiler. +# When called, the macro does the following things: +# 1. It finds an appropriate C++ compiler +# If you passed the flag --with-cxx=foo, then it uses that +# particular compiler +# 2. Checks whether the compiler accepts the -g +# ------------------------------------------------------------------ + +AC_DEFUN([LF_CONFIGURE_CXX],[ + AC_REQUIRE([AC_PROG_CXX])dnl + AC_REQUIRE([AC_PROG_CXXCPP])dnl + LF_CXX_PORTABILITY +]) + +# ----------------------------------------------------------------------- +# This macro tests the C++ compiler for various portability problem. +# 1. Defines CXX_HAS_NO_BOOL if the compiler does not support the bool +# data type +# 2. Defines CXX_HAS_BUGGY_FOR_LOOPS if the compiler has buggy +# scoping for the for-loop +# 3. Defines USE_ASSERT if the user wants to use assertions +# ----------------------------------------------------------------------- + + +AC_DEFUN([LF_CXX_PORTABILITY],[ + + dnl + dnl Check for common C++ portability problems + dnl + + dnl AC_LANG_PUSH + dnl AC_LANG_CPLUSPLUS + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + dnl Check whether we have bool + AC_MSG_CHECKING(whether C++ has bool) + AC_TRY_RUN([main() { bool b1=true; bool b2=false; }], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + AC_DEFINE(CXX_HAS_NO_BOOL,[],[Define if C++ is missing bool type]) ], + [ AC_MSG_WARN(Don't cross-compile)] + ) + + dnl Test whether C++ has buggy for-loops + AC_MSG_CHECKING(whether C++ has buggy scoping in for-loops) + AC_TRY_COMPILE([#include ], [ + for (int i=0;i<10;i++) { } + for (int i=0;i<10;i++) { } +], [ AC_MSG_RESULT(no) ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(CXX_HAS_BUGGY_FOR_LOOPS,[],[Define if for loop scoping is broken]) ]) + + dnl Test whether the user wants to enable assertions + AC_MSG_CHECKING(whether user wants assertions) + AC_ARG_ENABLE(assert, + [ --disable-assert don't use cpp.h assert], + [ AC_DEFINE(NDEBUG,[],[Define to disable asserts (don't doit!)]) + AC_MSG_RESULT(no) ], + [ AC_MSG_RESULT(yes) ], + ) + + dnl Test whether C++ has std::isnan + AC_MSG_CHECKING(whether C++ has std::isnan) + AC_TRY_COMPILE([#include ], [ + std::isnan(0); +], [ AC_MSG_RESULT(yes) + AC_DEFINE(CXX_HAS_STD_ISNAN,[],[Define if has std::isnan]) ], + [ AC_MSG_RESULT(no) ]) + + dnl Done with the portability checks + dnl AC_LANG_POP([C++]) + AC_LANG_RESTORE +]) + +AH_BOTTOM([// Workaround for compilers with buggy for-loop scoping +// That's quite a few compilers actually including recent versions of +// Dec Alpha cxx, HP-UX CC and SGI CC. +// The trivial "if" statement provides the correct scoping to the +// for loop + +#ifdef CXX_HAS_BUGGY_FOR_LOOPS +#undef for +#define for if(1) for +#endif +]) + +AH_BOTTOM([// If the C++ compiler we use doesn't have bool, then +// the following is a near-perfect work-around. +// You must make sure your code does not depend on "int" and "bool" +// being two different types, in overloading for instance. + +#ifdef CXX_HAS_NO_BOOL +#define bool int +#define true 1 +#define false 0 +#endif +]) diff --git a/config/lf_warnings.m4 b/config/lf_warnings.m4 new file mode 100644 index 00000000..0ebb97ef --- /dev/null +++ b/config/lf_warnings.m4 @@ -0,0 +1,128 @@ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# -------------------------------------------------------------------------- +# Check whether the C++ compiler accepts a certain flag +# If it does it adds the flag to CXXFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_CXX_FLAG],[ + echo 'void f(){}' > conftest.cc + for i in $1 + do + AC_MSG_CHECKING([whether $CXX accepts $i]) + if test -z "`${CXX} $i -c conftest.cc 2>&1`" + then + CXXFLAGS="${CXXFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.cc conftest.o +]) + +# -------------------------------------------------------------------------- +# Check whether the C compiler accepts a certain flag +# If it does it adds the flag to CFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_CC_FLAG],[ + echo 'void f(){}' > conftest.c + for i in $1 + do + AC_MSG_CHECKING([whether $CC accepts $i]) + if test -z "`${CC} $i -c conftest.c 2>&1`" + then + CFLAGS="${CFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.c conftest.o +]) + +# -------------------------------------------------------------------------- +# Check whether the Fortran compiler accepts a certain flag +# If it does it adds the flag to FFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_F77_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_F77_FLAG],[ + cat << EOF > conftest.f +c....:++++++++++++++++++++++++ + PROGRAM MAIN + PRINT*,'Hello World!' + END +EOF + for i in $1 + do + AC_MSG_CHECKING([whether $F77 accepts $i]) + if test -z "`${F77} $i -c conftest.f 2>&1`" + then + FFLAGS="${FFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.f conftest.o +]) + +# ---------------------------------------------------------------------- +# Provide the configure script with an --with-warnings option that +# turns on warnings. Call this command AFTER you have configured ALL your +# compilers. +# ---------------------------------------------------------------------- + +AC_DEFUN([LF_SET_WARNINGS],[ + dnl Check for --with-warnings + AC_MSG_CHECKING([whether user wants warnings]) + AC_ARG_WITH(warnings, + [ --with-warnings Turn on warnings], + [ lf_warnings=yes ], [ lf_warnings=no ]) + lf_warnings=yes # hard code for now -eb + AC_MSG_RESULT($lf_warnings) + + dnl Warnings for the two main compilers + cc_warning_flags="-Wall" + cxx_warning_flags="-Wall -Woverloaded-virtual" + if test $lf_warnings = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_warning_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_warning_flags) + fi + fi +]) diff --git a/config/lf_x11.m4 b/config/lf_x11.m4 new file mode 100644 index 00000000..3bd19f24 --- /dev/null +++ b/config/lf_x11.m4 @@ -0,0 +1,39 @@ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + + +#----------------------------------------------------------------------- +# This macro searches for Xlib and when it finds it it adds the +# appropriate flags to CXXFLAGS and export the link sequence to +# the variable XLIB. +# In your configure.in file add: +# LF_PATH_XLIB +# In your Makefile.am add +# program_LDADD = .... $(XLIB) +#------------------------------------------------------------------------ + +AC_DEFUN([LF_PATH_XLIB],[ + AC_PATH_XTRA + CXXFLAGS="$CXXFLAGS $X_CFLAGS" + XLIB="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" + AC_SUBST(XLIB) +]) + diff --git a/config/macosx_audiounit.m4 b/config/macosx_audiounit.m4 new file mode 100644 index 00000000..313feb3b --- /dev/null +++ b/config/macosx_audiounit.m4 @@ -0,0 +1,49 @@ +# Copyright 2006 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([MACOSX_AUDIOUNIT], +[ + audiounitok=yes + case "$host_os" in + darwin*);; + *) + audiounitok=no + AC_MSG_WARN([gr-audio-osx requires darwin or MacOS X.]) + esac + + AC_CHECK_HEADERS([AudioUnit/AudioUnit.h], + [], + [ + audiounitok=no, + AC_MSG_WARN([gr-audio-osx requires AudioUnit/AudioUnit.h, which is available on MacOS X.]) + ] + ) + + AC_CHECK_HEADERS([AudioToolbox/AudioToolbox.h], + [], + [ + audiounitok=no, + AC_MSG_WARN([gr-audio-osx requires AudioToolbox/AudioToolbox.h, which is available on MacOS X.]) + ] + ) + + if test $audiounitok = yes; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) diff --git a/config/mkstemp.m4 b/config/mkstemp.m4 new file mode 100644 index 00000000..4af0f0a9 --- /dev/null +++ b/config/mkstemp.m4 @@ -0,0 +1,89 @@ +#serial 4 + +# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a +# silly limit that it can create no more than 26 files from a given template. +# Other systems lack mkstemp altogether. +# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create +# only 32 files per process. +# On systems like the above, arrange to use the replacement function. +AC_DEFUN([UTILS_FUNC_MKSTEMP], +[dnl + AC_REPLACE_FUNCS(mkstemp) + if test $ac_cv_func_mkstemp = no; then + utils_cv_func_mkstemp_limitations=yes + else + AC_CACHE_CHECK([for mkstemp limitations], + utils_cv_func_mkstemp_limitations, + [ + AC_TRY_RUN([ +# include + int main () + { + int i; + for (i = 0; i < 70; i++) + { + char template[] = "conftestXXXXXX"; + int fd = mkstemp (template); + if (fd == -1) + exit (1); + close (fd); + } + exit (0); + } + ], + utils_cv_func_mkstemp_limitations=no, + utils_cv_func_mkstemp_limitations=yes, + utils_cv_func_mkstemp_limitations=yes + ) + ] + ) + fi + + if test $utils_cv_func_mkstemp_limitations = yes; then + AC_LIBOBJ(mkstemp) + AC_LIBOBJ(tempname) + AC_DEFINE(mkstemp, rpl_mkstemp, + [Define to rpl_mkstemp if the replacement function should be used.]) + gl_PREREQ_MKSTEMP + jm_PREREQ_TEMPNAME + fi +]) + +# Prerequisites of lib/mkstemp.c. +AC_DEFUN([gl_PREREQ_MKSTEMP], +[ + AH_BOTTOM( + [ + #ifndef HAVE_MKSTEMP + #ifdef __cplusplus + extern "C" { + #endif + int rpl_mkstemp (char *templ); + #ifdef __cplusplus + } + #endif + #endif + ]) +]) + +# Prerequisites of lib/tempname.c. +AC_DEFUN([jm_PREREQ_TEMPNAME], +[ + AC_REQUIRE([AC_HEADER_STAT]) + AC_CHECK_HEADERS_ONCE(fcntl.h sys/time.h unistd.h) + AC_CHECK_HEADERS(stdint.h) + AC_CHECK_FUNCS(__secure_getenv gettimeofday lstat) + AC_CHECK_DECLS_ONCE(getenv) + # AC_REQUIRE([jm_AC_TYPE_UINTMAX_T]) + + dnl Under Win32, mkdir prototype in io.h has only one arg + AC_MSG_CHECKING(whether mkdir accepts only one arg) + AC_TRY_COMPILE([#include + #include + #include ], [ + mkdir("") + ], [ AC_MSG_RESULT(yes) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ], + [ AC_MSG_RESULT(no) + ]) +]) diff --git a/config/onceonly.m4 b/config/onceonly.m4 new file mode 100644 index 00000000..f6fec37c --- /dev/null +++ b/config/onceonly.m4 @@ -0,0 +1,63 @@ +# onceonly.m4 serial 3 +dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl This file defines some "once only" variants of standard autoconf macros. +dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS +dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS +dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS +dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC +dnl The advantage is that the check for each of the headers/functions/decls +dnl will be put only once into the 'configure' file. It keeps the size of +dnl the 'configure' file down, and avoids redundant output when 'configure' +dnl is run. +dnl The drawback is that the checks cannot be conditionalized. If you write +dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi +dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to +dnl empty, and the check will be inserted before the body of the AC_DEFUNed +dnl function. + +dnl Autoconf version 2.57 or newer is recommended. +AC_PREREQ(2.54) + +# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of +# AC_CHECK_HEADERS(HEADER1 HEADER2 ...). +AC_DEFUN([AC_CHECK_HEADERS_ONCE], [ + : + AC_FOREACH([gl_HEADER_NAME], [$1], [ + AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(defn([gl_HEADER_NAME]), + [-./], [___])), [ + AC_CHECK_HEADERS(gl_HEADER_NAME) + ]) + AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, + [-./], [___]))) + ]) +]) + +# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of +# AC_CHECK_FUNCS(FUNC1 FUNC2 ...). +AC_DEFUN([AC_CHECK_FUNCS_ONCE], [ + : + AC_FOREACH([gl_FUNC_NAME], [$1], [ + AC_DEFUN([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]), [ + AC_CHECK_FUNCS(defn([gl_FUNC_NAME])) + ]) + AC_REQUIRE([gl_CHECK_FUNC_]defn([gl_FUNC_NAME])) + ]) +]) + +# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of +# AC_CHECK_DECLS(DECL1, DECL2, ...). +AC_DEFUN([AC_CHECK_DECLS_ONCE], [ + : + AC_FOREACH([gl_DECL_NAME], [$1], [ + AC_DEFUN([gl_CHECK_DECL_]defn([gl_DECL_NAME]), [ + AC_CHECK_DECLS(defn([gl_DECL_NAME])) + ]) + AC_REQUIRE([gl_CHECK_DECL_]defn([gl_DECL_NAME])) + ]) +]) diff --git a/config/pkg.m4 b/config/pkg.m4 new file mode 100644 index 00000000..770f0629 --- /dev/null +++ b/config/pkg.m4 @@ -0,0 +1,68 @@ +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN([PKG_CHECK_MODULES], [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + dnl If PKG_CONFIG_PATH is not already set, add /usr/local/lib/pkgconfig. + dnl If it's set, assume the user knows what they're doing. + dnl This should help avoid failures while looking for fftw3f + if test -z "$PKG_CONFIG_PATH"; then + export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" + fi + + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + + AC_MSG_CHECKING($1_INCLUDEDIR) + $1_INCLUDEDIR=`$PKG_CONFIG --variable=includedir "$2"` + AC_MSG_RESULT($$1_INCLUDEDIR) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + AC_SUBST($1_INCLUDEDIR) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + diff --git a/config/sdl.m4 b/config/sdl.m4 new file mode 100644 index 00000000..ada3a416 --- /dev/null +++ b/config/sdl.m4 @@ -0,0 +1,175 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN([AM_PATH_SDL], +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_REQUIRE([AC_CANONICAL_TARGET]) + PATH="$prefix/bin:$prefix/usr/bin:$PATH" + AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH]) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/config/usrp_fusb_tech.m4 b/config/usrp_fusb_tech.m4 new file mode 100644 index 00000000..78b5af55 --- /dev/null +++ b/config/usrp_fusb_tech.m4 @@ -0,0 +1,55 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[ + AC_ARG_WITH(fusb-tech, + [ --with-fusb-tech=OS set fast usb technique (auto)], + [cf_with_fusb_tech="$withval"], + [cf_with_fusb_tech="$host_os"]) + + + AC_CHECK_HEADER([linux/usbdevice_fs.h], + [x_have_usbdevice_fs_h=yes], + [x_have_usbdevice_fs_h=no]) + + AC_MSG_CHECKING([for fast usb technique to use]) + case "$cf_with_fusb_tech" in + linux*) if test x${x_have_usbdevice_fs_h} = xyes; + then + FUSB_TECH=linux + else + FUSB_TECH=generic + fi ;; + + darwin*) FUSB_TECH=darwin ;; + cygwin*|win*|mingw*) FUSB_TECH=win32 ;; + *) FUSB_TECH=generic ;; + esac + + AC_MSG_RESULT($FUSB_TECH) + AC_SUBST(FUSB_TECH) + + AM_CONDITIONAL(FUSB_TECH_darwin, test $FUSB_TECH = darwin) + AM_CONDITIONAL(FUSB_TECH_win32, test $FUSB_TECH = win32) + AM_CONDITIONAL(FUSB_TECH_generic, test $FUSB_TECH = generic) + AM_CONDITIONAL(FUSB_TECH_linux, test $FUSB_TECH = linux) +]) + diff --git a/config/usrp_libusb.m4 b/config/usrp_libusb.m4 new file mode 100644 index 00000000..9f670144 --- /dev/null +++ b/config/usrp_libusb.m4 @@ -0,0 +1,51 @@ +# Check for libusb support. -*- Autoconf -*- + +# Copyright 2003 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([USRP_LIBUSB], +[ + AC_LANG_PUSH(C) + + libusbok=yes + AC_CHECK_HEADERS([usb.h], + [], + [libusbok=no, + AC_MSG_RESULT([USRP requires libusb. usb.h not found. See http://libusb.sf.net])] + ) + + save_LIBS="$LIBS" + case "$host_os" in + darwin*) LIBS="$LIBS -lIOKit" ;; + *) ;; + esac + AC_SEARCH_LIBS(usb_bulk_write, [usb], + [USB_LIBS="$LIBS"], + [libusbok=no, + AC_MSG_RESULT([USRP requires libusb. usb_bulk_write not found. See http://libusb.sf.net])] + ) + LIBS="$save_LIBS" + + AC_LANG_POP + + if test $libusbok = yes; then + AC_SUBST(USB_LIBS) + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) diff --git a/config/usrp_sdcc.m4 b/config/usrp_sdcc.m4 new file mode 100644 index 00000000..eaf7fdd5 --- /dev/null +++ b/config/usrp_sdcc.m4 @@ -0,0 +1,75 @@ +# Check for sdcc support. -*- Autoconf -*- + +# Copyright 2004 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([USRP_SDCC], +[ + sdccok=yes + AC_CHECK_PROG(XCC, sdcc, sdcc -mmcs51 --no-xinit-opt,no) + AC_CHECK_PROG(XAS, asx8051, asx8051 -plosgff,no) + + if test "$XCC" = "no" -o "$XAS" = "no" ; then + AC_MSG_RESULT([USRP requires sdcc. sdcc not found. See http://sdcc.sf.net]) + sdccok=no + else + sdcc_version_min=$1 + + sdcc_version=`sdcc --version 2>&1 | \ + sed 's/\(SDCC.* \)\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\)\( .*$\)/\2/'` + + AC_MSG_CHECKING([sdcc_version "$sdcc_version"]) + + sdcc_major_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdcc_minor_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdcc_micro_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + sdcc_major_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdcc_minor_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdcc_micro_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + sdcc_version_proper=`expr \ + "$sdcc_major_version" \> "$sdcc_major_min" \| \ + "$sdcc_major_version" \= "$sdcc_major_min" \& \ + "$sdcc_minor_version" \> "$sdcc_minor_min" \| \ + "$sdcc_major_version" \= "$sdcc_major_min" \& \ + "$sdcc_minor_version" \= "$sdcc_minor_min" \& \ + "$sdcc_micro_version" \>= "$sdcc_micro_min" ` + + if test "$sdcc_version_proper" = "1" ; then + AC_MSG_RESULT([$sdcc_major_version.$sdcc_minor_version.$sdcc_micro_version]) + else + sdccok=no + AC_MSG_RESULT([USRP requires sdcc >= $sdcc_version_min. sdcc not found. See http://sdcc.sf.net"]) + fi + + AC_SUBST(XCC) + AC_SUBST(XAS) + fi + + if test $sdccok = yes; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , :, [$3]) + fi +]) diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..410567fc --- /dev/null +++ b/configure.ac @@ -0,0 +1,200 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_INIT +AC_PREREQ(2.57) +AM_CONFIG_HEADER(config.h) +AC_CANONICAL_HOST +AC_CANONICAL_TARGET([]) +AM_INIT_AUTOMAKE(gnuradio,2.8svn) + +GR_X86_64 dnl check for lib64 suffix +LF_CONFIGURE_CC +LF_CONFIGURE_CXX +LF_SET_WARNINGS +GR_SET_GPROF +GR_SET_PROF +GR_PROG_AS +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_INSTALL + +AC_LIBTOOL_WIN32_DLL +dnl AC_DISABLE_SHARED dnl don't build shared libraries +AC_ENABLE_SHARED dnl do build shared libraries +AC_DISABLE_STATIC dnl don't build static libraries +AC_PROG_LIBTOOL +GR_FORTRAN + +GR_NO_UNDEFINED dnl do we need the -no-undefined linker flag +GR_SCRIPTING + +dnl Checks for libraries. +AC_CHECK_LIB(socket,socket) + +dnl check for threads (mandatory) +GR_OMNITHREAD + +CFLAGS="${CFLAGS} $PTHREAD_CFLAGS" +CXXFLAGS="${CXXFLAGS} $PTHREAD_CFLAGS" + +if test "x$CXX_FOR_BUILD" = x +then + CXX_FOR_BUILD=${CXX} +fi +AC_SUBST(CXX_FOR_BUILD) + +dnl Check for SysV shm (mandatory) +dnl FIXME this is no longer mandatory. Check the macro. +GR_SYSV_SHM + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h limits.h strings.h time.h sys/ioctl.h sys/time.h unistd.h) +AC_CHECK_HEADERS(linux/ppdev.h sys/mman.h sys/select.h sys/types.h) +AC_CHECK_HEADERS(sys/resource.h stdint.h sched.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_C_BIGENDIAN + +dnl Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_SETVBUF_REVERSED +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([mmap select socket strcspn strerror strspn getpagesize sysconf]) +AC_CHECK_FUNCS([snprintf gettimeofday nanosleep sched_setscheduler]) + +AC_CHECK_LIB(m, sincos, [AC_DEFINE([HAVE_SINCOS],[1],[Define to 1 if your system has `sincos'.])]) +AC_CHECK_LIB(m, sincosf,[AC_DEFINE([HAVE_SINCOSF],[1],[Define to 1 if your system has `sincosf'.])]) +AC_CHECK_LIB(m, sinf, [AC_DEFINE([HAVE_SINF],[1],[Define to 1 if your system has `sinf'.])]) +AC_CHECK_LIB(m, cosf, [AC_DEFINE([HAVE_COSF],[1],[Define to 1 if your system has `cosf'.])]) +AC_CHECK_LIB(m, trunc, [AC_DEFINE([HAVE_TRUNC],[1],[Define to 1 if your system has `trunc'.])]) +AH_BOTTOM([ +#ifndef HAVE_TRUNC +#include +inline static double trunc(double x) +{ + return x >= 0 ? floor(x) : ceil(x); +} +#endif +]) + +GR_CHECK_SHM_OPEN +GR_LIBGNURADIO_CORE_EXTRA_LDFLAGS +GR_CHECK_CREATEFILEMAPPING + +dnl Check for Mingw support +GR_PWIN32 + +dnl Do we have "dot", part of the graphviz package from AT&T? +dnl Doxgen will use it to draw pretty diagrams ;-) +AC_CHECK_PROG(HAVE_DOT, [dot],[YES],[NO]) + +PKG_CHECK_MODULES(FFTW3F, fftw3f >= 3.0) +AC_SUBST(FFTW3F_LIBS) + +dnl conditional build stuff +GR_CHECK_DOXYGEN +GR_SET_MD_CPU + +dnl Define where to look for GNURADIO includes +GNURADIO_INCLUDES='-I$(top_srcdir)/gnuradio-core/src/lib/runtime -I$(top_srcdir)/gnuradio-core/src/lib/general -I$(top_srcdir)/gnuradio-core/src/lib/filter -I$(top_srcdir)/gnuradio-core/src/lib/io -I$(top_srcdir)/gnuradio-core/src/lib/g72x -I$(top_srcdir)/gnuradio-core/src/lib/atsc -I$(top_srcdir)/gnuradio-core/src/lib/omnithread -I$(top_builddir)/gnuradio-core/src/lib/general -I$(top_builddir)/gnuradio-core/src/lib/filter -I$(top_builddir)/gnuradio-core/src/lib/reed-solomon -I$(top_builddir)/gnuradio-core/src/lib/swig $(FFTW3F_CFLAGS)' +AC_SUBST(GNURADIO_INCLUDES) + +dnl Define where to look for cppunit includes and libs +dnl sets CPPUNIT_CFLAGS and CPPUNIT_LIBS +AM_PATH_CPPUNIT([1.9.14],[], + [AC_MSG_ERROR([GNU Radio requires cppunit. Stop])]) + +CPPUNIT_INCLUDES=$CPPUNIT_CFLAGS +AC_SUBST(CPPUNIT_INCLUDES) + +dnl Define where to find boost includes +dnl defines BOOST_CFLAGS +GR_REQUIRE_BOOST_INCLUDES + +DEFINES="" +AC_SUBST(DEFINES) + +STD_DEFINES_AND_INCLUDES="$DEFINES $GNURADIO_INCLUDES $BOOST_CFLAGS" +AC_SUBST(STD_DEFINES_AND_INCLUDES) + +dnl Component specific configuration +dnl The order of the GR_ macros determines the order of compilation +subdirs="config" +GR_GNURADIO_CORE +GR_GNURADIO_EXAMPLES +GR_USRP_HW +GR_USRP dnl this must come after GR_USRP_HW +GR_AUDIO_ALSA +GR_AUDIO_JACK +GR_AUDIO_OSS +#GR_AUDIO_PORTAUDIO dnl Disabled until portaudio patch figured out +GR_AUDIO_OSX dnl ***NOT TESTED*** +GR_AUDIO_WINDOWS dnl ***NOT TESTED*** +GR_ATSC +GR_COMEDI +#GR_ERROR_CORRECTING_CODES dnl Disabled until compile error fixed from CVS +GR_GSM_FR_VOCODER +GR_RADAR +GR_RADIO_ASTRONOMY +GR_PMT +GR_VIDEO_SDL +GR_WXGUI + +dnl Has list of successfully configured components +AC_SUBST([subdirs],$subdirs) + +AC_CONFIG_FILES([\ + Makefile \ + config/Makefile +]) + +AC_OUTPUT + +echo +echo "*******************************************************************" +echo The following GNU Radio components have been successfully configured: +echo +for dir in $subdirs +do + echo $dir +done +echo +if test "$failed" != ""; then + echo However, the following components did not configure successfully due to + echo missing dependencies: + echo + for dir in $failed + do + echo $dir + done + echo + echo You may still run the 'make' command to build the successfully configured + echo components. + echo + exit 1 +fi +echo You my now run the 'make' command to build these packages. +echo diff --git a/docs/COPYING b/docs/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/docs/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/docs/ChangeLog b/docs/ChangeLog new file mode 100644 index 00000000..f63303f1 --- /dev/null +++ b/docs/ChangeLog @@ -0,0 +1,24 @@ +2004-11-29 Eric Blossom + + * exploring-gnuradio/exploring-gnuradio.xml: new. revision 1.1 + +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/docs/exploring-gnuradio/Makefile b/docs/exploring-gnuradio/Makefile new file mode 100644 index 00000000..837c2c63 --- /dev/null +++ b/docs/exploring-gnuradio/Makefile @@ -0,0 +1,30 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +TARGETS = exploring-gnuradio.html + +all: $(TARGETS) + +clean: + -rm -f $(TARGETS) + +%.html : %.xml + xmlto html-nochunks $< diff --git a/docs/exploring-gnuradio/ddc.eps b/docs/exploring-gnuradio/ddc.eps new file mode 100644 index 00000000..8931a16a --- /dev/null +++ b/docs/exploring-gnuradio/ddc.eps @@ -0,0 +1,3105 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000010008000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000300FE001800C100000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000701CF001800C300000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000F03830018000300000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000003F03000018000300000000000 +%00000000000000001F800000000000031800000000000000000000000000780000000000000000 +%000000000000000000000000000000000000000000F00019C03000000000000000000000000000 +%0000000007303000019E0CFC0000000000 +%00000000000000007FE00000000000031800000000000000C00000000000F80000000000000000 +%000000000000000000000000000000000000000001E00019C03000000000000000000000000000 +%000000000030638001FF0C7C0000000000 +%000000000000000060700000000000030000000000000000C00000000000C00000000000000000 +%000000000000000000000000000000000000000003000019E03000000000000000000000000000 +%0000000000307FE001C38C300000000000 +%0000000000000000E0380000000000030000000000000000C00000000000C00000000000000000 +%000000000000000000000000000000000000000003000031F03000000000000000000000000000 +%000000000030787001C18C300000000000 +%0000000000000000E0000C04202002030842002100110181F01000000001F02000000000000000 +%000000000000000000000000000000000000000007C08031B03000000000000000000000000000 +%000000000030703001818C300000000000 +%0000000000000000E0007F86FDF87FC3187FC0FF803F8FF1F8FE001FFC03F9FC00000000000000 +%00000000000000000000000000000000000000000FE7F031B83000000000000000000000000000 +%0000000000307033F181CC300000000000 +%00000000000000007C00E3879FBC78C31879C1CF803F9C70E1C7001FFC00C38E00000000000000 +%0000000000000000000000000000000000000000030E38219C3000000000000000000000000000 +%0000000000307033F981CC300000000000 +%00000000000000003FC0C1C70E0C70631860E30780381838C38300000000C30600000000000000 +%0000000000000000000000000000000000000000030C18618C3000000000000000000000000000 +%00000000003070300181CC300000000000 +%000000000000000007E000C60E0C60631860630380380038C30180000000C30000000000000000 +%0000000000000000000000000000000000000000030C00618E3000000000000000000000000000 +%000000000030303001818C300000000000 +%000000000000000000F001C60E0C60731860670380380038C30380000000C3C000000000000000 +%0000000000000000000000000000000000000000030F804187300001B6DBFFFB6DB00000000000 +%000000000030303001C18C300000000000 +%000000000000000000383FC60E0C60331860670380380FF8C3FF801FFC00C1FC00000000000000 +%00000000000000000000000000000000000000000307F041833000000000000000000000000000 +%0000000000301C6001E30C300000000000 +%0000000000000001C018F8C60E0C60731860670380381E38C300001FFC00C03E00000000000000 +%00000000000000000000000000000000000000000300F8C183B000000000000000000000000000 +%0000000000300FC001FF0C3C0000000000 +%0000000000000001C019C0C60E0C60731860670380383838C30000000000C00700000000000000 +%000000000000000000000000000000000000000003001CC181F000000000000000000000000000 +%0000000000300780019C0C1C0000000000 +%0000000000000000E039C1C60E0C70631860630380383038C30180000000C30700000000000000 +%0000000000000000000000000000000000000000030C0C8180F000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000F071C1C60E0C70E31860638780383078E38380000000C30600000000000000 +%0000000000000000000000000000000000000000030C1D8180F000000000000000080000000000 +%0000000000000000000000000000000000 +%00000000000000007FE0E7C60E0C7FC3186061FF80381CF8F9FF00000000C3DE00000000000000 +%00000000000000000000000000000000000000000307F981807000000000000000040000000000 +%0000000000000000000000000000000000 +%00000000000000001FC07CC60E0C7F83186060FB80380F98787C00000000C0FC00000000000000 +%00000000000000000000000000000000000000000303F181803000000000000000020000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000000300000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000030300000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000038700000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000006000000001FE00000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000007800000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000008000000000 +%0008000000000000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000004000000000 +%000C000180000060000018000000001000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000004000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%03DC1F87E1F001F87E0019E01F00F87E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000001000000000 +%0FFC7FC7C7FC00F0FF001FF83FC3FC7C00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%1C3C60C38E0C0061C3801C1870E30E3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000001000000000 +%181C60E38C0C006181801C1CE063043000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000800000000 +%181C00E3800C006300C0181CC033803000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%381C0FE381FC006300C0181CC033F03000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000400000000 +%380C7FE387FC006300C0181CC030FC3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%181C60E38E0C006300C0181CC0300E3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%181CC0E38C0C006381C0181CC072063000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%1C1CC0E38C1C00618180181C6067063800 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0E3CE1E38E3C0071C380181C70E38E3800 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000100000000 +%07FC7F61E7EC0078FF00181C3FC1FC1E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000100000000 +%01881C60E3C600383C0018080F00F00E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000080000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000080000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000040000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000040000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000020000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000020000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C01803C03FC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C0180FF03FF00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C0181E7C38F80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000C018301C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000008000000 +%000000000000000C018300C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000004000000 +%00000603307E000C0183000301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000070330FF800C0183C0030180000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000002000000 +%0000030631C1800C0181FC030380000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000002000000 +%000003063181800C01807F03FF00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000001863001800C018007C3FF80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000001000000 +%0000018C303F800C018001C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000018C30FD800C018000E300C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000800000 +%000000DC31C1800C018600E300E0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000800000 +%000000D83181800E038700E300E0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000F83183800E038380C300C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000400000 +%0000007031C78007FF03FF83FFC0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000007030FD8003FE00FF03FF80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000203070800070003C03FC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000200000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000100000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000040000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000020000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000010000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000010000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000004000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000004000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000002600 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000003E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000003FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000001FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000020000000000000000000000000000000000000000000010000000FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000007E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000003E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000001E00 +%0000000000000000000000000000000000 +%000007000000000004003C00000000000000000000000000000000000F00000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000001E00 +%0000000000000000000000000000000000 +%00000700000000000C007C00000000000000000000000000000000007FE0000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000E00 +%0000000000000000000000000000000000 +%00000700000000000C00600000000000000000000000000000000007FFFE000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000600 +%0000000000000000000000000000000000 +%00000700000000000C0060000000000000000000000000000000001F801F800000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000200 +%0000000000000000000000000000000000 +%00000719E06F03033F01FCDC1E06787800000000000000000000007C0003E00000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071FF87FC3031F01F8FC7F87FDFC0000000000000000000000F80001F00000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071E1870E3030C0060E0E1C78F0C0000000000000000000001C00000380000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C1C6063030C0060C0C0E7060E00000000000000000000038000001C0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C0C6063030C0060C18067060E00000000000000000000078000000E0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E000000000000000000000CC000001B0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000018600000318000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000018300000618000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063070C0060C1C067060E0000000000000000000030180000C0C000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C60E3070C0060C0C0C7060E00000000000000000000300C000180C000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C71C38F0C0060C0E1C7060E0000000000000000000060060003006000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C7F81FB0F0060C07F87060E0000000000000000000040030006002000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000006180C6700F3070060C01E07060600000000000000000000C001800C003000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000000C000C01C003000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000001C0006038003800000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000601C0003070003800000000000000 +%000000000000000000700200000000000000000000000000000000000000000000100000000000 +%0000000060000001800000000000000000 +%00000000006000000000000000000000000000000000000007E1800018E0001800000000000000 +%0000000000000000007F0200000000000000000000000000000000000000000000100000000000 +%000000007E000001800000000000000000 +%00000000000000000000000000000000000000000000000007FD80000DC0001800000000000000 +%0000000000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC00001800000000000000000 +%00000000000000000000000000000000000000000000000007FF80000780001800000000000000 +%0000000000000000007FFA00000003FF0000000060000000000300000000000000100000000000 +%000000007FF00001800000000000000000 +%0000000000000000000000000000000000000000000000000FFF80000700001C00000000000000 +%0000000000000000007FFA00000003FF800000006000000000C300000000000000100000000000 +%00000000FFF00001800000000000000000 +%00000000000000000000000000000000000000000000000007FD80000780001800000000000000 +%0000000000000000007FC20000000301C00000000000000000C000000000000000100000000000 +%000000007FC00001800000000000000000 +%00000000000000000000000000000000000000000000000007F180000DC0001800000000000000 +%0000000000000000007F020000000300E00000000000000000C000000000000000100000000000 +%000000007E000001800000000000000000 +%00000000000001007F0000200000000000000000000000000601800018E0001800000000000000 +%00000000000000000070020000000300601800404210100301E200400420000000100000000000 +%0000000060000001800000000000000000 +%00000000000003807FF003FC0000000000000000000000000001C0003070003800000000000000 +%00000000000000000000020000000300707F03F8637EFC1FE3F31BF03F60000000100000000000 +%0000000000000001800000000000000000 +%00000000000007807FF807FF0000000000000000000000000001C0006038003800000000000000 +%0000000000000000000002000000030030E7871C63CFDE1CF0C31F3879E0000000100000000000 +%0000000000000001800000000000000000 +%00000000000006C0601C0E070000000000000000000000000000C000C018003000000000000000 +%000000000000000000000200000003003181860C6387063030C31C1C60E0000000100000000000 +%0000000000000000000000000000000000 +%00000000000006C0600C1C038000000000000000000000000000C001800C003000000000000000 +%000000000000000000000200000003003181CC006307060030C31C1CE060000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600E18018000000000000000000000000000C0030006003000000000000000 +%000000000000000000000200000003003381CC006303060070C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C6060063800000000000000000000000000000040060003002000000000000000 +%0000000000000000000002000000030033FFCC006303060FF0C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%0000000000001C70600638000000000000000000000000000000600C0001806000000000000000 +%0000000000000000000002000000030073800C006303063E30C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%000000000000183060063800000000000000000000000000000020180000C04000000000000000 +%0000000000000000000002000000030063800C006303063030C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%00000000000018306006380000000000000000000000000000003070000060C000000000000000 +%00000000000000000000020000000300E1818E0E6303063030C3181C60E0000000100000000000 +%0000000000000000000000000000000000 +%000000000000383860063800000000000000000000000000000038E0000031C000000000000000 +%00000000000000000000020000000301C1C1860C6303063070C3181C60E0000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF86006180000000000000000000000000000001CC000001B8000000000000000 +%000000000000000000000200000003FFC0FF87BC63030639F0F3181C3FE0000000100000000000 +%0000000000000000000000000000000000 +%000000000000301C600E180180000000000000000000000000000F8000000F0000000000000000 +%000000000000000000000200000003FF007E01F06303061FB873181C1F60000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C600C1C038000000000000000000000000000070000000E0000000000000000 +%000000000000000000000200000000000000000000000000000000000060000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C601C0E038000000000000000000000000000038000001C0000000000000000 +%000000000000000000000200000000000000000000000000000000004060000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E6078078F000000000000000000000000000001E00000780000000000000000 +%0000000000000000000002000000000000000000000000000000000061C0000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FF003FE000000000000000000000000000000F80001F00000000000000000 +%000000000000000000000200000000000000000000000000000000003F80000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FC000F00000000000000000000000000000003E0007C00000000000000000 +%000000000000000000000200000000000000000000000000000000000F00000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000007F07E000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000003FFFC000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000007FE0000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C000000000007FE0000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C000000000007FF8000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C00000000000701C000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C00000000000701C000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C000E040C080700C0700E00C0000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C003F860C180700C3FC3F83F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000001F00000000000000000000 +%00000000000000000000020000000000C0071C61E180700C71E31C738000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000001F80000000000000000000 +%00000000000000000000020000000000C00E0E61E180701C60660C61C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003F80000000000000000000 +%00000000000000000000020000000000C00C0631E3007FF8006700600000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003FC0000000000000000000 +%00000000000000000000020000000000C00C0731B3007FF000E3C0780000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C0733330070003FE1F83F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C071B360070007C607C07C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C061B3600700060600E01C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C061E1E007000E0E606C0C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00E0E1E1E007000E0E70E60C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000FFC7FC0E1C00700077E3FC7F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000FFC1F00E1C0070003E61F83F0000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%C00000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007000000000000003C0000000000000000000000000000000000040000000000000000001F +%FC0000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C007C000000000000000000000000000000000004000000000000000001FC +%7FC000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C0060000000000000000000000000000000000004000000000000000007E0 +%07E000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C006000000000000000000000000000000000000400000000000000001F00 +%00F80000000000000000020000000000000000FFE3180000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000718E04703021F01F89C1E0238700000000000000000000000000400000000000000007800 +%001C0000000000000000020000000000000000FFE3186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071BF07F83033F01FCFC7F87FCFC000000000000000000000000040000000000000000E000 +%000E0000000000000000020000000000000000C000186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071F3879C3030C0060FCF1C7CF9C000000000000000000000000040000000000000000E000 +%00070000000000000000020000000000000000C000186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C1C70E3030C0060C0C0C7070E000000000000000000000000040000000000000001E000 +%00038000000000000000020000000000000000C00318F81C046000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C0C6063030C0060C1C067060E0000000000000000000000000400000000000000033000 +%0007C000000000000000020000000000000000C00318FC7F07F000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000061800 +%000CE000000000000000020000000000000000C0031870E387E000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000061C00 +%00187000000000000000020000000000000000FFC3186181870000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000040E00 +%00307000000000000000020000000000000000FFC3186180C60000000000000000100000000000 +%0000000000000007C00000000000000000 +%000007180C6063030C0060C18067060E00000000000000000000000004000000000000000C0700 +%00603800000000000000020000000000000000C0031861FFC60000000000000000100000000000 +%000000000000001FF00000000000000000 +%000007180C6063070C0060C0C0E7060E0000000000000000000000000400000000000000180380 +%00C03800000000000000020000000000000000C0031861FFC60000000000000000100000000000 +%00000000000000383C0000000000000000 +%000007180C70C3070C0060C0E1C7060E00000000000000000000000004000000000000001801C0 +%01801800000000000000020000000000000000C003186180060000000000000000100000000000 +%00000000000000701C0000000000000000 +%000007180C7FC3FF0F0060C07F87060E00000000000000000000000004000000000000003000E0 +%03001C00000000000000020000000000000000C003186180060000000000000000100000000000 +%00000000000000E00E0000000000000000 +%000007180C6F00F3070060C03F07060E0000000000000000000000000400000000000000300060 +%06000C00000000000000020000000000000000C003186180C60000000000000000100000000000 +%00000000000000C0060000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000000300030 +%0C000C00000000000000020000000000000000C0031871C1860000000000000000100000000000 +%00000000000001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000C00300018 +%18000400000000000070020000000000000000C003187CFF860000000000000000100000000000 +%00000000600001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FE060000E +%3000060000000000007F020000000000000000C003183C3E060000000000000000100000000000 +%000000007E0001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FF8600006 +%6000060000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FFF600003 +%C000060000000000007FFA00000000000000000000000000000000000000000000100000000000 +%00000000FFF001C0070000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FFE600001 +%C000060000000000007FFA00000000000000000000000000000000000000000000100000000000 +%00000000FFF000C0060000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FF8600003 +%C000060000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC000C0060000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FE0600006 +%6000060000000000007F0200000000000000000000000000000000000000000000100000000000 +%000000007E000060EC0000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000C0060000C +%380006000000000000700200000000000000000000000000000000000000000000100000000000 +%00000000600000707C0000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000700018 +%180006000000000000000200000000000000000000000000000000000000000000100000000000 +%000000000000003FFC0000000000000000 +%00000000000003807FE001FC000000000000000000000000000000000400000000000000300030 +%0C000C000000000000000200000000000000000000000000000000000000000000100000000000 +%000000000000000FEE0000000000000000 +%00000000000003807FF807FE000000000000000000000000000000000400000000000000300070 +%07000C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000030000000000000000 +%00000000000006C0603C0E070000000000000000000000000000000004000000000000003000E0 +%03000C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000006C0600C0C038000000000000000000000000000000004000000000000003001C0 +%01801C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000EE0600E1801800000000000000000000000000000000400000000000000180380 +%00E018000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600E1800000000000000000000000000000000000400000000000000180700 +%007038000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600638000000000000000000000000000000000004000000000000000C0E00 +%003838000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000001C70600638000000000000000000000000000000000004000000000000000C1C00 +%001C70000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000183060063800000000000000000000000000000000000400000000000000061800 +%000E70000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000183860063800000000000000000000000000000000000400000000000000033000 +%0007E0000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF86006380000000000000000000000000000000000040000000000000001A000 +%000380000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF8600E180180000000000000000000000000000000040000000000000000C000 +%000300000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000701C600E1C0180000000000000000000000000000000040000000000000000E000 +%000700000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C601C0C03800000000000000000000000000000000400000000000000007C00 +%003E00000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E603C0F07000000000000000000000000000000000400000000000000003E00 +%00FC00000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E7FF807FE000000000000000000000000000000000400000000000000000F80 +%01F000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FE001F80000000000000000000000000000000004000000000000000003FC +%3F8000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000004000000000000000000FF +%FF0000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000001F +%F80000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000001 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%0000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000007 +%00000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000007 +%80000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%80000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%80000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000001F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000007F800000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000C00000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000C00000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000800000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007E0C6FC00400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000E70C7FE00400000000000000000000 +%0007807807C0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C38C70600400000000000000000000 +%001FC1FE0FE0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C00C60600400000000000000000000 +%003863871870000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000F00C60600400000000000000000000 +%003033039830000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007E0C60600400000000000000000000 +%007007019800000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000001F8C60600400000000000000000000 +%006007019F80000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000038C60600400000000000000000000 +%0060060187E0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000818C60600400000000000000000000 +%0060070180F0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C18C60600400000000000000000000 +%007037018038000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000E38C60600400000000000000000000 +%003033039838000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007F0C60600400000000000000000000 +%003863871830000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%001FE1FE0FF0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%0007807C07C0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001803003E000F800000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001C0300FF803FE00000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001E0303C1C070780000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001E030300C0E0380000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001F030700E1C01C0000 +%00000000000000004000000000000001FF00000000006000018006086000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001B83060001800C0000 +%00000000000000004000000000000001FFC0000000006000018006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000019C30E0003800E0000 +%0000000000000000400000000000000180C0000000006000000006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000019C30E0003800E0000 +%0000000000000000400000000000000180E0000000006000000006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018E30C0003800E0000 +%0000000000000000400000000000000180603C08E00E66060D80C67E6700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018630E0003800E0000 +%000000000000000040000000000000018060FF1FF83FE30E0D83F67E6FC0000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018330E0003800E0000 +%0000000000000000400000000000000180C1C71F3871E30E0D871E1878E0000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000183B060061800C0000 +%00000000000000004000000000000001FF83831C1C60E30F198E0E187060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000181B060061800C0000 +%00000000000000004000000000000001FF80031C0CE0630B198C0E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000181F0700E0C01C0000 +%0000000000000000400000000000000181E0071C0CE0619B198C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180F0381C0E0380000 +%000000000000000040000000000000018060FF1C0CC0619B318C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180701FF807FF00000 +%000000000000000040000000000000018071E31C0CC06199B18C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180700FF001FC00000 +%000000000000000040000000000000018073831C0CE060F1B18C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000018073031C0C6060F1E18E0E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000180E3071C0C70E0F0E1861E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000001FFC1FF9C0C3FE070E187FE1E6060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000001FF80F99C0C0F6060E181E60E6060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000003E0300000000006000FC00000003 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000FF830000000000C003FF00000003 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001C1C00000000000C0070780000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380E00000000000C00E0180000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380400000000000800C01C0000000 +%000000000000000040000000000000000C000000180000000010C0000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380031BF81F8001801C0001FC1FC3 +%1BF03F800000000040000000000000000C000000180000000030C0000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001F0031F3839C001801800039E38E3 +%1F3879C00000000040000000000000000C00000000000000003000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000FE031C1C60600100180007073063 +%1C1860E00000000040000000000000000C00000000000000003000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000001FC31C0C60700300180006033003 +%1C1CC060000000004000000000000001CC07001C18CF0E01F07CC07819E0000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000003C31C0CE070030018000E033C03 +%181CE060000000004000000000000007EC1FC07F18FFBF83FC7CC0FE1BF0000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000E31C0CFFF0030018000E031FC3 +%181CFFE000000000400000000000000E3C38E0E398F1F3861C30C1C71E38000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000300631C0CE00006001C00CE0303E3 +%181CC00000000000400000000000000C1C6070C198E0C18E0C30C3839C18000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000300631C0CE00006000C01CE030073 +%181CC0000000000040000000000000180C60318018E0C1800C30C3019818000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380631C0C606006000E0186073073 +%181CE0600000000040000000000000180C7FF18018C0C1803C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000003C0C31C0C70600400070387063073 +%181C70E00000000040000000000000180C7FF18018C0C183FC30C701981C000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001FFC31C0C3DE00C0003FF03DE3DE3 +%181C3BC00000000040000000000000180C60018018C0C1878C30C701981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000007F031C0C1F800C0001FC01F80FC3 +%181C1F800000000040000000000000180C60018098C0C18C0C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000C1C7031C1D8C0C18C0C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000E1C7060C198C0C18C1C30C383981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000007FC3FE07F18C0C187FE3EC1FF181C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000003CC0F803E18C0C183E61EC07C181C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000007E000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000001FF800000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000381C00000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000700E00000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000060060300860030110180F818 +%088000000000000040000000000000001E00000010000000000000380700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0001FC0DF81FC3F8FF0F8FE +%0FE000000000000040000000000000003E000000300000000000003C0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0003CE0F9C38E3F9C7061C7 +%0FC0000000000000400000000000000030000000300000000000003C0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0003030E0C3073818386383 +%8E00000000000000400000000000000030000000300000000000003E0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0FE6030C0E6033800386301 +%8C000000000000004000000000000000FE1F00F07E1F037007FF00360700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0FF7030C0E7033800386301 +%CC000000000000004000000000000000FE7FC1FC7C3F83F007FF00330700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0077FF0C0E7FF380FF86301 +%CC0000000000000040000000000000003061C38E3071C3D0000000338700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0076000C0E600381E386301 +%CC00000000000000400000000000000030E0C70630C0E38000000031C700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0076000C0E6003838386301 +%CC0000000000000040000000000000003000C60030C0630000000030C700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000070077030C0E7033830386301 +%8C0000000000000040000000000000003007C60030C0630000000030E700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000381E3870C0E3073830786383 +%8C000000000000004000000000000000303FC60031C0730007FF00307700000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000001FFC1FE0C0E3FE381CF879FF +%0C0000000000000040000000000000003070C60030C0630007FF00303700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000007F00FC0C0E0FC380F983C7C +%0C00000000000000400000000000000030C0C60230C06300000000303F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000030C0C60630C06300000000301F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000030E1C30E38E0E300000000300F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000000307FE3FC3E7FC300000000300F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000000303C60F01E1F0300000000300700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000018000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000018000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000007C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000007C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FE000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FE000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FF000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FF000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000001F800000000000000000F000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000007FE00000000C00000001F000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000E0F00000000C000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000001C0300000000C000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000180380000000E000000038000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000380003F837E3F0FC0FC07F7F1FC07EC606 +%0FE0DF81FC60700000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000003800073C3CF0C1CE0FC0187F3CE0E7C606 +%1C70FBC38E70600000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030000C0C3870C3030E0018703071C1C606 +%3830E0C30630600000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030000C0E3030C3038C001870603181C606 +%3018C0C60030E00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030001C0E3030C7038C001870703181C606 +%3038C0C60038C00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030001FFE3030C7FF8C0018707FF180C606 +%3FF8C0C60018C00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000038019C003030C7000C001870600180C606 +%3000C0C60019800000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000018019C003030C7000C001870600181C606 +%3000C0C6000D800000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000001C030C0C3030C3030C001870703181C606 +%3018C0C6060D000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000E070E0C3030C3830C0018703871C3C70E +%3838C0C3060F000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000007FE07BC3030F1EF0C0018703FE0F7C3FE +%1EF0C0C3DE07000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000003F803F0303070FC0C0018700FC07DC1F6 +%07E0C0C0F806000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000006000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000006000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%00000000001C000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000038000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000008000 +%000000000030000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001E000187C00000000000003C0 +%0060F8000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003E00011FF000C0000000007C0 +%0063FC000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000300003183001C000000000E00 +%00670E000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000300003303801C000000380C00 +%004606000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000FC1802301803E030000381F03 +%00C607000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000FC7F06001803F1FC000381F9F +%C0C006000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000070E706003801C38E000380C18 +%E08006000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C386007001C707003FF8C30 +%60800E000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C00C00E001C603003FF8C38 +%01801C000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000030F00C01C001C603800380C1E +%018038000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000FE307E0C038001C603800380C0F +%C10070000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000FE300F88070001C603800380C03 +%E300E0000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003003980E0001C603800380C00 +%7303C0000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003181981C0001C703000380C30 +%330300000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C190380001C307000000C38 +%760600000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000030FF103FF800F3FE000000C1F +%E60FFE000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000307E303FF800F0FC000000C0F +%C60FFF000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0 lw 1 lj 0.000 c 17781 10461 m 14606 10461 l 14606 6016 l 20956 6016 l +20956 10461 l 17781 10461 l pc +gs +pum +15663 7567 t +65 0 m 65 -606 l 274 -606 l 321 -606 357 -603 382 -597 ct 416 -589 446 -575 471 -554 ct +503 -527 526 -492 542 -450 ct 558 -408 566 -360 566 -306 ct 566 -260 561 -219 550 -184 ct +539 -148 525 -119 509 -95 ct 492 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +353 -3 320 0 284 0 ct p +145 -71 m 275 -71 l 315 -71 346 -75 369 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 457 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -371 473 -419 452 -453 ct +431 -487 406 -510 376 -522 ct 355 -530 320 -534 272 -534 ct 145 -534 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1564 -520 m 1564 -606 l 1638 -606 l 1638 -520 l p +1564 0 m 1564 -439 l 1638 -439 l 1638 0 l p ef +1748 0 m 1748 -439 l 1815 -439 l 1815 -377 l 1829 -399 1847 -416 1870 -429 ct +1893 -442 1919 -449 1948 -449 ct 1981 -449 2007 -442 2028 -428 ct 2049 -415 2064 -396 2072 -372 ct +2107 -423 2152 -449 2208 -449 ct 2251 -449 2285 -437 2308 -412 ct 2332 -388 2343 -351 2343 -301 ct +2343 0 l 2269 0 l 2269 -276 l 2269 -306 2267 -327 2262 -340 ct 2257 -354 2249 -364 2236 -372 ct +2223 -380 2208 -384 2191 -384 ct 2160 -384 2135 -374 2114 -353 ct 2094 -333 2084 -300 2084 -255 ct +2084 0 l 2009 0 l 2009 -285 l 2009 -318 2003 -343 1991 -359 ct 1979 -376 1959 -384 1932 -384 ct +1911 -384 1891 -379 1873 -368 ct 1856 -357 1843 -340 1835 -319 ct 1827 -298 1823 -267 1823 -227 ct +1823 0 l p ef +2750 -54 m 2722 -30 2696 -14 2670 -4 ct 2645 5 2617 9 2588 9 ct 2540 9 2503 -1 2477 -25 ct +2451 -49 2438 -79 2438 -115 ct 2438 -137 2443 -156 2453 -174 ct 2463 -192 2475 -206 2491 -217 ct +2507 -228 2525 -236 2545 -241 ct 2559 -245 2581 -249 2611 -253 ct 2671 -260 2715 -268 2744 -278 ct +2744 -288 2744 -295 2744 -298 ct 2744 -328 2737 -349 2723 -362 ct 2704 -379 2676 -387 2638 -387 ct +2603 -387 2577 -381 2561 -369 ct 2544 -356 2532 -335 2524 -303 ct 2451 -313 l +2458 -345 2468 -370 2484 -389 ct 2499 -408 2521 -423 2549 -433 ct 2578 -443 2611 -449 2649 -449 ct +2687 -449 2717 -444 2740 -435 ct 2764 -427 2781 -415 2792 -402 ct 2803 -389 2811 -372 2815 -351 ct +2818 -339 2819 -316 2819 -283 ct 2819 -184 l 2819 -114 2821 -71 2824 -52 ct +2827 -34 2833 -16 2843 0 ct 2765 0 l 2757 -15 l 2752 -33 l p +2744 -220 m 2717 -209 2676 -200 2622 -192 ct 2592 -187 2570 -182 2557 -177 ct +2545 -171 2535 -163 2528 -153 ct 2521 -142 2518 -130 2518 -117 ct 2518 -98 2525 -81 2540 -68 ct +2555 -55 2577 -48 2606 -48 ct 2635 -48 2660 -54 2683 -67 ct 2705 -79 2721 -96 2732 -118 ct +2740 -135 2744 -160 2744 -193 ct p ef +3076 -66 m 3087 0 l 3066 3 3047 5 3030 5 ct 3003 5 2982 1 2968 -7 ct 2953 -15 2942 -26 2936 -40 ct +2930 -54 2927 -83 2927 -128 ct 2927 -381 l 2872 -381 l 2872 -439 l 2927 -439 l +2927 -547 l 3001 -592 l 3001 -439 l 3076 -439 l 3076 -381 l 3001 -381 l +3001 -124 l 3001 -103 3002 -89 3005 -83 ct 3008 -77 3012 -72 3018 -69 ct 3024 -65 3032 -63 3043 -63 ct +3051 -63 l 3062 -64 l p ef +3152 -520 m 3152 -606 l 3226 -606 l 3226 -520 l p +3152 0 m 3152 -439 l 3226 -439 l 3226 0 l p ef +3336 0 m 3336 -439 l 3403 -439 l 3403 -376 l 3436 -425 3482 -449 3543 -449 ct +3570 -449 3594 -444 3616 -434 ct 3638 -425 3655 -412 3666 -397 ct 3677 -382 3685 -363 3689 -342 ct +3692 -328 3693 -304 3693 -270 ct 3693 0 l 3619 0 l 3619 -267 l 3619 -297 3616 -320 3610 -335 ct +3604 -350 3594 -362 3579 -371 ct 3565 -380 3547 -384 3527 -384 ct 3496 -384 3468 -374 3445 -354 ct +3422 -334 3411 -296 3411 -239 ct 3411 0 l p ef +3799 36 m 3871 47 l 3874 69 3883 85 3896 95 ct 3915 109 3940 116 3972 116 ct +4006 116 4033 109 4052 95 ct 4071 82 4083 62 4090 38 ct 4094 22 4095 -8 4095 -57 ct +4063 -19 4022 0 3974 0 ct 3913 0 3867 -21 3833 -65 ct 3800 -108 3784 -161 3784 -222 ct +3784 -264 3791 -302 3807 -338 ct 3822 -373 3844 -400 3873 -420 ct 3901 -439 3935 -449 3974 -449 ct +4026 -449 4069 -428 4102 -386 ct 4102 -439 l 4171 -439 l 4171 -59 l 4171 8 4164 57 4150 85 ct +4136 114 4114 136 4084 153 ct 4054 169 4017 178 3972 178 ct 3920 178 3878 166 3845 142 ct +3813 119 l 3798 83 l p +3860 -227 m 3860 -169 3872 -127 3895 -101 ct 3918 -74 3946 -61 3981 -61 ct +4015 -61 4044 -74 4067 -101 ct 4090 -127 4101 -168 4101 -224 ct 4101 -278 4090 -319 4066 -346 ct +4042 -373 4013 -387 3979 -387 ct 3946 -387 3918 -374 3895 -347 ct 3872 -320 l +3860 -280 l p ef +pom +pum +16007 8520 t +62 0 m 62 -606 l 142 -606 l 142 -71 l 440 -71 l 440 0 l p ef +478 -219 m 478 -300 500 -361 545 -400 ct 583 -432 629 -449 684 -449 ct 744 -449 793 -429 832 -389 ct +870 -350 889 -295 889 -225 ct 889 -169 881 -124 864 -92 ct 847 -60 822 -34 790 -16 ct +757 0 722 9 684 9 ct 622 9 572 -9 534 -49 ct 497 -88 l 478 -145 l p +554 -219 m 554 -163 566 -121 591 -93 ct 615 -65 646 -51 684 -51 ct 721 -51 751 -65 776 -93 ct +800 -121 813 -164 813 -222 ct 813 -276 800 -317 776 -345 ct 751 -373 720 -387 684 -387 ct +646 -387 615 -373 591 -345 ct 566 -317 l 554 -275 l p ef +1062 0 m 928 -439 l 1005 -439 l 1075 -185 l 1101 -91 l 1102 -96 1110 -126 1124 -181 ct +1194 -439 l 1270 -439 l 1336 -184 l 1358 -100 l 1383 -185 l 1458 -439 l +1531 -439 l 1393 0 l 1316 0 l 1246 -263 l 1229 -337 l 1140 0 l p ef +1811 0 m 1811 -606 l 2040 -606 l 2080 -606 2111 -604 2132 -600 ct 2162 -595 2187 -586 2207 -572 ct +2227 -558 2243 -538 2255 -513 ct 2268 -488 2274 -461 2274 -430 ct 2274 -379 2257 -335 2224 -300 ct +2192 -264 2132 -246 2047 -246 ct 1891 -246 l 1891 0 l p +1891 -318 m 2048 -318 l 2100 -318 2136 -327 2158 -346 ct 2180 -366 2191 -393 2191 -428 ct +2191 -453 2185 -475 2172 -493 ct 2159 -511 2142 -523 2121 -529 ct 2108 -532 2083 -534 2046 -534 ct +1891 -534 l p ef +2644 -54 m 2616 -30 2590 -14 2564 -4 ct 2539 5 2511 9 2482 9 ct 2434 9 2397 -1 2371 -25 ct +2345 -49 2332 -79 2332 -115 ct 2332 -137 2337 -156 2347 -174 ct 2357 -192 2369 -206 2385 -217 ct +2401 -228 2419 -236 2439 -241 ct 2453 -245 2475 -249 2505 -253 ct 2565 -260 2609 -268 2638 -278 ct +2638 -288 2638 -295 2638 -298 ct 2638 -328 2631 -349 2617 -362 ct 2598 -379 2570 -387 2532 -387 ct +2497 -387 2471 -381 2455 -369 ct 2438 -356 2426 -335 2418 -303 ct 2345 -313 l +2352 -345 2362 -370 2378 -389 ct 2393 -408 2415 -423 2443 -433 ct 2472 -443 2505 -449 2543 -449 ct +2581 -449 2611 -444 2634 -435 ct 2658 -427 2675 -415 2686 -402 ct 2697 -389 2705 -372 2709 -351 ct +2712 -339 2713 -316 2713 -283 ct 2713 -184 l 2713 -114 2715 -71 2718 -52 ct +2721 -34 2727 -16 2737 0 ct 2659 0 l 2651 -15 l 2646 -33 l p +2638 -220 m 2611 -209 2570 -200 2516 -192 ct 2486 -187 2464 -182 2451 -177 ct +2439 -171 2429 -163 2422 -153 ct 2415 -142 2412 -130 2412 -117 ct 2412 -98 2419 -81 2434 -68 ct +2449 -55 2471 -48 2500 -48 ct 2529 -48 2554 -54 2577 -67 ct 2599 -79 2615 -96 2626 -118 ct +2634 -135 2638 -160 2638 -193 ct p ef +2778 -131 m 2851 -142 l 2855 -113 2867 -90 2886 -74 ct 2905 -59 2931 -51 2965 -51 ct +2999 -51 3024 -58 3041 -72 ct 3058 -86 3066 -102 3066 -121 ct 3066 -138 3059 -151 3044 -160 ct +3034 -167 3008 -175 2968 -186 ct 2913 -199 2875 -211 2854 -221 ct 2833 -231 2817 -245 2806 -263 ct +2795 -281 2790 -301 2790 -322 ct 2790 -342 2794 -360 2803 -376 ct 2812 -393 2825 -407 2840 -418 ct +2852 -427 2867 -434 2887 -440 ct 2907 -446 2929 -449 2952 -449 ct 2986 -449 3016 -444 3042 -434 ct +3069 -424 3088 -410 3100 -393 ct 3113 -376 3121 -354 3126 -325 ct 3053 -315 l +3050 -338 3040 -356 3024 -368 ct 3008 -381 2986 -387 2957 -387 ct 2923 -387 2898 -382 2884 -370 ct +2869 -359 2862 -346 2862 -331 ct 2862 -321 2865 -312 2871 -305 ct 2877 -297 2887 -290 2900 -285 ct +2907 -282 2929 -276 2965 -266 ct 3018 -252 3055 -240 3076 -231 ct 3096 -222 3113 -209 3125 -192 ct +3136 -175 3142 -154 3142 -129 ct 3142 -104 3135 -80 3121 -58 ct 3106 -37 3085 -20 3058 -8 ct +3031 3 3000 9 2965 9 ct 2908 9 2865 -1 2835 -25 ct 2805 -49 l 2786 -84 l p ef +3175 -131 m 3248 -142 l 3252 -113 3264 -90 3283 -74 ct 3302 -59 3328 -51 3362 -51 ct +3396 -51 3421 -58 3438 -72 ct 3455 -86 3463 -102 3463 -121 ct 3463 -138 3456 -151 3441 -160 ct +3431 -167 3405 -175 3365 -186 ct 3310 -199 3272 -211 3251 -221 ct 3230 -231 3214 -245 3203 -263 ct +3192 -281 3187 -301 3187 -322 ct 3187 -342 3191 -360 3200 -376 ct 3209 -393 3222 -407 3237 -418 ct +3249 -427 3264 -434 3284 -440 ct 3304 -446 3326 -449 3349 -449 ct 3383 -449 3413 -444 3439 -434 ct +3466 -424 3485 -410 3497 -393 ct 3510 -376 3518 -354 3523 -325 ct 3450 -315 l +3447 -338 3437 -356 3421 -368 ct 3405 -381 3383 -387 3354 -387 ct 3320 -387 3295 -382 3281 -370 ct +3266 -359 3259 -346 3259 -331 ct 3259 -321 3262 -312 3268 -305 ct 3274 -297 3284 -290 3297 -285 ct +3304 -282 3326 -276 3362 -266 ct 3415 -252 3452 -240 3473 -231 ct 3493 -222 3510 -209 3522 -192 ct +3533 -175 3539 -154 3539 -129 ct 3539 -104 3532 -80 3518 -58 ct 3503 -37 3482 -20 3455 -8 ct +3428 3 3397 9 3362 9 ct 3305 9 3262 -1 3232 -25 ct 3202 -49 l 3183 -84 l p ef +pom +pum +16827 9473 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +585 -520 m 585 -606 l 659 -606 l 659 -520 l p +585 0 m 585 -439 l 659 -439 l 659 0 l p ef +768 0 m 768 -606 l 842 -606 l 842 0 l p ef +1118 -66 m 1129 0 l 1108 3 1089 5 1072 5 ct 1045 5 1024 1 1010 -7 ct 995 -15 984 -26 978 -40 ct +972 -54 969 -83 969 -128 ct 969 -381 l 914 -381 l 914 -439 l 969 -439 l +969 -547 l 1043 -592 l 1043 -439 l 1118 -439 l 1118 -381 l 1043 -381 l +1043 -124 l 1043 -103 1044 -89 1047 -83 ct 1050 -77 1054 -72 1060 -69 ct 1066 -65 1074 -63 1085 -63 ct +1093 -63 l 1104 -64 l p ef +1494 -141 m 1571 -131 l 1559 -86 1536 -52 1504 -27 ct 1471 -2 1429 9 1378 9 ct +1314 9 1263 -9 1225 -49 ct 1187 -88 1169 -144 1169 -215 ct 1169 -289 1188 -347 1226 -387 ct +1264 -428 1313 -449 1374 -449 ct 1432 -449 1480 -429 1518 -389 ct 1555 -349 1573 -292 1573 -220 ct +1573 -216 1573 -209 1573 -200 ct 1245 -200 l 1248 -152 1262 -115 1286 -89 ct +1311 -64 1342 -51 1378 -51 ct 1406 -51 1429 -58 1448 -72 ct 1467 -87 l 1483 -110 l +p +1250 -261 m 1495 -261 l 1492 -298 1482 -326 1467 -344 ct 1443 -373 1412 -387 1374 -387 ct +1340 -387 1312 -376 1288 -353 ct 1265 -330 l 1252 -300 l p ef +1669 0 m 1669 -439 l 1736 -439 l 1736 -372 l 1753 -403 1768 -424 1783 -434 ct +1797 -444 1813 -449 1831 -449 ct 1856 -449 1881 -441 1907 -425 ct 1882 -356 l +1863 -366 1845 -372 1827 -372 ct 1811 -372 1796 -367 1783 -357 ct 1770 -347 1761 -334 1755 -316 ct +1747 -290 1743 -261 1743 -229 ct 1743 0 l p ef +pom +gr +11317 10321 m 11312 10318 l 11099 10206 l 11093 10203 l 10924 10032 l +10921 10026 l 10811 9811 l 10808 9805 l 10769 9556 l 10769 9549 l +10808 9299 l 10811 9293 l 10921 9078 l 10924 9072 l 11093 8901 l 11099 8898 l +11312 8786 l 11317 8784 l 11564 8744 l 11571 8744 l 11817 8784 l 11823 8786 l +12036 8898 l 12041 8901 l 12210 9072 l 12213 9078 l 12324 9293 l 12326 9299 l +12366 9549 l 12366 9556 l 12326 9805 l 12324 9811 l 12213 10026 l +12210 10032 l 12041 10203 l 12036 10206 l 11823 10318 l 11817 10321 l +11571 10361 l 11564 10361 l 11317 10321 l p +11567 10319 m 11806 10279 l 12013 10171 l 12178 10004 l 12285 9794 l +12324 9552 l 12285 9310 l 12178 9100 l 12013 8933 l 11806 8825 l 11567 8786 l +11328 8825 l 11121 8933 l 10956 9100 l 10849 9310 l 10811 9552 l 10849 9794 l +10956 10004 l 11121 10171 l 11328 10279 l 11567 10319 l p +11049 9029 m 11079 8998 l 11286 9208 l 11493 9417 l 11700 9627 l 11907 9837 l +12115 10048 l 12085 10078 l 11877 9868 l 11670 9658 l 11463 9448 l +11255 9238 l 11049 9029 l p +11079 10078 m 11049 10049 l 11255 9838 l 11463 9628 l 11670 9418 l +11878 9208 l 12086 8998 l 12115 9029 l 11907 9239 l 11700 9449 l 11493 9659 l +11286 9869 l 11079 10078 l p ef +1 lw 0 lj 11317 10321 m 11312 10318 l 11099 10206 l 11093 10203 l 10924 10032 l +10921 10026 l 10811 9811 l 10808 9805 l 10769 9556 l 10769 9549 l +10808 9299 l 10811 9293 l 10921 9078 l 10924 9072 l 11093 8901 l 11099 8898 l +11312 8786 l 11317 8784 l 11564 8744 l 11571 8744 l 11817 8784 l 11823 8786 l +12036 8898 l 12041 8901 l 12210 9072 l 12213 9078 l 12324 9293 l 12326 9299 l +12366 9549 l 12366 9556 l 12326 9805 l 12324 9811 l 12213 10026 l +12210 10032 l 12041 10203 l 12036 10206 l 11823 10318 l 11817 10321 l +11571 10361 l 11564 10361 l 11317 10321 l pc +11567 10319 m 11806 10279 l 12013 10171 l 12178 10004 l 12285 9794 l +12324 9552 l 12285 9310 l 12178 9100 l 12013 8933 l 11806 8825 l 11567 8786 l +11328 8825 l 11121 8933 l 10956 9100 l 10849 9310 l 10811 9552 l 10849 9794 l +10956 10004 l 11121 10171 l 11328 10279 l 11567 10319 l pc +11049 9029 m 11079 8998 l 11286 9208 l 11493 9417 l 11700 9627 l 11907 9837 l +12115 10048 l 12085 10078 l 11877 9868 l 11670 9658 l 11463 9448 l +11255 9238 l 11049 9029 l pc +11079 10078 m 11049 10049 l 11255 9838 l 11463 9628 l 11670 9418 l +11878 9208 l 12086 8998 l 12115 9029 l 11907 9239 l 11700 9449 l 11493 9659 l +11286 9869 l 11079 10078 l pc +7989 6986 m 7538 6836 l 7539 7136 l 7989 6986 l p ef +5716 6986 m 7629 6986 l ps +14606 6986 m 14155 6836 l 14156 7136 l 14606 6986 l p ef +9526 6986 m 14246 6986 l ps +10769 9526 m 10318 9376 l 10319 9676 l 10769 9526 l p ef +5716 9526 m 10409 9526 l ps +14606 9526 m 14155 9376 l 14156 9676 l 14606 9526 l p ef +12426 9526 m 14246 9526 l ps +0 lw 1 lj 10061 16546 m 6251 16546 l 6251 12736 l 13871 12736 l 13871 16546 l +10061 16546 l pc +gs +pum +9102 13970 t +64 0 m 64 -606 l 146 -606 l 465 -130 l 465 -606 l 542 -606 l 542 0 l +459 0 l 141 -476 l 141 0 l p ef +1106 -212 m 1187 -192 l 1170 -126 1140 -76 1096 -41 ct 1052 -6 999 10 936 10 ct +870 10 817 -2 776 -29 ct 735 -56 704 -94 683 -145 ct 661 -195 651 -249 651 -307 ct +651 -370 663 -425 687 -472 ct 711 -519 745 -555 790 -580 ct 834 -604 883 -616 937 -616 ct +998 -616 1049 -601 1090 -570 ct 1131 -539 1160 -496 1176 -440 ct 1097 -421 l +1083 -465 1063 -497 1036 -517 ct 1009 -537 976 -547 935 -547 ct 889 -547 850 -536 818 -514 ct +787 -492 765 -462 752 -424 ct 740 -386 733 -348 733 -308 ct 733 -256 741 -211 756 -173 ct +771 -134 794 -105 826 -86 ct 858 -67 892 -58 929 -58 ct 974 -58 1012 -71 1043 -97 ct +1074 -123 l 1095 -161 l p ef +1284 -295 m 1284 -395 1311 -474 1366 -531 ct 1420 -588 1489 -617 1575 -617 ct +1631 -617 1681 -603 1726 -576 ct 1771 -550 1805 -512 1829 -465 ct 1852 -417 1864 -362 1864 -302 ct +1864 -240 1852 -185 1827 -137 ct 1802 -88 1767 -52 1722 -27 ct 1676 -2 1627 10 1574 10 ct +1517 10 1466 -3 1421 -31 ct 1376 -58 1342 -96 1319 -143 ct 1296 -191 l 1284 -242 l +p +1367 -294 m 1367 -220 1387 -163 1426 -121 ct 1465 -79 1515 -58 1574 -58 ct +1634 -58 1684 -79 1723 -122 ct 1762 -164 1782 -224 1782 -302 ct 1782 -352 1773 -395 1757 -431 ct +1740 -468 1715 -497 1683 -517 ct 1651 -537 1615 -547 1575 -547 ct 1518 -547 1470 -528 1429 -489 ct +1388 -450 l 1367 -385 l p ef +pom +pum +7514 14923 t +38 -194 m 113 -201 l 117 -171 125 -146 138 -126 ct 151 -107 172 -91 199 -79 ct +227 -67 258 -61 292 -61 ct 323 -61 350 -66 373 -75 ct 397 -84 414 -96 426 -112 ct +437 -128 443 -145 443 -164 ct 443 -183 437 -200 426 -214 ct 415 -228 397 -240 372 -250 ct +355 -256 319 -266 264 -279 ct 208 -293 169 -305 147 -317 ct 118 -332 96 -351 82 -374 ct +68 -396 61 -421 61 -449 ct 61 -480 69 -508 87 -535 ct 104 -561 130 -582 163 -595 ct +196 -609 233 -616 274 -616 ct 319 -616 359 -609 393 -594 ct 427 -580 454 -559 472 -531 ct +491 -502 501 -471 502 -435 ct 425 -429 l 421 -468 407 -496 383 -516 ct 359 -536 324 -545 277 -545 ct +229 -545 194 -537 171 -519 ct 149 -501 138 -480 138 -454 ct 138 -433 146 -415 162 -401 ct +177 -387 217 -372 283 -357 ct 348 -343 393 -330 417 -319 ct 452 -303 478 -282 495 -257 ct +512 -232 520 -203 520 -171 ct 520 -138 511 -108 492 -80 ct 474 -51 447 -29 413 -13 ct +378 2 339 10 296 10 ct 241 10 195 2 158 -13 ct 121 -29 92 -53 71 -85 ct 50 -117 l +39 -154 l p ef +638 -520 m 638 -606 l 712 -606 l 712 -520 l p +638 0 m 638 -439 l 712 -439 l 712 0 l p ef +822 0 m 822 -439 l 889 -439 l 889 -376 l 922 -425 968 -449 1029 -449 ct +1056 -449 1080 -444 1102 -434 ct 1124 -425 1141 -412 1152 -397 ct 1163 -382 1171 -363 1175 -342 ct +1178 -328 1179 -304 1179 -270 ct 1179 0 l 1105 0 l 1105 -267 l 1105 -297 1102 -320 1096 -335 ct +1090 -350 1080 -362 1065 -371 ct 1051 -380 1033 -384 1013 -384 ct 982 -384 954 -374 931 -354 ct +908 -334 897 -296 897 -239 ct 897 0 l p ef +1600 -141 m 1677 -131 l 1665 -86 1642 -52 1610 -27 ct 1577 -2 1535 9 1484 9 ct +1420 9 1369 -9 1331 -49 ct 1293 -88 1275 -144 1275 -215 ct 1275 -289 1294 -347 1332 -387 ct +1370 -428 1419 -449 1480 -449 ct 1538 -449 1586 -429 1624 -389 ct 1661 -349 1679 -292 1679 -220 ct +1679 -216 1679 -209 1679 -200 ct 1351 -200 l 1354 -152 1368 -115 1392 -89 ct +1417 -64 1448 -51 1484 -51 ct 1512 -51 1535 -58 1554 -72 ct 1573 -87 l 1589 -110 l +p +1356 -261 m 1601 -261 l 1598 -298 1588 -326 1573 -344 ct 1549 -373 1518 -387 1480 -387 ct +1446 -387 1418 -376 1394 -353 ct 1371 -330 l 1358 -300 l p ef +1958 10 m 2133 -616 l 2193 -616 l 2017 10 l p ef +2931 -212 m 3012 -192 l 2995 -126 2965 -76 2921 -41 ct 2877 -6 2824 10 2761 10 ct +2695 10 2642 -2 2601 -29 ct 2560 -56 2529 -94 2508 -145 ct 2486 -195 2476 -249 2476 -307 ct +2476 -370 2488 -425 2512 -472 ct 2536 -519 2570 -555 2615 -580 ct 2659 -604 2708 -616 2762 -616 ct +2823 -616 2874 -601 2915 -570 ct 2956 -539 2985 -496 3001 -440 ct 2922 -421 l +2908 -465 2888 -497 2861 -517 ct 2834 -537 2801 -547 2760 -547 ct 2714 -547 2675 -536 2643 -514 ct +2612 -492 2590 -462 2577 -424 ct 2565 -386 2558 -348 2558 -308 ct 2558 -256 2566 -211 2581 -173 ct +2596 -134 2619 -105 2651 -86 ct 2683 -67 2717 -58 2754 -58 ct 2799 -58 2837 -71 2868 -97 ct +2899 -123 l 2920 -161 l p ef +3097 -219 m 3097 -300 3119 -361 3164 -400 ct 3202 -432 3248 -449 3303 -449 ct +3363 -449 3412 -429 3451 -389 ct 3489 -350 3508 -295 3508 -225 ct 3508 -169 3500 -124 3483 -92 ct +3466 -60 3441 -34 3409 -16 ct 3376 0 3341 9 3303 9 ct 3241 9 3191 -9 3153 -49 ct +3116 -88 l 3097 -145 l p +3173 -219 m 3173 -163 3185 -121 3210 -93 ct 3234 -65 3265 -51 3303 -51 ct 3340 -51 3370 -65 3395 -93 ct +3419 -121 3432 -164 3432 -222 ct 3432 -276 3419 -317 3395 -345 ct 3370 -373 3339 -387 3303 -387 ct +3265 -387 3234 -373 3210 -345 ct 3185 -317 l 3173 -275 l p ef +3571 -131 m 3644 -142 l 3648 -113 3660 -90 3679 -74 ct 3698 -59 3724 -51 3758 -51 ct +3792 -51 3817 -58 3834 -72 ct 3851 -86 3859 -102 3859 -121 ct 3859 -138 3852 -151 3837 -160 ct +3827 -167 3801 -175 3761 -186 ct 3706 -199 3668 -211 3647 -221 ct 3626 -231 3610 -245 3599 -263 ct +3588 -281 3583 -301 3583 -322 ct 3583 -342 3587 -360 3596 -376 ct 3605 -393 3618 -407 3633 -418 ct +3645 -427 3660 -434 3680 -440 ct 3700 -446 3722 -449 3745 -449 ct 3779 -449 3809 -444 3835 -434 ct +3862 -424 3881 -410 3893 -393 ct 3906 -376 3914 -354 3919 -325 ct 3846 -315 l +3843 -338 3833 -356 3817 -368 ct 3801 -381 3779 -387 3750 -387 ct 3716 -387 3691 -382 3677 -370 ct +3662 -359 3655 -346 3655 -331 ct 3655 -321 3658 -312 3664 -305 ct 3670 -297 3680 -290 3693 -285 ct +3700 -282 3722 -276 3758 -266 ct 3811 -252 3848 -240 3869 -231 ct 3889 -222 3906 -209 3918 -192 ct +3929 -175 3935 -154 3935 -129 ct 3935 -104 3928 -80 3914 -58 ct 3899 -37 3878 -20 3851 -8 ct +3824 3 3793 9 3758 9 ct 3701 9 3658 -1 3628 -25 ct 3598 -49 l 3579 -84 l p ef +3998 -520 m 3998 -606 l 4072 -606 l 4072 -520 l p +3998 0 m 3998 -439 l 4072 -439 l 4072 0 l p ef +4183 0 m 4183 -439 l 4250 -439 l 4250 -376 l 4283 -425 4329 -449 4390 -449 ct +4417 -449 4441 -444 4463 -434 ct 4485 -425 4502 -412 4513 -397 ct 4524 -382 4532 -363 4536 -342 ct +4539 -328 4540 -304 4540 -270 ct 4540 0 l 4466 0 l 4466 -267 l 4466 -297 4463 -320 4457 -335 ct +4451 -350 4441 -362 4426 -371 ct 4412 -380 4394 -384 4374 -384 ct 4343 -384 4315 -374 4292 -354 ct +4269 -334 4258 -296 4258 -239 ct 4258 0 l p ef +4960 -141 m 5037 -131 l 5025 -86 5002 -52 4970 -27 ct 4937 -2 4895 9 4844 9 ct +4780 9 4729 -9 4691 -49 ct 4653 -88 4635 -144 4635 -215 ct 4635 -289 4654 -347 4692 -387 ct +4730 -428 4779 -449 4840 -449 ct 4898 -449 4946 -429 4984 -389 ct 5021 -349 5039 -292 5039 -220 ct +5039 -216 5039 -209 5039 -200 ct 4711 -200 l 4714 -152 4728 -115 4752 -89 ct +4777 -64 4808 -51 4844 -51 ct 4872 -51 4895 -58 4914 -72 ct 4933 -87 l 4949 -110 l +p +4716 -261 m 4961 -261 l 4958 -298 4948 -326 4933 -344 ct 4909 -373 4878 -387 4840 -387 ct +4806 -387 4778 -376 4754 -353 ct 4731 -330 l 4718 -300 l p ef +pom +pum +8136 15876 t +349 -237 m 349 -308 l 605 -309 l 605 -84 l 566 -52 525 -29 483 -13 ct +441 2 398 10 354 10 ct 295 10 241 -2 192 -27 ct 143 -53 107 -90 82 -138 ct 57 -186 45 -240 45 -300 ct +45 -359 57 -414 82 -465 ct 106 -516 142 -554 188 -579 ct 234 -604 288 -616 348 -616 ct +392 -616 432 -609 467 -595 ct 502 -581 530 -561 550 -535 ct 571 -510 586 -477 596 -436 ct +524 -416 l 515 -447 504 -472 490 -489 ct 476 -507 457 -521 432 -532 ct 407 -542 379 -547 349 -547 ct +312 -547 280 -542 253 -531 ct 227 -520 205 -505 189 -487 ct 172 -468 160 -449 150 -427 ct +135 -389 127 -349 127 -305 ct 127 -251 137 -205 155 -169 ct 174 -133 201 -106 236 -88 ct +272 -70 310 -62 350 -62 ct 385 -62 418 -68 452 -82 ct 485 -95 510 -109 527 -124 ct +527 -237 l p ef +1017 -141 m 1094 -131 l 1082 -86 1059 -52 1027 -27 ct 994 -2 952 9 901 9 ct +837 9 786 -9 748 -49 ct 710 -88 692 -144 692 -215 ct 692 -289 711 -347 749 -387 ct +787 -428 836 -449 897 -449 ct 955 -449 1003 -429 1041 -389 ct 1078 -349 1096 -292 1096 -220 ct +1096 -216 1096 -209 1096 -200 ct 768 -200 l 771 -152 785 -115 809 -89 ct 834 -64 865 -51 901 -51 ct +929 -51 952 -58 971 -72 ct 990 -87 l 1006 -110 l p +773 -261 m 1018 -261 l 1015 -298 1005 -326 990 -344 ct 966 -373 935 -387 897 -387 ct +863 -387 835 -376 811 -353 ct 788 -330 l 775 -300 l p ef +1193 0 m 1193 -439 l 1260 -439 l 1260 -376 l 1293 -425 1339 -449 1400 -449 ct +1427 -449 1451 -444 1473 -434 ct 1495 -425 1512 -412 1523 -397 ct 1534 -382 1542 -363 1546 -342 ct +1549 -328 1550 -304 1550 -270 ct 1550 0 l 1476 0 l 1476 -267 l 1476 -297 1473 -320 1467 -335 ct +1461 -350 1451 -362 1436 -371 ct 1422 -380 1404 -384 1384 -384 ct 1353 -384 1325 -374 1302 -354 ct +1279 -334 1268 -296 1268 -239 ct 1268 0 l p ef +1970 -141 m 2047 -131 l 2035 -86 2012 -52 1980 -27 ct 1947 -2 1905 9 1854 9 ct +1790 9 1739 -9 1701 -49 ct 1663 -88 1645 -144 1645 -215 ct 1645 -289 1664 -347 1702 -387 ct +1740 -428 1789 -449 1850 -449 ct 1908 -449 1956 -429 1994 -389 ct 2031 -349 2049 -292 2049 -220 ct +2049 -216 2049 -209 2049 -200 ct 1721 -200 l 1724 -152 1738 -115 1762 -89 ct +1787 -64 1818 -51 1854 -51 ct 1882 -51 1905 -58 1924 -72 ct 1943 -87 l 1959 -110 l +p +1726 -261 m 1971 -261 l 1968 -298 1958 -326 1943 -344 ct 1919 -373 1888 -387 1850 -387 ct +1816 -387 1788 -376 1764 -353 ct 1741 -330 l 1728 -300 l p ef +2145 0 m 2145 -439 l 2212 -439 l 2212 -372 l 2229 -403 2244 -424 2259 -434 ct +2273 -444 2289 -449 2307 -449 ct 2332 -449 2357 -441 2383 -425 ct 2358 -356 l +2339 -366 2321 -372 2303 -372 ct 2287 -372 2272 -367 2259 -357 ct 2246 -347 2237 -334 2231 -316 ct +2223 -290 2219 -261 2219 -229 ct 2219 0 l p ef +2723 -54 m 2695 -30 2669 -14 2643 -4 ct 2618 5 2590 9 2561 9 ct 2513 9 2476 -1 2450 -25 ct +2424 -49 2411 -79 2411 -115 ct 2411 -137 2416 -156 2426 -174 ct 2436 -192 2448 -206 2464 -217 ct +2480 -228 2498 -236 2518 -241 ct 2532 -245 2554 -249 2584 -253 ct 2644 -260 2688 -268 2717 -278 ct +2717 -288 2717 -295 2717 -298 ct 2717 -328 2710 -349 2696 -362 ct 2677 -379 2649 -387 2611 -387 ct +2576 -387 2550 -381 2534 -369 ct 2517 -356 2505 -335 2497 -303 ct 2424 -313 l +2431 -345 2441 -370 2457 -389 ct 2472 -408 2494 -423 2522 -433 ct 2551 -443 2584 -449 2622 -449 ct +2660 -449 2690 -444 2713 -435 ct 2737 -427 2754 -415 2765 -402 ct 2776 -389 2784 -372 2788 -351 ct +2791 -339 2792 -316 2792 -283 ct 2792 -184 l 2792 -114 2794 -71 2797 -52 ct +2800 -34 2806 -16 2816 0 ct 2738 0 l 2730 -15 l 2725 -33 l p +2717 -220 m 2690 -209 2649 -200 2595 -192 ct 2565 -187 2543 -182 2530 -177 ct +2518 -171 2508 -163 2501 -153 ct 2494 -142 2491 -130 2491 -117 ct 2491 -98 2498 -81 2513 -68 ct +2528 -55 2550 -48 2579 -48 ct 2608 -48 2633 -54 2656 -67 ct 2678 -79 2694 -96 2705 -118 ct +2713 -135 2717 -160 2717 -193 ct p ef +3049 -66 m 3060 0 l 3039 3 3020 5 3003 5 ct 2976 5 2955 1 2941 -7 ct 2926 -15 2915 -26 2909 -40 ct +2903 -54 2900 -83 2900 -128 ct 2900 -381 l 2845 -381 l 2845 -439 l 2900 -439 l +2900 -547 l 2974 -592 l 2974 -439 l 3049 -439 l 3049 -381 l 2974 -381 l +2974 -124 l 2974 -103 2975 -89 2978 -83 ct 2981 -77 2985 -72 2991 -69 ct 2997 -65 3005 -63 3016 -63 ct +3024 -63 l 3035 -64 l p ef +3097 -219 m 3097 -300 3119 -361 3164 -400 ct 3202 -432 3248 -449 3303 -449 ct +3363 -449 3412 -429 3451 -389 ct 3489 -350 3508 -295 3508 -225 ct 3508 -169 3500 -124 3483 -92 ct +3466 -60 3441 -34 3409 -16 ct 3376 0 3341 9 3303 9 ct 3241 9 3191 -9 3153 -49 ct +3116 -88 l 3097 -145 l p +3173 -219 m 3173 -163 3185 -121 3210 -93 ct 3234 -65 3265 -51 3303 -51 ct 3340 -51 3370 -65 3395 -93 ct +3419 -121 3432 -164 3432 -222 ct 3432 -276 3419 -317 3395 -345 ct 3370 -373 3339 -387 3303 -387 ct +3265 -387 3234 -373 3210 -345 ct 3185 -317 l 3173 -275 l p ef +3600 0 m 3600 -439 l 3667 -439 l 3667 -372 l 3684 -403 3699 -424 3714 -434 ct +3728 -444 3744 -449 3762 -449 ct 3787 -449 3812 -441 3838 -425 ct 3813 -356 l +3794 -366 3776 -372 3758 -372 ct 3742 -372 3727 -367 3714 -357 ct 3701 -347 3692 -334 3686 -316 ct +3678 -290 3674 -261 3674 -229 ct 3674 0 l p ef +pom +gr +gs +pum +1284 9366 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +293 0 m 293 -439 l 360 -439 l 360 -376 l 393 -425 439 -449 500 -449 ct +527 -449 551 -444 573 -434 ct 595 -425 612 -412 623 -397 ct 634 -382 642 -363 646 -342 ct +649 -328 650 -304 650 -270 ct 650 0 l 576 0 l 576 -267 l 576 -297 573 -320 567 -335 ct +561 -350 551 -362 536 -371 ct 522 -380 504 -384 484 -384 ct 453 -384 425 -374 402 -354 ct +379 -334 368 -296 368 -239 ct 368 0 l p ef +769 168 m 769 -439 l 837 -439 l 837 -382 l 853 -404 871 -421 891 -432 ct +911 -443 936 -449 965 -449 ct 1002 -449 1035 -439 1064 -420 ct 1092 -400 1114 -373 1129 -338 ct +1143 -303 1151 -264 1151 -222 ct 1151 -177 1143 -137 1126 -101 ct 1110 -65 1087 -37 1056 -18 ct +1025 0 993 9 959 9 ct 934 9 912 4 892 -5 ct 873 -16 856 -29 844 -45 ct 844 168 l +p +837 -217 m 837 -160 848 -118 871 -91 ct 894 -64 922 -51 954 -51 ct 987 -51 1016 -65 1039 -93 ct +1063 -121 1075 -164 1075 -223 ct 1075 -279 1063 -321 1040 -349 ct 1017 -376 990 -390 958 -390 ct +926 -390 898 -376 873 -346 ct 849 -316 l 837 -273 l p ef +1507 0 m 1507 -64 l 1473 -14 1427 9 1368 9 ct 1342 9 1318 4 1295 -4 ct 1273 -14 1256 -27 1245 -42 ct +1234 -57 1227 -75 1222 -97 ct 1219 -112 1218 -135 1218 -167 ct 1218 -439 l 1292 -439 l +1292 -195 l 1292 -156 1294 -130 1297 -117 ct 1301 -97 1311 -82 1326 -70 ct +1342 -59 1360 -54 1383 -54 ct 1405 -54 1426 -59 1446 -71 ct 1465 -82 1479 -98 1487 -118 ct +1495 -137 1499 -166 1499 -203 ct 1499 -439 l 1574 -439 l 1574 0 l p ef +1858 -66 m 1869 0 l 1848 3 1829 5 1812 5 ct 1785 5 1764 1 1750 -7 ct 1735 -15 1724 -26 1718 -40 ct +1712 -54 1709 -83 1709 -128 ct 1709 -381 l 1654 -381 l 1654 -439 l 1709 -439 l +1709 -547 l 1783 -592 l 1783 -439 l 1858 -439 l 1858 -381 l 1783 -381 l +1783 -124 l 1783 -103 1784 -89 1787 -83 ct 1790 -77 1794 -72 1800 -69 ct 1806 -65 1814 -63 1825 -63 ct +1833 -63 l 1844 -64 l p ef +2190 0 m 2190 -381 l 2124 -381 l 2124 -439 l 2190 -439 l 2190 -485 l +2190 -515 2193 -537 2198 -551 ct 2205 -571 2218 -586 2236 -598 ct 2254 -610 2279 -616 2312 -616 ct +2333 -616 2356 -614 2381 -609 ct 2370 -544 l 2355 -547 2340 -548 2326 -548 ct +2304 -548 2288 -543 2278 -533 ct 2269 -524 2264 -506 2264 -479 ct 2264 -439 l +2350 -439 l 2350 -381 l 2264 -381 l 2264 0 l p ef +2410 0 m 2410 -439 l 2477 -439 l 2477 -372 l 2494 -403 2509 -424 2524 -434 ct +2538 -444 2554 -449 2572 -449 ct 2597 -449 2622 -441 2648 -425 ct 2623 -356 l +2604 -366 2586 -372 2568 -372 ct 2552 -372 2537 -367 2524 -357 ct 2511 -347 2502 -334 2496 -316 ct +2488 -290 2484 -261 2484 -229 ct 2484 0 l p ef +2674 -219 m 2674 -300 2696 -361 2741 -400 ct 2779 -432 2825 -449 2880 -449 ct +2940 -449 2989 -429 3028 -389 ct 3066 -350 3085 -295 3085 -225 ct 3085 -169 3077 -124 3060 -92 ct +3043 -60 3018 -34 2986 -16 ct 2953 0 2918 9 2880 9 ct 2818 9 2768 -9 2730 -49 ct +2693 -88 l 2674 -145 l p +2750 -219 m 2750 -163 2762 -121 2787 -93 ct 2811 -65 2842 -51 2880 -51 ct 2917 -51 2947 -65 2972 -93 ct +2996 -121 3009 -164 3009 -222 ct 3009 -276 2996 -317 2972 -345 ct 2947 -373 2916 -387 2880 -387 ct +2842 -387 2811 -373 2787 -345 ct 2762 -317 l 2750 -275 l p ef +3177 0 m 3177 -439 l 3244 -439 l 3244 -377 l 3258 -399 3276 -416 3299 -429 ct +3322 -442 3348 -449 3377 -449 ct 3410 -449 3436 -442 3457 -428 ct 3478 -415 3493 -396 3501 -372 ct +3536 -423 3581 -449 3637 -449 ct 3680 -449 3714 -437 3737 -412 ct 3761 -388 3772 -351 3772 -301 ct +3772 0 l 3698 0 l 3698 -276 l 3698 -306 3696 -327 3691 -340 ct 3686 -354 3678 -364 3665 -372 ct +3652 -380 3637 -384 3620 -384 ct 3589 -384 3564 -374 3543 -353 ct 3523 -333 3513 -300 3513 -255 ct +3513 0 l 3438 0 l 3438 -285 l 3438 -318 3432 -343 3420 -359 ct 3408 -376 3388 -384 3361 -384 ct +3340 -384 3320 -379 3302 -368 ct 3285 -357 3272 -340 3264 -319 ct 3256 -298 3252 -267 3252 -227 ct +3252 0 l p ef +pom +pum +2302 10319 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +gs +pum +1284 6773 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +293 0 m 293 -439 l 360 -439 l 360 -376 l 393 -425 439 -449 500 -449 ct +527 -449 551 -444 573 -434 ct 595 -425 612 -412 623 -397 ct 634 -382 642 -363 646 -342 ct +649 -328 650 -304 650 -270 ct 650 0 l 576 0 l 576 -267 l 576 -297 573 -320 567 -335 ct +561 -350 551 -362 536 -371 ct 522 -380 504 -384 484 -384 ct 453 -384 425 -374 402 -354 ct +379 -334 368 -296 368 -239 ct 368 0 l p ef +769 168 m 769 -439 l 837 -439 l 837 -382 l 853 -404 871 -421 891 -432 ct +911 -443 936 -449 965 -449 ct 1002 -449 1035 -439 1064 -420 ct 1092 -400 1114 -373 1129 -338 ct +1143 -303 1151 -264 1151 -222 ct 1151 -177 1143 -137 1126 -101 ct 1110 -65 1087 -37 1056 -18 ct +1025 0 993 9 959 9 ct 934 9 912 4 892 -5 ct 873 -16 856 -29 844 -45 ct 844 168 l +p +837 -217 m 837 -160 848 -118 871 -91 ct 894 -64 922 -51 954 -51 ct 987 -51 1016 -65 1039 -93 ct +1063 -121 1075 -164 1075 -223 ct 1075 -279 1063 -321 1040 -349 ct 1017 -376 990 -390 958 -390 ct +926 -390 898 -376 873 -346 ct 849 -316 l 837 -273 l p ef +1507 0 m 1507 -64 l 1473 -14 1427 9 1368 9 ct 1342 9 1318 4 1295 -4 ct 1273 -14 1256 -27 1245 -42 ct +1234 -57 1227 -75 1222 -97 ct 1219 -112 1218 -135 1218 -167 ct 1218 -439 l 1292 -439 l +1292 -195 l 1292 -156 1294 -130 1297 -117 ct 1301 -97 1311 -82 1326 -70 ct +1342 -59 1360 -54 1383 -54 ct 1405 -54 1426 -59 1446 -71 ct 1465 -82 1479 -98 1487 -118 ct +1495 -137 1499 -166 1499 -203 ct 1499 -439 l 1574 -439 l 1574 0 l p ef +1858 -66 m 1869 0 l 1848 3 1829 5 1812 5 ct 1785 5 1764 1 1750 -7 ct 1735 -15 1724 -26 1718 -40 ct +1712 -54 1709 -83 1709 -128 ct 1709 -381 l 1654 -381 l 1654 -439 l 1709 -439 l +1709 -547 l 1783 -592 l 1783 -439 l 1858 -439 l 1858 -381 l 1783 -381 l +1783 -124 l 1783 -103 1784 -89 1787 -83 ct 1790 -77 1794 -72 1800 -69 ct 1806 -65 1814 -63 1825 -63 ct +1833 -63 l 1844 -64 l p ef +2190 0 m 2190 -381 l 2124 -381 l 2124 -439 l 2190 -439 l 2190 -485 l +2190 -515 2193 -537 2198 -551 ct 2205 -571 2218 -586 2236 -598 ct 2254 -610 2279 -616 2312 -616 ct +2333 -616 2356 -614 2381 -609 ct 2370 -544 l 2355 -547 2340 -548 2326 -548 ct +2304 -548 2288 -543 2278 -533 ct 2269 -524 2264 -506 2264 -479 ct 2264 -439 l +2350 -439 l 2350 -381 l 2264 -381 l 2264 0 l p ef +2410 0 m 2410 -439 l 2477 -439 l 2477 -372 l 2494 -403 2509 -424 2524 -434 ct +2538 -444 2554 -449 2572 -449 ct 2597 -449 2622 -441 2648 -425 ct 2623 -356 l +2604 -366 2586 -372 2568 -372 ct 2552 -372 2537 -367 2524 -357 ct 2511 -347 2502 -334 2496 -316 ct +2488 -290 2484 -261 2484 -229 ct 2484 0 l p ef +2674 -219 m 2674 -300 2696 -361 2741 -400 ct 2779 -432 2825 -449 2880 -449 ct +2940 -449 2989 -429 3028 -389 ct 3066 -350 3085 -295 3085 -225 ct 3085 -169 3077 -124 3060 -92 ct +3043 -60 3018 -34 2986 -16 ct 2953 0 2918 9 2880 9 ct 2818 9 2768 -9 2730 -49 ct +2693 -88 l 2674 -145 l p +2750 -219 m 2750 -163 2762 -121 2787 -93 ct 2811 -65 2842 -51 2880 -51 ct 2917 -51 2947 -65 2972 -93 ct +2996 -121 3009 -164 3009 -222 ct 3009 -276 2996 -317 2972 -345 ct 2947 -373 2916 -387 2880 -387 ct +2842 -387 2811 -373 2787 -345 ct 2762 -317 l 2750 -275 l p ef +3177 0 m 3177 -439 l 3244 -439 l 3244 -377 l 3258 -399 3276 -416 3299 -429 ct +3322 -442 3348 -449 3377 -449 ct 3410 -449 3436 -442 3457 -428 ct 3478 -415 3493 -396 3501 -372 ct +3536 -423 3581 -449 3637 -449 ct 3680 -449 3714 -437 3737 -412 ct 3761 -388 3772 -351 3772 -301 ct +3772 0 l 3698 0 l 3698 -276 l 3698 -306 3696 -327 3691 -340 ct 3686 -354 3678 -364 3665 -372 ct +3652 -380 3637 -384 3620 -384 ct 3589 -384 3564 -374 3543 -353 ct 3523 -333 3513 -300 3513 -255 ct +3513 0 l 3438 0 l 3438 -285 l 3438 -318 3432 -343 3420 -359 ct 3408 -376 3388 -384 3361 -384 ct +3340 -384 3320 -379 3302 -368 ct 3285 -357 3272 -340 3264 -319 ct 3256 -298 3252 -267 3252 -227 ct +3252 0 l p ef +pom +pum +2302 7726 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8442 7781 m 8437 7778 l 8224 7666 l 8218 7663 l 8049 7492 l 8046 7486 l +7936 7271 l 7933 7265 l 7894 7016 l 7894 7009 l 7933 6759 l 7936 6753 l +8046 6538 l 8049 6532 l 8218 6361 l 8224 6358 l 8437 6246 l 8442 6244 l +8689 6204 l 8696 6204 l 8942 6244 l 8948 6246 l 9161 6358 l 9166 6361 l +9335 6532 l 9338 6538 l 9449 6753 l 9451 6759 l 9491 7009 l 9491 7016 l +9451 7265 l 9449 7271 l 9338 7486 l 9335 7492 l 9166 7663 l 9161 7666 l +8948 7778 l 8942 7781 l 8696 7821 l 8689 7821 l 8442 7781 l p +8692 7779 m 8931 7739 l 9138 7631 l 9303 7464 l 9410 7254 l 9449 7012 l +9410 6770 l 9303 6560 l 9138 6393 l 8931 6285 l 8692 6246 l 8453 6285 l +8246 6393 l 8081 6560 l 7974 6770 l 7936 7012 l 7974 7254 l 8081 7464 l +8246 7631 l 8453 7739 l 8692 7779 l p +8174 6489 m 8204 6458 l 8411 6668 l 8618 6877 l 8825 7087 l 9032 7297 l +9240 7508 l 9210 7538 l 9002 7328 l 8795 7118 l 8588 6908 l 8380 6698 l +8174 6489 l p +8204 7538 m 8174 7509 l 8380 7298 l 8588 7088 l 8795 6878 l 9003 6668 l +9211 6458 l 9240 6489 l 9032 6699 l 8825 6909 l 8618 7119 l 8411 7329 l +8204 7538 l p ef +1 lw 0 lj 8442 7781 m 8437 7778 l 8224 7666 l 8218 7663 l 8049 7492 l +8046 7486 l 7936 7271 l 7933 7265 l 7894 7016 l 7894 7009 l 7933 6759 l +7936 6753 l 8046 6538 l 8049 6532 l 8218 6361 l 8224 6358 l 8437 6246 l +8442 6244 l 8689 6204 l 8696 6204 l 8942 6244 l 8948 6246 l 9161 6358 l +9166 6361 l 9335 6532 l 9338 6538 l 9449 6753 l 9451 6759 l 9491 7009 l +9491 7016 l 9451 7265 l 9449 7271 l 9338 7486 l 9335 7492 l 9166 7663 l +9161 7666 l 8948 7778 l 8942 7781 l 8696 7821 l 8689 7821 l 8442 7781 l +pc +8692 7779 m 8931 7739 l 9138 7631 l 9303 7464 l 9410 7254 l 9449 7012 l +9410 6770 l 9303 6560 l 9138 6393 l 8931 6285 l 8692 6246 l 8453 6285 l +8246 6393 l 8081 6560 l 7974 6770 l 7936 7012 l 7974 7254 l 8081 7464 l +8246 7631 l 8453 7739 l 8692 7779 l pc +8174 6489 m 8204 6458 l 8411 6668 l 8618 6877 l 8825 7087 l 9032 7297 l +9240 7508 l 9210 7538 l 9002 7328 l 8795 7118 l 8588 6908 l 8380 6698 l +8174 6489 l pc +8204 7538 m 8174 7509 l 8380 7298 l 8588 7088 l 8795 6878 l 9003 6668 l +9211 6458 l 9240 6489 l 9032 6699 l 8825 6909 l 8618 7119 l 8411 7329 l +8204 7538 l pc +8691 7821 m 8541 8271 l 8841 8270 l 8691 7821 l p ef +8691 8181 m 8691 12701 l ps +11531 10361 m 11381 10811 l 11681 10810 l 11531 10361 l p ef +11531 10721 m 11531 12701 l ps +gs +pum +7329 12171 t +26 -131 m 99 -142 l 103 -113 115 -90 134 -74 ct 153 -59 179 -51 213 -51 ct +247 -51 272 -58 289 -72 ct 306 -86 314 -102 314 -121 ct 314 -138 307 -151 292 -160 ct +282 -167 256 -175 216 -186 ct 161 -199 123 -211 102 -221 ct 81 -231 65 -245 54 -263 ct +43 -281 38 -301 38 -322 ct 38 -342 42 -360 51 -376 ct 60 -393 73 -407 88 -418 ct +100 -427 115 -434 135 -440 ct 155 -446 177 -449 200 -449 ct 234 -449 264 -444 290 -434 ct +317 -424 336 -410 348 -393 ct 361 -376 369 -354 374 -325 ct 301 -315 l 298 -338 288 -356 272 -368 ct +256 -381 234 -387 205 -387 ct 171 -387 146 -382 132 -370 ct 117 -359 110 -346 110 -331 ct +110 -321 113 -312 119 -305 ct 125 -297 135 -290 148 -285 ct 155 -282 177 -276 213 -266 ct +266 -252 303 -240 324 -231 ct 344 -222 361 -209 373 -192 ct 384 -175 390 -154 390 -129 ct +390 -104 383 -80 369 -58 ct 354 -37 333 -20 306 -8 ct 279 3 248 9 213 9 ct 156 9 113 -1 83 -25 ct +53 -49 l 34 -84 l p ef +453 -520 m 453 -606 l 527 -606 l 527 -520 l p +453 0 m 453 -439 l 527 -439 l 527 0 l p ef +637 0 m 637 -439 l 704 -439 l 704 -376 l 737 -425 783 -449 844 -449 ct +871 -449 895 -444 917 -434 ct 939 -425 956 -412 967 -397 ct 978 -382 986 -363 990 -342 ct +993 -328 994 -304 994 -270 ct 994 0 l 920 0 l 920 -267 l 920 -297 917 -320 911 -335 ct +905 -350 895 -362 880 -371 ct 866 -380 848 -384 828 -384 ct 797 -384 769 -374 746 -354 ct +723 -334 712 -296 712 -239 ct 712 0 l p ef +pom +gr +gs +pum +11880 12223 t +342 -160 m 415 -151 l 407 -100 387 -61 354 -32 ct 321 -4 280 9 232 9 ct 172 9 124 -9 87 -49 ct +51 -88 33 -144 33 -217 ct 33 -265 40 -306 56 -342 ct 72 -378 96 -404 128 -422 ct +160 -440 195 -449 233 -449 ct 280 -449 319 -437 350 -412 ct 380 -388 400 -354 408 -310 ct +336 -299 l 329 -328 317 -350 299 -365 ct 282 -380 260 -387 236 -387 ct 198 -387 168 -374 144 -347 ct +121 -320 109 -278 109 -220 ct 109 -161 120 -118 143 -91 ct 166 -64 195 -51 232 -51 ct +261 -51 285 -60 305 -78 ct 324 -96 l 337 -123 l p ef +451 -219 m 451 -300 473 -361 518 -400 ct 556 -432 602 -449 657 -449 ct 717 -449 766 -429 805 -389 ct +843 -350 862 -295 862 -225 ct 862 -169 854 -124 837 -92 ct 820 -60 795 -34 763 -16 ct +730 0 695 9 657 9 ct 595 9 545 -9 507 -49 ct 470 -88 l 451 -145 l p +527 -219 m 527 -163 539 -121 564 -93 ct 588 -65 619 -51 657 -51 ct 694 -51 724 -65 749 -93 ct +773 -121 786 -164 786 -222 ct 786 -276 773 -317 749 -345 ct 724 -373 693 -387 657 -387 ct +619 -387 588 -373 564 -345 ct 539 -317 l 527 -275 l p ef +926 -131 m 999 -142 l 1003 -113 1015 -90 1034 -74 ct 1053 -59 1079 -51 1113 -51 ct +1147 -51 1172 -58 1189 -72 ct 1206 -86 1214 -102 1214 -121 ct 1214 -138 1207 -151 1192 -160 ct +1182 -167 1156 -175 1116 -186 ct 1061 -199 1023 -211 1002 -221 ct 981 -231 965 -245 954 -263 ct +943 -281 938 -301 938 -322 ct 938 -342 942 -360 951 -376 ct 960 -393 973 -407 988 -418 ct +1000 -427 1015 -434 1035 -440 ct 1055 -446 1077 -449 1100 -449 ct 1134 -449 1164 -444 1190 -434 ct +1217 -424 1236 -410 1248 -393 ct 1261 -376 1269 -354 1274 -325 ct 1201 -315 l +1198 -338 1188 -356 1172 -368 ct 1156 -381 1134 -387 1105 -387 ct 1071 -387 1046 -382 1032 -370 ct +1017 -359 1010 -346 1010 -331 ct 1010 -321 1013 -312 1019 -305 ct 1025 -297 1035 -290 1048 -285 ct +1055 -282 1077 -276 1113 -266 ct 1166 -252 1203 -240 1224 -231 ct 1244 -222 1261 -209 1273 -192 ct +1284 -175 1290 -154 1290 -129 ct 1290 -104 1283 -80 1269 -58 ct 1254 -37 1233 -20 1206 -8 ct +1179 3 1148 9 1113 9 ct 1056 9 1013 -1 983 -25 ct 953 -49 l 934 -84 l p ef +pom +gr +24131 6986 m 23680 6836 l 23681 7136 l 24131 6986 l p ef +20956 6986 m 23771 6986 l ps +24131 9526 m 23680 9376 l 23681 9676 l 24131 9526 l p ef +20956 9526 m 23771 9526 l ps +gs +pum +24646 7223 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +pom +gr +gs +pum +24435 9763 t +524 -64 m 562 -39 596 -20 627 -8 ct 604 47 l 560 31 517 6 473 -27 ct 429 -2 379 10 325 10 ct +270 10 220 -2 175 -29 ct 131 -55 96 -93 72 -141 ct 48 -189 36 -243 36 -303 ct 36 -362 48 -417 72 -466 ct +97 -515 131 -552 176 -578 ct 221 -604 271 -617 326 -617 ct 382 -617 433 -603 478 -577 ct +523 -550 557 -513 580 -465 ct 604 -417 616 -363 616 -303 ct 616 -253 608 -208 593 -168 ct +578 -129 l 555 -94 l p +348 -167 m 394 -154 432 -135 462 -109 ct 509 -152 533 -217 533 -303 ct 533 -352 525 -395 508 -432 ct +491 -468 467 -497 435 -517 ct 403 -537 367 -547 327 -547 ct 267 -547 217 -527 178 -486 ct +138 -445 119 -384 119 -303 ct 119 -224 138 -163 177 -121 ct 216 -79 266 -58 327 -58 ct +355 -58 382 -63 408 -74 ct 383 -90 356 -102 328 -109 ct p ef +pom +gr +gs +pum +23747 3307 t +315 0 m 241 0 l 241 -474 l 223 -457 199 -440 170 -423 ct 141 -405 115 -393 92 -384 ct +92 -456 l 133 -476 170 -499 201 -527 ct 232 -555 254 -582 267 -608 ct 315 -608 l +p ef +897 -457 m 823 -452 l 816 -481 807 -502 795 -515 ct 775 -536 750 -547 720 -547 ct +697 -547 676 -540 658 -527 ct 634 -510 616 -485 602 -452 ct 589 -420 582 -373 581 -312 ct +599 -339 621 -360 647 -373 ct 673 -386 700 -393 729 -393 ct 778 -393 820 -375 855 -338 ct +890 -301 908 -254 908 -196 ct 908 -158 899 -123 883 -90 ct 867 -58 844 -33 815 -15 ct +787 1 754 10 718 10 ct 656 10 605 -12 566 -58 ct 527 -103 507 -178 507 -283 ct +507 -400 529 -486 572 -539 ct 610 -585 661 -608 725 -608 ct 773 -608 812 -595 842 -568 ct +873 -541 l 891 -504 l p +593 -196 m 593 -170 598 -146 609 -122 ct 620 -99 635 -81 655 -69 ct 675 -57 695 -50 717 -50 ct +748 -50 775 -63 798 -88 ct 820 -114 832 -148 832 -192 ct 832 -234 820 -267 798 -291 ct +776 -315 748 -327 714 -327 ct 680 -327 652 -315 628 -291 ct 605 -267 l 593 -235 l +p ef +952 -181 m 952 -256 l 1181 -256 l 1181 -181 l p ef +1341 0 m 1272 0 l 1272 -606 l 1346 -606 l 1346 -390 l 1378 -429 1418 -449 1467 -449 ct +1494 -449 1519 -443 1543 -432 ct 1568 -421 1587 -406 1603 -386 ct 1619 -367 1631 -343 1640 -315 ct +1648 -287 1653 -257 1653 -226 ct 1653 -150 1634 -92 1597 -51 ct 1560 -10 1515 9 1463 9 ct +1411 9 1370 -11 1341 -55 ct p +1340 -222 m 1340 -170 1347 -132 1362 -108 ct 1385 -70 1417 -51 1457 -51 ct +1489 -51 1517 -65 1541 -93 ct 1565 -121 1577 -164 1577 -220 ct 1577 -277 1565 -319 1543 -346 ct +1520 -374 1492 -387 1460 -387 ct 1428 -387 1399 -373 1376 -345 ct 1352 -317 l +1340 -276 l p ef +1723 -520 m 1723 -606 l 1797 -606 l 1797 -520 l p +1723 0 m 1723 -439 l 1797 -439 l 1797 0 l p ef +2070 -66 m 2081 0 l 2060 3 2041 5 2024 5 ct 1997 5 1976 1 1962 -7 ct 1947 -15 1936 -26 1930 -40 ct +1924 -54 1921 -83 1921 -128 ct 1921 -381 l 1866 -381 l 1866 -439 l 1921 -439 l +1921 -547 l 1995 -592 l 1995 -439 l 2070 -439 l 2070 -381 l 1995 -381 l +1995 -124 l 1995 -103 1996 -89 1999 -83 ct 2002 -77 2006 -72 2012 -69 ct 2018 -65 2026 -63 2037 -63 ct +2045 -63 l 2056 -64 l p ef +pom +pum +22596 4260 t +340 0 m 340 -55 l 312 -11 272 9 217 9 ct 182 9 150 0 121 -19 ct 92 -38 69 -65 53 -99 ct +37 -134 28 -174 28 -219 ct 28 -263 36 -302 50 -338 ct 65 -374 87 -401 116 -420 ct +145 -439 178 -449 214 -449 ct 241 -449 264 -443 285 -432 ct 306 -421 322 -406 335 -388 ct +335 -606 l 409 -606 l 409 0 l p +105 -219 m 105 -162 117 -120 141 -93 ct 164 -65 192 -51 224 -51 ct 257 -51 285 -64 307 -91 ct +330 -117 342 -158 342 -212 ct 342 -273 330 -317 307 -345 ct 284 -373 255 -387 221 -387 ct +188 -387 160 -374 138 -346 ct 116 -319 l 105 -277 l p ef +818 -54 m 790 -30 764 -14 738 -4 ct 713 5 685 9 656 9 ct 608 9 571 -1 545 -25 ct +519 -49 506 -79 506 -115 ct 506 -137 511 -156 521 -174 ct 531 -192 543 -206 559 -217 ct +575 -228 593 -236 613 -241 ct 627 -245 649 -249 679 -253 ct 739 -260 783 -268 812 -278 ct +812 -288 812 -295 812 -298 ct 812 -328 805 -349 791 -362 ct 772 -379 744 -387 706 -387 ct +671 -387 645 -381 629 -369 ct 612 -356 600 -335 592 -303 ct 519 -313 l 526 -345 536 -370 552 -389 ct +567 -408 589 -423 617 -433 ct 646 -443 679 -449 717 -449 ct 755 -449 785 -444 808 -435 ct +832 -427 849 -415 860 -402 ct 871 -389 879 -372 883 -351 ct 886 -339 887 -316 887 -283 ct +887 -184 l 887 -114 889 -71 892 -52 ct 895 -34 901 -16 911 0 ct 833 0 l 825 -15 l +820 -33 l p +812 -220 m 785 -209 744 -200 690 -192 ct 660 -187 638 -182 625 -177 ct 613 -171 603 -163 596 -153 ct +589 -142 586 -130 586 -117 ct 586 -98 593 -81 608 -68 ct 623 -55 645 -48 674 -48 ct +703 -48 728 -54 751 -67 ct 773 -79 789 -96 800 -118 ct 808 -135 812 -160 812 -193 ct +p ef +1144 -66 m 1155 0 l 1134 3 1115 5 1098 5 ct 1071 5 1050 1 1036 -7 ct 1021 -15 1010 -26 1004 -40 ct +998 -54 995 -83 995 -128 ct 995 -381 l 940 -381 l 940 -439 l 995 -439 l +995 -547 l 1069 -592 l 1069 -439 l 1144 -439 l 1144 -381 l 1069 -381 l +1069 -124 l 1069 -103 1070 -89 1073 -83 ct 1076 -77 1080 -72 1086 -69 ct 1092 -65 1100 -63 1111 -63 ct +1119 -63 l 1130 -64 l p ef +1506 -54 m 1478 -30 1452 -14 1426 -4 ct 1401 5 1373 9 1344 9 ct 1296 9 1259 -1 1233 -25 ct +1207 -49 1194 -79 1194 -115 ct 1194 -137 1199 -156 1209 -174 ct 1219 -192 1231 -206 1247 -217 ct +1263 -228 1281 -236 1301 -241 ct 1315 -245 1337 -249 1367 -253 ct 1427 -260 1471 -268 1500 -278 ct +1500 -288 1500 -295 1500 -298 ct 1500 -328 1493 -349 1479 -362 ct 1460 -379 1432 -387 1394 -387 ct +1359 -387 1333 -381 1317 -369 ct 1300 -356 1288 -335 1280 -303 ct 1207 -313 l +1214 -345 1224 -370 1240 -389 ct 1255 -408 1277 -423 1305 -433 ct 1334 -443 1367 -449 1405 -449 ct +1443 -449 1473 -444 1496 -435 ct 1520 -427 1537 -415 1548 -402 ct 1559 -389 1567 -372 1571 -351 ct +1574 -339 1575 -316 1575 -283 ct 1575 -184 l 1575 -114 1577 -71 1580 -52 ct +1583 -34 1589 -16 1599 0 ct 1521 0 l 1513 -15 l 1508 -33 l p +1500 -220 m 1473 -209 1432 -200 1378 -192 ct 1348 -187 1326 -182 1313 -177 ct +1301 -171 1291 -163 1284 -153 ct 1277 -142 1274 -130 1274 -117 ct 1274 -98 1281 -81 1296 -68 ct +1311 -55 1333 -48 1362 -48 ct 1391 -48 1416 -54 1439 -67 ct 1461 -79 1477 -96 1488 -118 ct +1496 -135 1500 -160 1500 -193 ct p ef +2070 -66 m 2081 0 l 2060 3 2041 5 2024 5 ct 1997 5 1976 1 1962 -7 ct 1947 -15 1936 -26 1930 -40 ct +1924 -54 1921 -83 1921 -128 ct 1921 -381 l 1866 -381 l 1866 -439 l 1921 -439 l +1921 -547 l 1995 -592 l 1995 -439 l 2070 -439 l 2070 -381 l 1995 -381 l +1995 -124 l 1995 -103 1996 -89 1999 -83 ct 2002 -77 2006 -72 2012 -69 ct 2018 -65 2026 -63 2037 -63 ct +2045 -63 l 2056 -64 l p ef +2118 -219 m 2118 -300 2140 -361 2185 -400 ct 2223 -432 2269 -449 2324 -449 ct +2384 -449 2433 -429 2472 -389 ct 2510 -350 2529 -295 2529 -225 ct 2529 -169 2521 -124 2504 -92 ct +2487 -60 2462 -34 2430 -16 ct 2397 0 2362 9 2324 9 ct 2262 9 2212 -9 2174 -49 ct +2137 -88 l 2118 -145 l p +2194 -219 m 2194 -163 2206 -121 2231 -93 ct 2255 -65 2286 -51 2324 -51 ct 2361 -51 2391 -65 2416 -93 ct +2440 -121 2453 -164 2453 -222 ct 2453 -276 2440 -317 2416 -345 ct 2391 -373 2360 -387 2324 -387 ct +2286 -387 2255 -373 2231 -345 ct 2206 -317 l 2194 -275 l p ef +2860 0 m 2860 -606 l 2935 -606 l 2935 -388 l 2970 -429 3013 -449 3066 -449 ct +3099 -449 3127 -442 3151 -429 ct 3175 -417 3192 -399 3203 -376 ct 3213 -354 3218 -321 3218 -278 ct +3218 0 l 3144 0 l 3144 -278 l 3144 -315 3136 -342 3119 -359 ct 3103 -376 3081 -385 3051 -385 ct +3029 -385 3008 -379 2989 -367 ct 2969 -356 2955 -340 2947 -321 ct 2939 -301 2935 -274 2935 -240 ct +2935 0 l p ef +3309 -219 m 3309 -300 3331 -361 3376 -400 ct 3414 -432 3460 -449 3515 -449 ct +3575 -449 3624 -429 3663 -389 ct 3701 -350 3720 -295 3720 -225 ct 3720 -169 3712 -124 3695 -92 ct +3678 -60 3653 -34 3621 -16 ct 3588 0 3553 9 3515 9 ct 3453 9 3403 -9 3365 -49 ct +3328 -88 l 3309 -145 l p +3385 -219 m 3385 -163 3397 -121 3422 -93 ct 3446 -65 3477 -51 3515 -51 ct 3552 -51 3582 -65 3607 -93 ct +3631 -121 3644 -164 3644 -222 ct 3644 -276 3631 -317 3607 -345 ct 3582 -373 3551 -387 3515 -387 ct +3477 -387 3446 -373 3422 -345 ct 3397 -317 l 3385 -275 l p ef +3783 -131 m 3856 -142 l 3860 -113 3872 -90 3891 -74 ct 3910 -59 3936 -51 3970 -51 ct +4004 -51 4029 -58 4046 -72 ct 4063 -86 4071 -102 4071 -121 ct 4071 -138 4064 -151 4049 -160 ct +4039 -167 4013 -175 3973 -186 ct 3918 -199 3880 -211 3859 -221 ct 3838 -231 3822 -245 3811 -263 ct +3800 -281 3795 -301 3795 -322 ct 3795 -342 3799 -360 3808 -376 ct 3817 -393 3830 -407 3845 -418 ct +3857 -427 3872 -434 3892 -440 ct 3912 -446 3934 -449 3957 -449 ct 3991 -449 4021 -444 4047 -434 ct +4074 -424 4093 -410 4105 -393 ct 4118 -376 4126 -354 4131 -325 ct 4058 -315 l +4055 -338 4045 -356 4029 -368 ct 4013 -381 3991 -387 3962 -387 ct 3928 -387 3903 -382 3889 -370 ct +3874 -359 3867 -346 3867 -331 ct 3867 -321 3870 -312 3876 -305 ct 3882 -297 3892 -290 3905 -285 ct +3912 -282 3934 -276 3970 -266 ct 4023 -252 4060 -240 4081 -231 ct 4101 -222 4118 -209 4130 -192 ct +4141 -175 4147 -154 4147 -129 ct 4147 -104 4140 -80 4126 -58 ct 4111 -37 4090 -20 4063 -8 ct +4036 3 4005 9 3970 9 ct 3913 9 3870 -1 3840 -25 ct 3810 -49 l 3791 -84 l p ef +4372 -66 m 4383 0 l 4362 3 4343 5 4326 5 ct 4299 5 4278 1 4264 -7 ct 4249 -15 4238 -26 4232 -40 ct +4226 -54 4223 -83 4223 -128 ct 4223 -381 l 4168 -381 l 4168 -439 l 4223 -439 l +4223 -547 l 4297 -592 l 4297 -439 l 4372 -439 l 4372 -381 l 4297 -381 l +4297 -124 l 4297 -103 4298 -89 4301 -83 ct 4304 -77 4308 -72 4314 -69 ct 4320 -65 4328 -63 4339 -63 ct +4347 -63 l 4358 -64 l p ef +pom +pum +23257 5213 t +177 0 m 10 -439 l 89 -439 l 183 -176 l 193 -147 203 -118 211 -87 ct 218 -110 227 -138 239 -171 ct +337 -439 l 413 -439 l 247 0 l p ef +479 -520 m 479 -606 l 553 -606 l 553 -520 l p +479 0 m 479 -439 l 553 -439 l 553 0 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -49 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -253 ct 872 -260 916 -268 945 -278 ct +945 -288 945 -295 945 -298 ct 945 -328 938 -349 924 -362 ct 905 -379 877 -387 839 -387 ct +804 -387 778 -381 762 -369 ct 745 -356 733 -335 725 -303 ct 652 -313 l 659 -345 669 -370 685 -389 ct +700 -408 722 -423 750 -433 ct 779 -443 812 -449 850 -449 ct 888 -449 918 -444 941 -435 ct +965 -427 982 -415 993 -402 ct 1004 -389 1012 -372 1016 -351 ct 1019 -339 1020 -316 1020 -283 ct +1020 -184 l 1020 -114 1022 -71 1025 -52 ct 1028 -34 1034 -16 1044 0 ct 966 0 l +958 -15 l 953 -33 l p +945 -220 m 918 -209 877 -200 823 -192 ct 793 -187 771 -182 758 -177 ct 746 -171 736 -163 729 -153 ct +722 -142 719 -130 719 -117 ct 719 -98 726 -81 741 -68 ct 756 -55 778 -48 807 -48 ct +836 -48 861 -54 884 -67 ct 906 -79 922 -96 933 -118 ct 941 -135 945 -160 945 -193 ct +p ef +1759 -606 m 1839 -606 l 1839 -256 l 1839 -195 1832 -146 1818 -110 ct 1804 -75 1780 -45 1744 -23 ct +1708 0 1660 10 1602 10 ct 1545 10 1499 0 1463 -19 ct 1426 -38 1401 -66 1385 -104 ct +1370 -141 1362 -191 1362 -256 ct 1362 -606 l 1442 -606 l 1442 -256 l 1442 -203 1447 -164 1457 -139 ct +1467 -115 1484 -95 1507 -82 ct 1531 -68 1560 -62 1595 -62 ct 1654 -62 1696 -75 1721 -102 ct +1746 -128 1759 -180 1759 -256 ct p ef +1969 -194 m 2044 -201 l 2048 -171 2056 -146 2069 -126 ct 2082 -107 2103 -91 2130 -79 ct +2158 -67 2189 -61 2223 -61 ct 2254 -61 2281 -66 2304 -75 ct 2328 -84 2345 -96 2357 -112 ct +2368 -128 2374 -145 2374 -164 ct 2374 -183 2368 -200 2357 -214 ct 2346 -228 2328 -240 2303 -250 ct +2286 -256 2250 -266 2195 -279 ct 2139 -293 2100 -305 2078 -317 ct 2049 -332 2027 -351 2013 -374 ct +1999 -396 1992 -421 1992 -449 ct 1992 -480 2000 -508 2018 -535 ct 2035 -561 2061 -582 2094 -595 ct +2127 -609 2164 -616 2205 -616 ct 2250 -616 2290 -609 2324 -594 ct 2358 -580 2385 -559 2403 -531 ct +2422 -502 2432 -471 2433 -435 ct 2356 -429 l 2352 -468 2338 -496 2314 -516 ct +2290 -536 2255 -545 2208 -545 ct 2160 -545 2125 -537 2102 -519 ct 2080 -501 2069 -480 2069 -454 ct +2069 -433 2077 -415 2093 -401 ct 2108 -387 2148 -372 2214 -357 ct 2279 -343 2324 -330 2348 -319 ct +2383 -303 2409 -282 2426 -257 ct 2443 -232 2451 -203 2451 -171 ct 2451 -138 2442 -108 2423 -80 ct +2405 -51 2378 -29 2344 -13 ct 2309 2 2270 10 2227 10 ct 2172 10 2126 2 2089 -13 ct +2052 -29 2023 -53 2002 -85 ct 1981 -117 l 1970 -154 l p ef +2576 0 m 2576 -606 l 2803 -606 l 2849 -606 2886 -600 2914 -587 ct 2942 -575 2964 -556 2980 -531 ct +2996 -505 3004 -479 3004 -451 ct 3004 -425 2997 -400 2983 -378 ct 2969 -355 2948 -336 2919 -322 ct +2956 -311 2984 -293 3004 -267 ct 3024 -241 3033 -211 3033 -175 ct 3033 -147 3027 -120 3015 -96 ct +3003 -72 2989 -53 2971 -40 ct 2953 -26 2931 -16 2905 -10 ct 2878 -3 2845 0 2807 0 ct +p +2656 -351 m 2787 -351 l 2822 -351 2848 -353 2863 -358 ct 2884 -364 2899 -374 2909 -388 ct +2920 -402 2925 -420 2925 -441 ct 2925 -461 2920 -479 2911 -494 ct 2901 -510 2887 -520 2869 -526 ct +2851 -531 2821 -534 2777 -534 ct 2656 -534 l p +2656 -71 m 2807 -71 l 2833 -71 2851 -72 2861 -74 ct 2880 -77 2895 -83 2908 -90 ct +2920 -98 2930 -109 2938 -124 ct 2946 -139 2950 -156 2950 -175 ct 2950 -198 2944 -218 2933 -234 ct +2921 -251 2905 -263 2885 -269 ct 2864 -276 2835 -279 2796 -279 ct 2656 -279 l +p ef +pom +gr +gs +pum +6825 19235 t +497 -212 m 578 -192 l 561 -126 531 -76 487 -41 ct 443 -6 390 10 327 10 ct +261 10 208 -2 167 -29 ct 126 -56 95 -94 74 -145 ct 52 -195 42 -249 42 -307 ct 42 -370 54 -425 78 -472 ct +102 -519 136 -555 181 -580 ct 225 -604 274 -616 328 -616 ct 389 -616 440 -601 481 -570 ct +522 -539 551 -496 567 -440 ct 488 -421 l 474 -465 454 -497 427 -517 ct 400 -537 367 -547 326 -547 ct +280 -547 241 -536 209 -514 ct 178 -492 156 -462 143 -424 ct 131 -386 124 -348 124 -308 ct +124 -256 132 -211 147 -173 ct 162 -134 185 -105 217 -86 ct 249 -67 283 -58 320 -58 ct +365 -58 403 -71 434 -97 ct 465 -123 l 486 -161 l p ef +991 -141 m 1068 -131 l 1056 -86 1033 -52 1001 -27 ct 968 -2 926 9 875 9 ct +811 9 760 -9 722 -49 ct 684 -88 666 -144 666 -215 ct 666 -289 685 -347 723 -387 ct +761 -428 810 -449 871 -449 ct 929 -449 977 -429 1015 -389 ct 1052 -349 1070 -292 1070 -220 ct +1070 -216 1070 -209 1070 -200 ct 742 -200 l 745 -152 759 -115 783 -89 ct 808 -64 839 -51 875 -51 ct +903 -51 926 -58 945 -72 ct 964 -87 l 980 -110 l p +747 -261 m 992 -261 l 989 -298 979 -326 964 -344 ct 940 -373 909 -387 871 -387 ct +837 -387 809 -376 785 -353 ct 762 -330 l 749 -300 l p ef +1166 0 m 1166 -439 l 1233 -439 l 1233 -376 l 1266 -425 1312 -449 1373 -449 ct +1400 -449 1424 -444 1446 -434 ct 1468 -425 1485 -412 1496 -397 ct 1507 -382 1515 -363 1519 -342 ct +1522 -328 1523 -304 1523 -270 ct 1523 0 l 1449 0 l 1449 -267 l 1449 -297 1446 -320 1440 -335 ct +1434 -350 1424 -362 1409 -371 ct 1395 -380 1377 -384 1357 -384 ct 1326 -384 1298 -374 1275 -354 ct +1252 -334 1241 -296 1241 -239 ct 1241 0 l p ef +1806 -66 m 1817 0 l 1796 3 1777 5 1760 5 ct 1733 5 1712 1 1698 -7 ct 1683 -15 1672 -26 1666 -40 ct +1660 -54 1657 -83 1657 -128 ct 1657 -381 l 1602 -381 l 1602 -439 l 1657 -439 l +1657 -547 l 1731 -592 l 1731 -439 l 1806 -439 l 1806 -381 l 1731 -381 l +1731 -124 l 1731 -103 1732 -89 1735 -83 ct 1738 -77 1742 -72 1748 -69 ct 1754 -65 1762 -63 1773 -63 ct +1781 -63 l 1792 -64 l p ef +2182 -141 m 2259 -131 l 2247 -86 2224 -52 2192 -27 ct 2159 -2 2117 9 2066 9 ct +2002 9 1951 -9 1913 -49 ct 1875 -88 1857 -144 1857 -215 ct 1857 -289 1876 -347 1914 -387 ct +1952 -428 2001 -449 2062 -449 ct 2120 -449 2168 -429 2206 -389 ct 2243 -349 2261 -292 2261 -220 ct +2261 -216 2261 -209 2261 -200 ct 1933 -200 l 1936 -152 1950 -115 1974 -89 ct +1999 -64 2030 -51 2066 -51 ct 2094 -51 2117 -58 2136 -72 ct 2155 -87 l 2171 -110 l +p +1938 -261 m 2183 -261 l 2180 -298 2170 -326 2155 -344 ct 2131 -373 2100 -387 2062 -387 ct +2028 -387 2000 -376 1976 -353 ct 1953 -330 l 1940 -300 l p ef +2357 0 m 2357 -439 l 2424 -439 l 2424 -372 l 2441 -403 2456 -424 2471 -434 ct +2485 -444 2501 -449 2519 -449 ct 2544 -449 2569 -441 2595 -425 ct 2570 -356 l +2551 -366 2533 -372 2515 -372 ct 2499 -372 2484 -367 2471 -357 ct 2458 -347 2449 -334 2443 -316 ct +2435 -290 2431 -261 2431 -229 ct 2431 0 l p ef +2904 0 m 2904 -381 l 2838 -381 l 2838 -439 l 2904 -439 l 2904 -485 l +2904 -515 2907 -537 2912 -551 ct 2919 -571 2932 -586 2950 -598 ct 2968 -610 2993 -616 3026 -616 ct +3047 -616 3070 -614 3095 -609 ct 3084 -544 l 3069 -547 3054 -548 3040 -548 ct +3018 -548 3002 -543 2992 -533 ct 2983 -524 2978 -506 2978 -479 ct 2978 -439 l +3064 -439 l 3064 -381 l 2978 -381 l 2978 0 l p ef +3124 0 m 3124 -439 l 3191 -439 l 3191 -372 l 3208 -403 3223 -424 3238 -434 ct +3252 -444 3268 -449 3286 -449 ct 3311 -449 3336 -441 3362 -425 ct 3337 -356 l +3318 -366 3300 -372 3282 -372 ct 3266 -372 3251 -367 3238 -357 ct 3225 -347 3216 -334 3210 -316 ct +3202 -290 3198 -261 3198 -229 ct 3198 0 l p ef +3716 -141 m 3793 -131 l 3781 -86 3758 -52 3726 -27 ct 3693 -2 3651 9 3600 9 ct +3536 9 3485 -9 3447 -49 ct 3409 -88 3391 -144 3391 -215 ct 3391 -289 3410 -347 3448 -387 ct +3486 -428 3535 -449 3596 -449 ct 3654 -449 3702 -429 3740 -389 ct 3777 -349 3795 -292 3795 -220 ct +3795 -216 3795 -209 3795 -200 ct 3467 -200 l 3470 -152 3484 -115 3508 -89 ct +3533 -64 3564 -51 3600 -51 ct 3628 -51 3651 -58 3670 -72 ct 3689 -87 l 3705 -110 l +p +3472 -261 m 3717 -261 l 3714 -298 3704 -326 3689 -344 ct 3665 -373 3634 -387 3596 -387 ct +3562 -387 3534 -376 3510 -353 ct 3487 -330 l 3474 -300 l p ef +4171 168 m 4171 -46 l 4160 -30 4144 -16 4123 -6 ct 4102 4 4080 9 4056 9 ct +4004 9 3959 -10 3922 -52 ct 3884 -94 3865 -151 3865 -223 ct 3865 -267 3873 -307 3888 -342 ct +3904 -377 3926 -404 3955 -422 ct 3984 -440 4016 -449 4051 -449 ct 4105 -449 4148 -426 4179 -380 ct +4179 -439 l 4246 -439 l 4246 168 l p +3942 -220 m 3942 -164 3954 -121 3977 -93 ct 4001 -65 4029 -51 4063 -51 ct 4094 -51 4122 -64 4144 -91 ct +4167 -118 4179 -159 4179 -214 ct 4179 -272 4167 -316 4143 -346 ct 4118 -375 4090 -390 4058 -390 ct +4025 -390 3998 -376 3975 -349 ct 3953 -321 l 3942 -279 l p ef +4656 0 m 4656 -64 l 4622 -14 4576 9 4517 9 ct 4491 9 4467 4 4444 -4 ct 4422 -14 4405 -27 4394 -42 ct +4383 -57 4376 -75 4371 -97 ct 4368 -112 4367 -135 4367 -167 ct 4367 -439 l 4441 -439 l +4441 -195 l 4441 -156 4443 -130 4446 -117 ct 4450 -97 4460 -82 4475 -70 ct +4491 -59 4509 -54 4532 -54 ct 4554 -54 4575 -59 4595 -71 ct 4614 -82 4628 -98 4636 -118 ct +4644 -137 4648 -166 4648 -203 ct 4648 -439 l 4723 -439 l 4723 0 l p ef +5145 -141 m 5222 -131 l 5210 -86 5187 -52 5155 -27 ct 5122 -2 5080 9 5029 9 ct +4965 9 4914 -9 4876 -49 ct 4838 -88 4820 -144 4820 -215 ct 4820 -289 4839 -347 4877 -387 ct +4915 -428 4964 -449 5025 -449 ct 5083 -449 5131 -429 5169 -389 ct 5206 -349 5224 -292 5224 -220 ct +5224 -216 5224 -209 5224 -200 ct 4896 -200 l 4899 -152 4913 -115 4937 -89 ct +4962 -64 4993 -51 5029 -51 ct 5057 -51 5080 -58 5099 -72 ct 5118 -87 l 5134 -110 l +p +4901 -261 m 5146 -261 l 5143 -298 5133 -326 5118 -344 ct 5094 -373 5063 -387 5025 -387 ct +4991 -387 4963 -376 4939 -353 ct 4916 -330 l 4903 -300 l p ef +5320 0 m 5320 -439 l 5387 -439 l 5387 -376 l 5420 -425 5466 -449 5527 -449 ct +5554 -449 5578 -444 5600 -434 ct 5622 -425 5639 -412 5650 -397 ct 5661 -382 5669 -363 5673 -342 ct +5676 -328 5677 -304 5677 -270 ct 5677 0 l 5603 0 l 5603 -267 l 5603 -297 5600 -320 5594 -335 ct +5588 -350 5578 -362 5563 -371 ct 5549 -380 5531 -384 5511 -384 ct 5480 -384 5452 -374 5429 -354 ct +5406 -334 5395 -296 5395 -239 ct 5395 0 l p ef +6083 -160 m 6156 -151 l 6148 -100 6128 -61 6095 -32 ct 6062 -4 6021 9 5973 9 ct +5913 9 5865 -9 5828 -49 ct 5792 -88 5774 -144 5774 -217 ct 5774 -265 5781 -306 5797 -342 ct +5813 -378 5837 -404 5869 -422 ct 5901 -440 5936 -449 5974 -449 ct 6021 -449 6060 -437 6091 -412 ct +6121 -388 6141 -354 6149 -310 ct 6077 -299 l 6070 -328 6058 -350 6040 -365 ct +6023 -380 6001 -387 5977 -387 ct 5939 -387 5909 -374 5885 -347 ct 5862 -320 5850 -278 5850 -220 ct +5850 -161 5861 -118 5884 -91 ct 5907 -64 5936 -51 5973 -51 ct 6002 -51 6026 -60 6046 -78 ct +6065 -96 l 6078 -123 l p ef +6217 169 m 6209 99 l 6225 103 6239 105 6251 105 ct 6268 105 6281 103 6291 97 ct +6301 92 6309 84 6315 74 ct 6320 66 6328 48 6338 19 ct 6340 14 6342 8 6345 0 ct +6178 -439 l 6258 -439 l 6350 -184 l 6362 -152 6372 -118 6382 -83 ct 6390 -117 6400 -150 6412 -183 ct +6506 -439 l 6581 -439 l 6413 7 l 6396 55 6382 88 6372 107 ct 6358 131 6343 149 6326 161 ct +6309 172 6289 178 6265 178 ct 6251 178 l 6235 175 l p ef +pom +pum +7778 20188 t +26 -181 m 26 -256 l 255 -256 l 255 -181 l p ef +364 0 m 364 -381 l 298 -381 l 298 -439 l 364 -439 l 364 -485 l 364 -515 367 -537 372 -551 ct +379 -571 392 -586 410 -598 ct 428 -610 453 -616 486 -616 ct 507 -616 530 -614 555 -609 ct +544 -544 l 529 -547 514 -548 500 -548 ct 478 -548 462 -543 452 -533 ct 443 -524 438 -506 438 -479 ct +438 -439 l 524 -439 l 524 -381 l 438 -381 l 438 0 l p ef +555 -131 m 628 -142 l 632 -113 644 -90 663 -74 ct 682 -59 708 -51 742 -51 ct +776 -51 801 -58 818 -72 ct 835 -86 843 -102 843 -121 ct 843 -138 836 -151 821 -160 ct +811 -167 785 -175 745 -186 ct 690 -199 652 -211 631 -221 ct 610 -231 594 -245 583 -263 ct +572 -281 567 -301 567 -322 ct 567 -342 571 -360 580 -376 ct 589 -393 602 -407 617 -418 ct +629 -427 644 -434 664 -440 ct 684 -446 706 -449 729 -449 ct 763 -449 793 -444 819 -434 ct +846 -424 865 -410 877 -393 ct 890 -376 898 -354 903 -325 ct 830 -315 l 827 -338 817 -356 801 -368 ct +785 -381 763 -387 734 -387 ct 700 -387 675 -382 661 -370 ct 646 -359 639 -346 639 -331 ct +639 -321 642 -312 648 -305 ct 654 -297 664 -290 677 -285 ct 684 -282 706 -276 742 -266 ct +795 -252 832 -240 853 -231 ct 873 -222 890 -209 902 -192 ct 913 -175 919 -154 919 -129 ct +919 -104 912 -80 898 -58 ct 883 -37 862 -20 835 -8 ct 808 3 777 9 742 9 ct 685 9 642 -1 612 -25 ct +582 -49 l 563 -84 l p ef +926 10 m 1101 -616 l 1161 -616 l 985 10 l p ef +1590 -71 m 1590 0 l 1189 0 l 1189 -17 1191 -35 1198 -51 ct 1208 -79 1224 -105 1247 -132 ct +1269 -158 1302 -189 1344 -224 ct 1410 -278 1455 -321 1478 -352 ct 1501 -384 1513 -413 1513 -442 ct +1513 -471 1502 -496 1481 -516 ct 1460 -537 1432 -547 1398 -547 ct 1363 -547 1334 -536 1312 -514 ct +1291 -493 1280 -463 1280 -425 ct 1203 -433 l 1208 -490 1228 -533 1262 -563 ct +1297 -593 1342 -608 1400 -608 ct 1458 -608 1504 -592 1538 -560 ct 1572 -528 1589 -488 1589 -440 ct +1589 -416 1584 -392 1574 -368 ct 1564 -345 1548 -320 1525 -294 ct 1502 -268 1463 -233 1410 -188 ct +1365 -150 1337 -125 1324 -111 ct 1311 -98 1301 -85 1293 -71 ct p ef +2097 -66 m 2108 0 l 2087 3 2068 5 2051 5 ct 2024 5 2003 1 1989 -7 ct 1974 -15 1963 -26 1957 -40 ct +1951 -54 1948 -83 1948 -128 ct 1948 -381 l 1893 -381 l 1893 -439 l 1948 -439 l +1948 -547 l 2022 -592 l 2022 -439 l 2097 -439 l 2097 -381 l 2022 -381 l +2022 -124 l 2022 -103 2023 -89 2026 -83 ct 2029 -77 2033 -72 2039 -69 ct 2045 -65 2053 -63 2064 -63 ct +2072 -63 l 2083 -64 l p ef +2145 -219 m 2145 -300 2167 -361 2212 -400 ct 2250 -432 2296 -449 2351 -449 ct +2411 -449 2460 -429 2499 -389 ct 2537 -350 2556 -295 2556 -225 ct 2556 -169 2548 -124 2531 -92 ct +2514 -60 2489 -34 2457 -16 ct 2424 0 2389 9 2351 9 ct 2289 9 2239 -9 2201 -49 ct +2164 -88 l 2145 -145 l p +2221 -219 m 2221 -163 2233 -121 2258 -93 ct 2282 -65 2313 -51 2351 -51 ct 2388 -51 2418 -65 2443 -93 ct +2467 -121 2480 -164 2480 -222 ct 2480 -276 2467 -317 2443 -345 ct 2418 -373 2387 -387 2351 -387 ct +2313 -387 2282 -373 2258 -345 ct 2233 -317 l 2221 -275 l p ef +3043 -98 m 3043 -264 l 2878 -264 l 2878 -333 l 3043 -333 l 3043 -498 l +3113 -498 l 3113 -333 l 3278 -333 l 3278 -264 l 3113 -264 l 3113 -98 l +p ef +3407 0 m 3407 -381 l 3341 -381 l 3341 -439 l 3407 -439 l 3407 -485 l +3407 -515 3410 -537 3415 -551 ct 3422 -571 3435 -586 3453 -598 ct 3471 -610 3496 -616 3529 -616 ct +3550 -616 3573 -614 3598 -609 ct 3587 -544 l 3572 -547 3557 -548 3543 -548 ct +3521 -548 3505 -543 3495 -533 ct 3486 -524 3481 -506 3481 -479 ct 3481 -439 l +3567 -439 l 3567 -381 l 3481 -381 l 3481 0 l p ef +3598 -131 m 3671 -142 l 3675 -113 3687 -90 3706 -74 ct 3725 -59 3751 -51 3785 -51 ct +3819 -51 3844 -58 3861 -72 ct 3878 -86 3886 -102 3886 -121 ct 3886 -138 3879 -151 3864 -160 ct +3854 -167 3828 -175 3788 -186 ct 3733 -199 3695 -211 3674 -221 ct 3653 -231 3637 -245 3626 -263 ct +3615 -281 3610 -301 3610 -322 ct 3610 -342 3614 -360 3623 -376 ct 3632 -393 3645 -407 3660 -418 ct +3672 -427 3687 -434 3707 -440 ct 3727 -446 3749 -449 3772 -449 ct 3806 -449 3836 -444 3862 -434 ct +3889 -424 3908 -410 3920 -393 ct 3933 -376 3941 -354 3946 -325 ct 3873 -315 l +3870 -338 3860 -356 3844 -368 ct 3828 -381 3806 -387 3777 -387 ct 3743 -387 3718 -382 3704 -370 ct +3689 -359 3682 -346 3682 -331 ct 3682 -321 3685 -312 3691 -305 ct 3697 -297 3707 -290 3720 -285 ct +3727 -282 3749 -276 3785 -266 ct 3838 -252 3875 -240 3896 -231 ct 3916 -222 3933 -209 3945 -192 ct +3956 -175 3962 -154 3962 -129 ct 3962 -104 3955 -80 3941 -58 ct 3926 -37 3905 -20 3878 -8 ct +3851 3 3820 9 3785 9 ct 3728 9 3685 -1 3655 -25 ct 3625 -49 l 3606 -84 l p ef +3969 10 m 4144 -616 l 4204 -616 l 4028 10 l p ef +4633 -71 m 4633 0 l 4232 0 l 4232 -17 4234 -35 4241 -51 ct 4251 -79 4267 -105 4290 -132 ct +4312 -158 4345 -189 4387 -224 ct 4453 -278 4498 -321 4521 -352 ct 4544 -384 4556 -413 4556 -442 ct +4556 -471 4545 -496 4524 -516 ct 4503 -537 4475 -547 4441 -547 ct 4406 -547 4377 -536 4355 -514 ct +4334 -493 4323 -463 4323 -425 ct 4246 -433 l 4251 -490 4271 -533 4305 -563 ct +4340 -593 4385 -608 4443 -608 ct 4501 -608 4547 -592 4581 -560 ct 4615 -528 4632 -488 4632 -440 ct +4632 -416 4627 -392 4617 -368 ct 4607 -345 4591 -320 4568 -294 ct 4545 -268 4506 -233 4453 -188 ct +4408 -150 4380 -125 4367 -111 ct 4354 -98 4344 -85 4336 -71 ct p ef +pom +gr +10161 16546 m 10011 16996 l 10311 16995 l 10161 16546 l p ef +10161 18381 m 10161 16906 l ps +gs +pum +2805 3466 t +38 -194 m 113 -201 l 117 -171 125 -146 138 -126 ct 151 -107 172 -91 199 -79 ct +227 -67 258 -61 292 -61 ct 323 -61 350 -66 373 -75 ct 397 -84 414 -96 426 -112 ct +437 -128 443 -145 443 -164 ct 443 -183 437 -200 426 -214 ct 415 -228 397 -240 372 -250 ct +355 -256 319 -266 264 -279 ct 208 -293 169 -305 147 -317 ct 118 -332 96 -351 82 -374 ct +68 -396 61 -421 61 -449 ct 61 -480 69 -508 87 -535 ct 104 -561 130 -582 163 -595 ct +196 -609 233 -616 274 -616 ct 319 -616 359 -609 393 -594 ct 427 -580 454 -559 472 -531 ct +491 -502 501 -471 502 -435 ct 425 -429 l 421 -468 407 -496 383 -516 ct 359 -536 324 -545 277 -545 ct +229 -545 194 -537 171 -519 ct 149 -501 138 -480 138 -454 ct 138 -433 146 -415 162 -401 ct +177 -387 217 -372 283 -357 ct 348 -343 393 -330 417 -319 ct 452 -303 478 -282 495 -257 ct +512 -232 520 -203 520 -171 ct 520 -138 511 -108 492 -80 ct 474 -51 447 -29 413 -13 ct +378 2 339 10 296 10 ct 241 10 195 2 158 -13 ct 121 -29 92 -53 71 -85 ct 50 -117 l +39 -154 l p ef +924 -54 m 896 -30 870 -14 844 -4 ct 819 5 791 9 762 9 ct 714 9 677 -1 651 -25 ct +625 -49 612 -79 612 -115 ct 612 -137 617 -156 627 -174 ct 637 -192 649 -206 665 -217 ct +681 -228 699 -236 719 -241 ct 733 -245 755 -249 785 -253 ct 845 -260 889 -268 918 -278 ct +918 -288 918 -295 918 -298 ct 918 -328 911 -349 897 -362 ct 878 -379 850 -387 812 -387 ct +777 -387 751 -381 735 -369 ct 718 -356 706 -335 698 -303 ct 625 -313 l 632 -345 642 -370 658 -389 ct +673 -408 695 -423 723 -433 ct 752 -443 785 -449 823 -449 ct 861 -449 891 -444 914 -435 ct +938 -427 955 -415 966 -402 ct 977 -389 985 -372 989 -351 ct 992 -339 993 -316 993 -283 ct +993 -184 l 993 -114 995 -71 998 -52 ct 1001 -34 1007 -16 1017 0 ct 939 0 l +931 -15 l 926 -33 l p +918 -220 m 891 -209 850 -200 796 -192 ct 766 -187 744 -182 731 -177 ct 719 -171 709 -163 702 -153 ct +695 -142 692 -130 692 -117 ct 692 -98 699 -81 714 -68 ct 729 -55 751 -48 780 -48 ct +809 -48 834 -54 857 -67 ct 879 -79 895 -96 906 -118 ct 914 -135 918 -160 918 -193 ct +p ef +1087 0 m 1087 -439 l 1154 -439 l 1154 -377 l 1168 -399 1186 -416 1209 -429 ct +1232 -442 1258 -449 1287 -449 ct 1320 -449 1346 -442 1367 -428 ct 1388 -415 1403 -396 1411 -372 ct +1446 -423 1491 -449 1547 -449 ct 1590 -449 1624 -437 1647 -412 ct 1671 -388 1682 -351 1682 -301 ct +1682 0 l 1608 0 l 1608 -276 l 1608 -306 1606 -327 1601 -340 ct 1596 -354 1588 -364 1575 -372 ct +1562 -380 1547 -384 1530 -384 ct 1499 -384 1474 -374 1453 -353 ct 1433 -333 1423 -300 1423 -255 ct +1423 0 l 1348 0 l 1348 -285 l 1348 -318 1342 -343 1330 -359 ct 1318 -376 1298 -384 1271 -384 ct +1250 -384 1230 -379 1212 -368 ct 1195 -357 1182 -340 1174 -319 ct 1166 -298 1162 -267 1162 -227 ct +1162 0 l p ef +1801 168 m 1801 -439 l 1869 -439 l 1869 -382 l 1885 -404 1903 -421 1923 -432 ct +1943 -443 1968 -449 1997 -449 ct 2034 -449 2067 -439 2096 -420 ct 2124 -400 2146 -373 2161 -338 ct +2175 -303 2183 -264 2183 -222 ct 2183 -177 2175 -137 2158 -101 ct 2142 -65 2119 -37 2088 -18 ct +2057 0 2025 9 1991 9 ct 1966 9 1944 4 1924 -5 ct 1905 -16 1888 -29 1876 -45 ct +1876 168 l p +1869 -217 m 1869 -160 1880 -118 1903 -91 ct 1926 -64 1954 -51 1986 -51 ct 2019 -51 2048 -65 2071 -93 ct +2095 -121 2107 -164 2107 -223 ct 2107 -279 2095 -321 2072 -349 ct 2049 -376 2022 -390 1990 -390 ct +1958 -390 1930 -376 1905 -346 ct 1881 -316 l 1869 -273 l p ef +2250 0 m 2250 -606 l 2324 -606 l 2324 0 l p ef +2437 -520 m 2437 -606 l 2511 -606 l 2511 -520 l p +2437 0 m 2437 -439 l 2511 -439 l 2511 0 l p ef +2621 0 m 2621 -439 l 2688 -439 l 2688 -376 l 2721 -425 2767 -449 2828 -449 ct +2855 -449 2879 -444 2901 -434 ct 2923 -425 2940 -412 2951 -397 ct 2962 -382 2970 -363 2974 -342 ct +2977 -328 2978 -304 2978 -270 ct 2978 0 l 2904 0 l 2904 -267 l 2904 -297 2901 -320 2895 -335 ct +2889 -350 2879 -362 2864 -371 ct 2850 -380 2832 -384 2812 -384 ct 2781 -384 2753 -374 2730 -354 ct +2707 -334 2696 -296 2696 -239 ct 2696 0 l p ef +3085 36 m 3157 47 l 3160 69 3169 85 3182 95 ct 3201 109 3226 116 3258 116 ct +3292 116 3319 109 3338 95 ct 3357 82 3369 62 3376 38 ct 3380 22 3381 -8 3381 -57 ct +3349 -19 3308 0 3260 0 ct 3199 0 3153 -21 3119 -65 ct 3086 -108 3070 -161 3070 -222 ct +3070 -264 3077 -302 3093 -338 ct 3108 -373 3130 -400 3159 -420 ct 3187 -439 3221 -449 3260 -449 ct +3312 -449 3355 -428 3388 -386 ct 3388 -439 l 3457 -439 l 3457 -59 l 3457 8 3450 57 3436 85 ct +3422 114 3400 136 3370 153 ct 3340 169 3303 178 3258 178 ct 3206 178 3164 166 3131 142 ct +3099 119 l 3084 83 l p +3146 -227 m 3146 -169 3158 -127 3181 -101 ct 3204 -74 3232 -61 3267 -61 ct +3301 -61 3330 -74 3353 -101 ct 3376 -127 3387 -168 3387 -224 ct 3387 -278 3376 -319 3352 -346 ct +3328 -373 3299 -387 3265 -387 ct 3232 -387 3204 -374 3181 -347 ct 3158 -320 l +3146 -280 l p ef +3812 0 m 3812 -439 l 3879 -439 l 3879 -372 l 3896 -403 3911 -424 3926 -434 ct +3940 -444 3956 -449 3974 -449 ct 3999 -449 4024 -441 4050 -425 ct 4025 -356 l +4006 -366 3988 -372 3970 -372 ct 3954 -372 3939 -367 3926 -357 ct 3913 -347 3904 -334 3898 -316 ct +3890 -290 3886 -261 3886 -229 ct 3886 0 l p ef +4390 -54 m 4362 -30 4336 -14 4310 -4 ct 4285 5 4257 9 4228 9 ct 4180 9 4143 -1 4117 -25 ct +4091 -49 4078 -79 4078 -115 ct 4078 -137 4083 -156 4093 -174 ct 4103 -192 4115 -206 4131 -217 ct +4147 -228 4165 -236 4185 -241 ct 4199 -245 4221 -249 4251 -253 ct 4311 -260 4355 -268 4384 -278 ct +4384 -288 4384 -295 4384 -298 ct 4384 -328 4377 -349 4363 -362 ct 4344 -379 4316 -387 4278 -387 ct +4243 -387 4217 -381 4201 -369 ct 4184 -356 4172 -335 4164 -303 ct 4091 -313 l +4098 -345 4108 -370 4124 -389 ct 4139 -408 4161 -423 4189 -433 ct 4218 -443 4251 -449 4289 -449 ct +4327 -449 4357 -444 4380 -435 ct 4404 -427 4421 -415 4432 -402 ct 4443 -389 4451 -372 4455 -351 ct +4458 -339 4459 -316 4459 -283 ct 4459 -184 l 4459 -114 4461 -71 4464 -52 ct +4467 -34 4473 -16 4483 0 ct 4405 0 l 4397 -15 l 4392 -33 l p +4384 -220 m 4357 -209 4316 -200 4262 -192 ct 4232 -187 4210 -182 4197 -177 ct +4185 -171 4175 -163 4168 -153 ct 4161 -142 4158 -130 4158 -117 ct 4158 -98 4165 -81 4180 -68 ct +4195 -55 4217 -48 4246 -48 ct 4275 -48 4300 -54 4323 -67 ct 4345 -79 4361 -96 4372 -118 ct +4380 -135 4384 -160 4384 -193 ct p ef +4716 -66 m 4727 0 l 4706 3 4687 5 4670 5 ct 4643 5 4622 1 4608 -7 ct 4593 -15 4582 -26 4576 -40 ct +4570 -54 4567 -83 4567 -128 ct 4567 -381 l 4512 -381 l 4512 -439 l 4567 -439 l +4567 -547 l 4641 -592 l 4641 -439 l 4716 -439 l 4716 -381 l 4641 -381 l +4641 -124 l 4641 -103 4642 -89 4645 -83 ct 4648 -77 4652 -72 4658 -69 ct 4664 -65 4672 -63 4683 -63 ct +4691 -63 l 4702 -64 l p ef +5092 -141 m 5169 -131 l 5157 -86 5134 -52 5102 -27 ct 5069 -2 5027 9 4976 9 ct +4912 9 4861 -9 4823 -49 ct 4785 -88 4767 -144 4767 -215 ct 4767 -289 4786 -347 4824 -387 ct +4862 -428 4911 -449 4972 -449 ct 5030 -449 5078 -429 5116 -389 ct 5153 -349 5171 -292 5171 -220 ct +5171 -216 5171 -209 5171 -200 ct 4843 -200 l 4846 -152 4860 -115 4884 -89 ct +4909 -64 4940 -51 4976 -51 ct 5004 -51 5027 -58 5046 -72 ct 5065 -87 l 5081 -110 l +p +4848 -261 m 5093 -261 l 5090 -298 5080 -326 5065 -344 ct 5041 -373 5010 -387 4972 -387 ct +4938 -387 4910 -376 4886 -353 ct 4863 -330 l 4850 -300 l p ef +5897 -356 m 5497 -356 l 5497 -425 l 5897 -425 l p +5897 -172 m 5497 -172 l 5497 -241 l 5897 -241 l p ef +6264 0 m 6264 -381 l 6198 -381 l 6198 -439 l 6264 -439 l 6264 -485 l +6264 -515 6267 -537 6272 -551 ct 6279 -571 6292 -586 6310 -598 ct 6328 -610 6353 -616 6386 -616 ct +6407 -616 6430 -614 6455 -609 ct 6444 -544 l 6429 -547 6414 -548 6400 -548 ct +6378 -548 6362 -543 6352 -533 ct 6343 -524 6338 -506 6338 -479 ct 6338 -439 l +6424 -439 l 6424 -381 l 6338 -381 l 6338 0 l p ef +6455 -131 m 6528 -142 l 6532 -113 6544 -90 6563 -74 ct 6582 -59 6608 -51 6642 -51 ct +6676 -51 6701 -58 6718 -72 ct 6735 -86 6743 -102 6743 -121 ct 6743 -138 6736 -151 6721 -160 ct +6711 -167 6685 -175 6645 -186 ct 6590 -199 6552 -211 6531 -221 ct 6510 -231 6494 -245 6483 -263 ct +6472 -281 6467 -301 6467 -322 ct 6467 -342 6471 -360 6480 -376 ct 6489 -393 6502 -407 6517 -418 ct +6529 -427 6544 -434 6564 -440 ct 6584 -446 6606 -449 6629 -449 ct 6663 -449 6693 -444 6719 -434 ct +6746 -424 6765 -410 6777 -393 ct 6790 -376 6798 -354 6803 -325 ct 6730 -315 l +6727 -338 6717 -356 6701 -368 ct 6685 -381 6663 -387 6634 -387 ct 6600 -387 6575 -382 6561 -370 ct +6546 -359 6539 -346 6539 -331 ct 6539 -321 6542 -312 6548 -305 ct 6554 -297 6564 -290 6577 -285 ct +6584 -282 6606 -276 6642 -266 ct 6695 -252 6732 -240 6753 -231 ct 6773 -222 6790 -209 6802 -192 ct +6813 -175 6819 -154 6819 -129 ct 6819 -104 6812 -80 6798 -58 ct 6783 -37 6762 -20 6735 -8 ct +6708 3 6677 9 6642 9 ct 6585 9 6542 -1 6512 -25 ct 6482 -49 l 6463 -84 l p ef +pom +gr +gs +pum +15981 14102 t +62 0 m 62 -606 l 289 -606 l 335 -606 372 -600 400 -587 ct 428 -575 450 -556 466 -531 ct +482 -505 490 -479 490 -451 ct 490 -425 483 -400 469 -378 ct 455 -355 434 -336 405 -322 ct +442 -311 470 -293 490 -267 ct 510 -241 519 -211 519 -175 ct 519 -147 513 -120 501 -96 ct +489 -72 475 -53 457 -40 ct 439 -26 417 -16 391 -10 ct 364 -3 331 0 293 0 ct p +142 -351 m 273 -351 l 308 -351 334 -353 349 -358 ct 370 -364 385 -374 395 -388 ct +406 -402 411 -420 411 -441 ct 411 -461 406 -479 397 -494 ct 387 -510 373 -520 355 -526 ct +337 -531 307 -534 263 -534 ct 142 -534 l p +142 -71 m 293 -71 l 319 -71 337 -72 347 -74 ct 366 -77 381 -83 394 -90 ct +406 -98 416 -109 424 -124 ct 432 -139 436 -156 436 -175 ct 436 -198 430 -218 419 -234 ct +407 -251 391 -263 371 -269 ct 350 -276 321 -279 282 -279 ct 142 -279 l p ef +898 -54 m 870 -30 844 -14 818 -4 ct 793 5 765 9 736 9 ct 688 9 651 -1 625 -25 ct +599 -49 586 -79 586 -115 ct 586 -137 591 -156 601 -174 ct 611 -192 623 -206 639 -217 ct +655 -228 673 -236 693 -241 ct 707 -245 729 -249 759 -253 ct 819 -260 863 -268 892 -278 ct +892 -288 892 -295 892 -298 ct 892 -328 885 -349 871 -362 ct 852 -379 824 -387 786 -387 ct +751 -387 725 -381 709 -369 ct 692 -356 680 -335 672 -303 ct 599 -313 l 606 -345 616 -370 632 -389 ct +647 -408 669 -423 697 -433 ct 726 -443 759 -449 797 -449 ct 835 -449 865 -444 888 -435 ct +912 -427 929 -415 940 -402 ct 951 -389 959 -372 963 -351 ct 966 -339 967 -316 967 -283 ct +967 -184 l 967 -114 969 -71 972 -52 ct 975 -34 981 -16 991 0 ct 913 0 l 905 -15 l +900 -33 l p +892 -220 m 865 -209 824 -200 770 -192 ct 740 -187 718 -182 705 -177 ct 693 -171 683 -163 676 -153 ct +669 -142 666 -130 666 -117 ct 666 -98 673 -81 688 -68 ct 703 -55 725 -48 754 -48 ct +783 -48 808 -54 831 -67 ct 853 -79 869 -96 880 -118 ct 888 -135 892 -160 892 -193 ct +p ef +1060 0 m 1060 -439 l 1127 -439 l 1127 -376 l 1160 -425 1206 -449 1267 -449 ct +1294 -449 1318 -444 1340 -434 ct 1362 -425 1379 -412 1390 -397 ct 1401 -382 1409 -363 1413 -342 ct +1416 -328 1417 -304 1417 -270 ct 1417 0 l 1343 0 l 1343 -267 l 1343 -297 1340 -320 1334 -335 ct +1328 -350 1318 -362 1303 -371 ct 1289 -380 1271 -384 1251 -384 ct 1220 -384 1192 -374 1169 -354 ct +1146 -334 1135 -296 1135 -239 ct 1135 0 l p ef +1822 0 m 1822 -55 l 1794 -11 1754 9 1699 9 ct 1664 9 1632 0 1603 -19 ct 1574 -38 1551 -65 1535 -99 ct +1519 -134 1510 -174 1510 -219 ct 1510 -263 1518 -302 1532 -338 ct 1547 -374 1569 -401 1598 -420 ct +1627 -439 1660 -449 1696 -449 ct 1723 -449 1746 -443 1767 -432 ct 1788 -421 1804 -406 1817 -388 ct +1817 -606 l 1891 -606 l 1891 0 l p +1587 -219 m 1587 -162 1599 -120 1623 -93 ct 1646 -65 1674 -51 1706 -51 ct 1739 -51 1767 -64 1789 -91 ct +1812 -117 1824 -158 1824 -212 ct 1824 -273 1812 -317 1789 -345 ct 1766 -373 1737 -387 1703 -387 ct +1670 -387 1642 -374 1620 -346 ct 1598 -319 l 1587 -277 l p ef +2094 0 m 1960 -439 l 2037 -439 l 2107 -185 l 2133 -91 l 2134 -96 2142 -126 2156 -181 ct +2226 -439 l 2302 -439 l 2368 -184 l 2390 -100 l 2415 -185 l 2490 -439 l +2563 -439 l 2425 0 l 2348 0 l 2278 -263 l 2261 -337 l 2172 0 l p ef +2596 -520 m 2596 -606 l 2670 -606 l 2670 -520 l p +2596 0 m 2596 -439 l 2670 -439 l 2670 0 l p ef +3065 0 m 3065 -55 l 3037 -11 2997 9 2942 9 ct 2907 9 2875 0 2846 -19 ct 2817 -38 2794 -65 2778 -99 ct +2762 -134 2753 -174 2753 -219 ct 2753 -263 2761 -302 2775 -338 ct 2790 -374 2812 -401 2841 -420 ct +2870 -439 2903 -449 2939 -449 ct 2966 -449 2989 -443 3010 -432 ct 3031 -421 3047 -406 3060 -388 ct +3060 -606 l 3134 -606 l 3134 0 l p +2830 -219 m 2830 -162 2842 -120 2866 -93 ct 2889 -65 2917 -51 2949 -51 ct 2982 -51 3010 -64 3032 -91 ct +3055 -117 3067 -158 3067 -212 ct 3067 -273 3055 -317 3032 -345 ct 3009 -373 2980 -387 2946 -387 ct +2913 -387 2885 -374 2863 -346 ct 2841 -319 l 2830 -277 l p ef +3419 -66 m 3430 0 l 3409 3 3390 5 3373 5 ct 3346 5 3325 1 3311 -7 ct 3296 -15 3285 -26 3279 -40 ct +3273 -54 3270 -83 3270 -128 ct 3270 -381 l 3215 -381 l 3215 -439 l 3270 -439 l +3270 -547 l 3344 -592 l 3344 -439 l 3419 -439 l 3419 -381 l 3344 -381 l +3344 -124 l 3344 -103 3345 -89 3348 -83 ct 3351 -77 3355 -72 3361 -69 ct 3367 -65 3375 -63 3386 -63 ct +3394 -63 l 3405 -64 l p ef +3495 0 m 3495 -606 l 3570 -606 l 3570 -388 l 3605 -429 3648 -449 3701 -449 ct +3734 -449 3762 -442 3786 -429 ct 3810 -417 3827 -399 3838 -376 ct 3848 -354 3853 -321 3853 -278 ct +3853 0 l 3779 0 l 3779 -278 l 3779 -315 3771 -342 3754 -359 ct 3738 -376 3716 -385 3686 -385 ct +3664 -385 3643 -379 3624 -367 ct 3604 -356 3590 -340 3582 -321 ct 3574 -301 3570 -274 3570 -240 ct +3570 0 l p ef +pom +pum +15888 15055 t +340 0 m 340 -55 l 312 -11 272 9 217 9 ct 182 9 150 0 121 -19 ct 92 -38 69 -65 53 -99 ct +37 -134 28 -174 28 -219 ct 28 -263 36 -302 50 -338 ct 65 -374 87 -401 116 -420 ct +145 -439 178 -449 214 -449 ct 241 -449 264 -443 285 -432 ct 306 -421 322 -406 335 -388 ct +335 -606 l 409 -606 l 409 0 l p +105 -219 m 105 -162 117 -120 141 -93 ct 164 -65 192 -51 224 -51 ct 257 -51 285 -64 307 -91 ct +330 -117 342 -158 342 -212 ct 342 -273 330 -317 307 -345 ct 284 -373 255 -387 221 -387 ct +188 -387 160 -374 138 -346 ct 116 -319 l 105 -277 l p ef +832 -141 m 909 -131 l 897 -86 874 -52 842 -27 ct 809 -2 767 9 716 9 ct 652 9 601 -9 563 -49 ct +525 -88 507 -144 507 -215 ct 507 -289 526 -347 564 -387 ct 602 -428 651 -449 712 -449 ct +770 -449 818 -429 856 -389 ct 893 -349 911 -292 911 -220 ct 911 -216 911 -209 911 -200 ct +583 -200 l 586 -152 600 -115 624 -89 ct 649 -64 680 -51 716 -51 ct 744 -51 767 -58 786 -72 ct +805 -87 l 821 -110 l p +588 -261 m 833 -261 l 830 -298 820 -326 805 -344 ct 781 -373 750 -387 712 -387 ct +678 -387 650 -376 626 -353 ct 603 -330 l 590 -300 l p ef +1295 -160 m 1368 -151 l 1360 -100 1340 -61 1307 -32 ct 1274 -4 1233 9 1185 9 ct +1125 9 1077 -9 1040 -49 ct 1004 -88 986 -144 986 -217 ct 986 -265 993 -306 1009 -342 ct +1025 -378 1049 -404 1081 -422 ct 1113 -440 1148 -449 1186 -449 ct 1233 -449 1272 -437 1303 -412 ct +1333 -388 1353 -354 1361 -310 ct 1289 -299 l 1282 -328 1270 -350 1252 -365 ct +1235 -380 1213 -387 1189 -387 ct 1151 -387 1121 -374 1097 -347 ct 1074 -320 1062 -278 1062 -220 ct +1062 -161 1073 -118 1096 -91 ct 1119 -64 1148 -51 1185 -51 ct 1214 -51 1238 -60 1258 -78 ct +1277 -96 l 1290 -123 l p ef +1432 -520 m 1432 -606 l 1506 -606 l 1506 -520 l p +1432 0 m 1432 -439 l 1506 -439 l 1506 0 l p ef +1616 0 m 1616 -439 l 1683 -439 l 1683 -377 l 1697 -399 1715 -416 1738 -429 ct +1761 -442 1787 -449 1816 -449 ct 1849 -449 1875 -442 1896 -428 ct 1917 -415 1932 -396 1940 -372 ct +1975 -423 2020 -449 2076 -449 ct 2119 -449 2153 -437 2176 -412 ct 2200 -388 2211 -351 2211 -301 ct +2211 0 l 2137 0 l 2137 -276 l 2137 -306 2135 -327 2130 -340 ct 2125 -354 2117 -364 2104 -372 ct +2091 -380 2076 -384 2059 -384 ct 2028 -384 2003 -374 1982 -353 ct 1962 -333 1952 -300 1952 -255 ct +1952 0 l 1877 0 l 1877 -285 l 1877 -318 1871 -343 1859 -359 ct 1847 -376 1827 -384 1800 -384 ct +1779 -384 1759 -379 1741 -368 ct 1724 -357 1711 -340 1703 -319 ct 1695 -298 1691 -267 1691 -227 ct +1691 0 l p ef +2617 -54 m 2589 -30 2563 -14 2537 -4 ct 2512 5 2484 9 2455 9 ct 2407 9 2370 -1 2344 -25 ct +2318 -49 2305 -79 2305 -115 ct 2305 -137 2310 -156 2320 -174 ct 2330 -192 2342 -206 2358 -217 ct +2374 -228 2392 -236 2412 -241 ct 2426 -245 2448 -249 2478 -253 ct 2538 -260 2582 -268 2611 -278 ct +2611 -288 2611 -295 2611 -298 ct 2611 -328 2604 -349 2590 -362 ct 2571 -379 2543 -387 2505 -387 ct +2470 -387 2444 -381 2428 -369 ct 2411 -356 2399 -335 2391 -303 ct 2318 -313 l +2325 -345 2335 -370 2351 -389 ct 2366 -408 2388 -423 2416 -433 ct 2445 -443 2478 -449 2516 -449 ct +2554 -449 2584 -444 2607 -435 ct 2631 -427 2648 -415 2659 -402 ct 2670 -389 2678 -372 2682 -351 ct +2685 -339 2686 -316 2686 -283 ct 2686 -184 l 2686 -114 2688 -71 2691 -52 ct +2694 -34 2700 -16 2710 0 ct 2632 0 l 2624 -15 l 2619 -33 l p +2611 -220 m 2584 -209 2543 -200 2489 -192 ct 2459 -187 2437 -182 2424 -177 ct +2412 -171 2402 -163 2395 -153 ct 2388 -142 2385 -130 2385 -117 ct 2385 -98 2392 -81 2407 -68 ct +2422 -55 2444 -48 2473 -48 ct 2502 -48 2527 -54 2550 -67 ct 2572 -79 2588 -96 2599 -118 ct +2607 -135 2611 -160 2611 -193 ct p ef +2943 -66 m 2954 0 l 2933 3 2914 5 2897 5 ct 2870 5 2849 1 2835 -7 ct 2820 -15 2809 -26 2803 -40 ct +2797 -54 2794 -83 2794 -128 ct 2794 -381 l 2739 -381 l 2739 -439 l 2794 -439 l +2794 -547 l 2868 -592 l 2868 -439 l 2943 -439 l 2943 -381 l 2868 -381 l +2868 -124 l 2868 -103 2869 -89 2872 -83 ct 2875 -77 2879 -72 2885 -69 ct 2891 -65 2899 -63 2910 -63 ct +2918 -63 l 2929 -64 l p ef +3019 -520 m 3019 -606 l 3093 -606 l 3093 -520 l p +3019 0 m 3019 -439 l 3093 -439 l 3093 0 l p ef +3177 -219 m 3177 -300 3199 -361 3244 -400 ct 3282 -432 3328 -449 3383 -449 ct +3443 -449 3492 -429 3531 -389 ct 3569 -350 3588 -295 3588 -225 ct 3588 -169 3580 -124 3563 -92 ct +3546 -60 3521 -34 3489 -16 ct 3456 0 3421 9 3383 9 ct 3321 9 3271 -9 3233 -49 ct +3196 -88 l 3177 -145 l p +3253 -219 m 3253 -163 3265 -121 3290 -93 ct 3314 -65 3345 -51 3383 -51 ct 3420 -51 3450 -65 3475 -93 ct +3499 -121 3512 -164 3512 -222 ct 3512 -276 3499 -317 3475 -345 ct 3450 -373 3419 -387 3383 -387 ct +3345 -387 3314 -373 3290 -345 ct 3265 -317 l 3253 -275 l p ef +3680 0 m 3680 -439 l 3747 -439 l 3747 -376 l 3780 -425 3826 -449 3887 -449 ct +3914 -449 3938 -444 3960 -434 ct 3982 -425 3999 -412 4010 -397 ct 4021 -382 4029 -363 4033 -342 ct +4036 -328 4037 -304 4037 -270 ct 4037 0 l 3963 0 l 3963 -267 l 3963 -297 3960 -320 3954 -335 ct +3948 -350 3938 -362 3923 -371 ct 3909 -380 3891 -384 3871 -384 ct 3840 -384 3812 -374 3789 -354 ct +3766 -334 3755 -296 3755 -239 ct 3755 0 l p ef +pom +pum +16087 16008 t +73 0 m 73 -381 l 7 -381 l 7 -439 l 73 -439 l 73 -485 l 73 -515 76 -537 81 -551 ct +88 -571 101 -586 119 -598 ct 137 -610 162 -616 195 -616 ct 216 -616 239 -614 264 -609 ct +253 -544 l 238 -547 223 -548 209 -548 ct 187 -548 171 -543 161 -533 ct 152 -524 147 -506 147 -479 ct +147 -439 l 233 -439 l 233 -381 l 147 -381 l 147 0 l p ef +580 -54 m 552 -30 526 -14 500 -4 ct 475 5 447 9 418 9 ct 370 9 333 -1 307 -25 ct +281 -49 268 -79 268 -115 ct 268 -137 273 -156 283 -174 ct 293 -192 305 -206 321 -217 ct +337 -228 355 -236 375 -241 ct 389 -245 411 -249 441 -253 ct 501 -260 545 -268 574 -278 ct +574 -288 574 -295 574 -298 ct 574 -328 567 -349 553 -362 ct 534 -379 506 -387 468 -387 ct +433 -387 407 -381 391 -369 ct 374 -356 362 -335 354 -303 ct 281 -313 l 288 -345 298 -370 314 -389 ct +329 -408 351 -423 379 -433 ct 408 -443 441 -449 479 -449 ct 517 -449 547 -444 570 -435 ct +594 -427 611 -415 622 -402 ct 633 -389 641 -372 645 -351 ct 648 -339 649 -316 649 -283 ct +649 -184 l 649 -114 651 -71 654 -52 ct 657 -34 663 -16 673 0 ct 595 0 l 587 -15 l +582 -33 l p +574 -220 m 547 -209 506 -200 452 -192 ct 422 -187 400 -182 387 -177 ct 375 -171 365 -163 358 -153 ct +351 -142 348 -130 348 -117 ct 348 -98 355 -81 370 -68 ct 385 -55 407 -48 436 -48 ct +465 -48 490 -54 513 -67 ct 535 -79 551 -96 562 -118 ct 570 -135 574 -160 574 -193 ct +p ef +1030 -160 m 1103 -151 l 1095 -100 1075 -61 1042 -32 ct 1009 -4 968 9 920 9 ct +860 9 812 -9 775 -49 ct 739 -88 721 -144 721 -217 ct 721 -265 728 -306 744 -342 ct +760 -378 784 -404 816 -422 ct 848 -440 883 -449 921 -449 ct 968 -449 1007 -437 1038 -412 ct +1068 -388 1088 -354 1096 -310 ct 1024 -299 l 1017 -328 1005 -350 987 -365 ct +970 -380 948 -387 924 -387 ct 886 -387 856 -374 832 -347 ct 809 -320 797 -278 797 -220 ct +797 -161 808 -118 831 -91 ct 854 -64 883 -51 920 -51 ct 949 -51 973 -60 993 -78 ct +1012 -96 l 1025 -123 l p ef +1329 -66 m 1340 0 l 1319 3 1300 5 1283 5 ct 1256 5 1235 1 1221 -7 ct 1206 -15 1195 -26 1189 -40 ct +1183 -54 1180 -83 1180 -128 ct 1180 -381 l 1125 -381 l 1125 -439 l 1180 -439 l +1180 -547 l 1254 -592 l 1254 -439 l 1329 -439 l 1329 -381 l 1254 -381 l +1254 -124 l 1254 -103 1255 -89 1258 -83 ct 1261 -77 1265 -72 1271 -69 ct 1277 -65 1285 -63 1296 -63 ct +1304 -63 l 1315 -64 l p ef +1377 -219 m 1377 -300 1399 -361 1444 -400 ct 1482 -432 1528 -449 1583 -449 ct +1643 -449 1692 -429 1731 -389 ct 1769 -350 1788 -295 1788 -225 ct 1788 -169 1780 -124 1763 -92 ct +1746 -60 1721 -34 1689 -16 ct 1656 0 1621 9 1583 9 ct 1521 9 1471 -9 1433 -49 ct +1396 -88 l 1377 -145 l p +1453 -219 m 1453 -163 1465 -121 1490 -93 ct 1514 -65 1545 -51 1583 -51 ct 1620 -51 1650 -65 1675 -93 ct +1699 -121 1712 -164 1712 -222 ct 1712 -276 1699 -317 1675 -345 ct 1650 -373 1619 -387 1583 -387 ct +1545 -387 1514 -373 1490 -345 ct 1465 -317 l 1453 -275 l p ef +1881 0 m 1881 -439 l 1948 -439 l 1948 -372 l 1965 -403 1980 -424 1995 -434 ct +2009 -444 2025 -449 2043 -449 ct 2068 -449 2093 -441 2119 -425 ct 2094 -356 l +2075 -366 2057 -372 2039 -372 ct 2023 -372 2008 -367 1995 -357 ct 1982 -347 1973 -334 1967 -316 ct +1959 -290 1955 -261 1955 -229 ct 1955 0 l p ef +2802 -356 m 2402 -356 l 2402 -425 l 2802 -425 l p +2802 -172 m 2402 -172 l 2402 -241 l 2802 -241 l p ef +3160 0 m 3160 -606 l 3242 -606 l 3561 -130 l 3561 -606 l 3638 -606 l +3638 0 l 3555 0 l 3237 -476 l 3237 0 l p ef +pom +gr +17781 10461 m 17631 10911 l 17931 10910 l 17781 10461 l p ef +17781 13336 m 17781 10821 l ps +gs +pum +17357 3466 t +73 0 m 73 -381 l 7 -381 l 7 -439 l 73 -439 l 73 -485 l 73 -515 76 -537 81 -551 ct +88 -571 101 -586 119 -598 ct 137 -610 162 -616 195 -616 ct 216 -616 239 -614 264 -609 ct +253 -544 l 238 -547 223 -548 209 -548 ct 187 -548 171 -543 161 -533 ct 152 -524 147 -506 147 -479 ct +147 -439 l 233 -439 l 233 -381 l 147 -381 l 147 0 l p ef +264 -131 m 337 -142 l 341 -113 353 -90 372 -74 ct 391 -59 417 -51 451 -51 ct +485 -51 510 -58 527 -72 ct 544 -86 552 -102 552 -121 ct 552 -138 545 -151 530 -160 ct +520 -167 494 -175 454 -186 ct 399 -199 361 -211 340 -221 ct 319 -231 303 -245 292 -263 ct +281 -281 276 -301 276 -322 ct 276 -342 280 -360 289 -376 ct 298 -393 311 -407 326 -418 ct +338 -427 353 -434 373 -440 ct 393 -446 415 -449 438 -449 ct 472 -449 502 -444 528 -434 ct +555 -424 574 -410 586 -393 ct 599 -376 607 -354 612 -325 ct 539 -315 l 536 -338 526 -356 510 -368 ct +494 -381 472 -387 443 -387 ct 409 -387 384 -382 370 -370 ct 355 -359 348 -346 348 -331 ct +348 -321 351 -312 357 -305 ct 363 -297 373 -290 386 -285 ct 393 -282 415 -276 451 -266 ct +504 -252 541 -240 562 -231 ct 582 -222 599 -209 611 -192 ct 622 -175 628 -154 628 -129 ct +628 -104 621 -80 607 -58 ct 592 -37 571 -20 544 -8 ct 517 3 486 9 451 9 ct 394 9 351 -1 321 -25 ct +291 -49 l 272 -84 l p ef +635 10 m 810 -616 l 870 -616 l 694 10 l p ef +937 0 m 937 -606 l 1019 -606 l 1338 -130 l 1338 -606 l 1415 -606 l +1415 0 l 1332 0 l 1014 -476 l 1014 0 l p ef +pom +gr +22227 6350 m 22199 5876 l 21920 5987 l 22227 6350 l p ef +19422 3175 m 19475 3175 l ps +19528 3175 m 19581 3175 l ps +19634 3175 m 19687 3175 l ps +19740 3175 m 19793 3175 l ps +19846 3175 m 19899 3175 l ps +19952 3175 m 20006 3175 l ps +20059 3175 m 20112 3175 l ps +20165 3175 m 20218 3175 l ps +20271 3175 m 20324 3175 l ps +20377 3175 m 20430 3175 l ps +20483 3175 m 20536 3175 l ps +20590 3175 m 20643 3175 l ps +20696 3175 m 20749 3175 l ps +20802 3175 m 20855 3175 l ps +20908 3175 m 20956 3175 l ps +20956 3175 m 20958 3180 l ps +20977 3229 m 20997 3278 l ps +21017 3328 m 21037 3377 l ps +21056 3426 m 21076 3475 l ps +21096 3525 m 21115 3574 l ps +21135 3623 m 21155 3673 l ps +21175 3722 m 21194 3771 l ps +21214 3821 m 21234 3870 l ps +21254 3919 m 21273 3968 l ps +21293 4018 m 21313 4067 l ps +21332 4116 m 21352 4166 l ps +21372 4215 m 21392 4264 l ps +21411 4313 m 21431 4363 l ps +21451 4412 m 21471 4461 l ps +21490 4511 m 21510 4560 l ps +21530 4609 m 21550 4658 l ps +21569 4708 m 21589 4757 l ps +21609 4806 m 21628 4856 l ps +21648 4905 m 21668 4954 l ps +21688 5003 m 21707 5053 l ps +21727 5102 m 21747 5151 l ps +21767 5201 m 21786 5250 l ps +21806 5299 m 21826 5348 l ps +21845 5398 m 21865 5447 l ps +21885 5496 m 21905 5546 l ps +21924 5595 m 21944 5644 l ps +21964 5693 m 21984 5743 l ps +22003 5792 m 22023 5841 l ps +22043 5891 m 22063 5940 l ps +22082 5989 m 22093 6015 l ps +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/docs/exploring-gnuradio/ddc.png b/docs/exploring-gnuradio/ddc.png new file mode 100644 index 00000000..ce35bc2a Binary files /dev/null and b/docs/exploring-gnuradio/ddc.png differ diff --git a/docs/exploring-gnuradio/dial_tone.py b/docs/exploring-gnuradio/dial_tone.py new file mode 100755 index 00000000..3139ba3a --- /dev/null +++ b/docs/exploring-gnuradio/dial_tone.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio + +def build_graph (): + sampling_freq = 32000 + ampl = 0.1 + + fg = gr.flow_graph () + src0 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 350, ampl) + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 440, ampl) + dst = audio.sink (sampling_freq) + fg.connect (src0, (dst, 0)) + fg.connect (src1, (dst, 1)) + + return fg + +if __name__ == '__main__': + fg = build_graph () + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () diff --git a/docs/exploring-gnuradio/dial_tone_example.xml b/docs/exploring-gnuradio/dial_tone_example.xml new file mode 100644 index 00000000..14ea6803 --- /dev/null +++ b/docs/exploring-gnuradio/dial_tone_example.xml @@ -0,0 +1,28 @@ + +Dial Tone Output + +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio + +def build_graph (): + sampling_freq = 48000 + ampl = 0.1 + + fg = gr.flow_graph () + src0 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 350, ampl) + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 440, ampl) + dst = audio.sink (sampling_freq) + fg.connect ((src0, 0), (dst, 0)) + fg.connect ((src1, 0), (dst, 1)) + + return fg + +if __name__ == '__main__': + fg = build_graph () + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () + + diff --git a/docs/exploring-gnuradio/exploring-gnuradio.xml b/docs/exploring-gnuradio/exploring-gnuradio.xml new file mode 100644 index 00000000..9d471f66 --- /dev/null +++ b/docs/exploring-gnuradio/exploring-gnuradio.xml @@ -0,0 +1,460 @@ + + + +]> + +
+ + Exploring GNU Radio + + Eric + Blossom + +
+ eb@comsec.com +
+
+
+ + + + v1.1 + 2004-11-29 + + Revised and expanded. Examples now use 2.x code base. + + + + + v1.0 + 2004-02-29 + + Initial version published in Linux Journal, Issue 122, June 2004, as + GNU Radio: Tools for Exploring the RF Spectrum. + + + + +This article provides an overview of the GNU Radio +toolkit for building software radios. + + +
+ +Introduction + +Software radio is the technique of getting code as close to the +antenna as possible. It turns radio hardware problems into software +problems. The fundamental characteristic of software radio is that +software defines the transmitted waveforms, and software demodulates +the received waveforms. This is in contrast to most radios in which +the processing is done with either analog circuitry or analog +circuitry combined with digital chips. GNU Radio is a free software +toolkit for building software radios. + +Software radio is a revolution in radio design due to its ability to +create radios that change on the fly, creating new choices for +users. At the baseline, software radios can do pretty much anything a +traditional radio can do. The exciting part is the flexibility that +software provides you. Instead of a bunch of fixed function gadgets, +in the next few years we'll see a move to universal communication +devices. Imagine a device that can morph into a cell phone and get you +connectivity using GPRS, 802.11 Wi-Fi, 802.16 WiMax, a satellite +hookup or the emerging standard of the day. You could determine your +location using GPS, GLONASS or both. + +Perhaps most exciting of all is the potential to build decentralized +communication systems. If you look at today's systems, the vast +majority are infrastructure-based. Broadcast radio and TV provide a +one-way channel, are tightly regulated and the content is controlled +by a handful of organizations. Cell phones are a great convenience, +but the features your phone supports are determined by the operator's +interests, not yours. + +A centralized system limits the rate of innovation. We could take some +lessons from the Internet and push the smarts out to the +edges. Instead of cell phones being second-class citizens, usable only +if infrastructure is in place and limited to the capabilities +determined worthwhile by the operator, we could build smarter +devices. These user-owned devices would generate the network. They'd +create a mesh among themselves, negotiate for backhaul and be free to +evolve new solutions, features and applications. + + + +The Block Diagram + + shows a typical block +diagram for a software radio. To understand the software part of the +radio, we first need to understand a bit about the associated +hardware. Examining the receive path in the figure, +we see an antenna, a mysterious RF front end, an analog-to-digital +converter (ADC) and a bunch of code. The analog-to-digital converter +is the bridge between the physical world of continuous analog signals +and the world of discrete digital samples manipulated by +software. + +
Typical software radio block diagram + + + + + +
+ +ADCs have two primary characteristics, sampling rate and dynamic +range. Sampling rate is the number of times per second that the ADC +measures the analog signal. Dynamic range refers to the difference +between the smallest and largest signal that can be distinguished; +it's a function of the number of bits in the ADC's digital output and +the design of the converter. For example, an 8-bit converter at most +can represent 256 (28) signal levels, while +a 16-bit converter represents up to 65,536 levels. Generally speaking, +device physics and cost impose trade-offs between the sample rate and +dynamic range. + +Before we dive into the software, we need to talk about a bit of +theory. In 1927, a Swedish-born physicist and electrical engineer +named Harry Nyquist determined that to avoid aliasing when converting +from analog to digital, the ADC sampling frequency must be at least +twice the bandwidth of the signal of interest. Aliasing is what makes +the wagon wheels look like they're going backward in the old westerns: +the sampling rate of the movie camera is not fast enough to represent +the position of the spokes unambiguously. + +Assuming we're dealing with low pass signals - signals where the +bandwidth of interest goes from 0 to fMAX, the +Nyquist criterion states that our sampling frequency needs to be at +least 2 * fMAX. But if our ADC runs at 20 MHz, +how can we listen to broadcast FM radio at 92.1 MHz? The answer is the +RF front end. The receive RF front end translates a range of +frequencies appearing at its input to a lower range at its output. For +example, we could imagine an RF front end that translated the signals +occurring in the 90 - 100 MHz range down to the 0 - 10 MHz +range. + +Mostly, we can treat the RF front end as a black box with a single +control, the center of the input range that's to be translated. As a +concrete example, a cable modem tuner module that we've employed +successfully has the following characteristics. It translates a 6 MHz +chunk of the spectrum centered between about 50 MHz and 800 MHz down to +an output range centered at 5.75 MHz. The center frequency of the +output range is called the intermediate frequency, or IF. + +In the simplest-thing-that-possibly-could-work category, the RF front +end may be eliminated altogether. One GNU Radio experimenter has +listened to AM and shortwave broadcasts by connecting a 100-foot piece +of wire directly to his 20M sample/sec ADC. + +
+ +On to the Software + +GNU Radio provides a library of signal processing blocks and the +glue to tie it all together. The programmer builds a radio by creating +a graph (as in graph theory) where the vertices are signal processing +blocks and the edges represent the data flow between them. The +signal processing blocks are implemented in C++. Conceptually, +blocks process infinite streams of data flowing from their input +ports to their output ports. Blocks' attributes include the number +of input and output ports they have as well as the type of data that +flows through each. The most frequently used types are short, float +and complex. + +Some blocks have only output ports or input ports. These serve as +data sources and sinks in the graph. There are sources that read from +a file or ADC, and sinks that write to a file, digital-to-analog +converter (DAC) or graphical display. About 100 blocks come with +GNU Radio. Writing new blocks is not difficult. + +Graphs are constructed and run in Python. + +Example 1 +is the "Hello World" of GNU Radio. It generates two sine waves and outputs +them to the sound card, one on the left channel, one on the +right. + +&dial_tone_example; + +We start by creating a flow graph to hold the blocks and +connections between them. The two sine waves are generated by the +gr.sig_source_f calls. The f suffix indicates that the source produces +floats. One sine wave is at 350 Hz, and the other is at +440 Hz. Together, they sound like the US dial tone. + +audio.sink is a sink that writes its input to the sound card. It +takes one or more streams of floats in the range -1 to +1 as its +input. We connect the three blocks together using the +connect method of the flow graph. + +connect takes two parameters, the +source endpoint and the destination endpoint, and creates a connection +from the source to the destination. An endpoint has two components: a +signal processing block and a port number. The port number specifies +which input or output port of the specified block is to be connected. +In the most general form, an endpoint is represented as a python tuple +like this: (block, port_number). When +port_number is zero, the block may be used alone. + + +These two expressions are equivalent: + +fg.connect ((src1, 0), (dst, 1)) +fg.connect (src1, (dst, 1)) + + +Once the graph is built, we start it. Calling +start forks one or more threads to run the +computation described by the graph and returns control immediately to +the caller. In this case, we simply wait for any keystroke. + + + +A Complete FM Receiver + + + +Example 2 +shows a somewhat simplified but +complete broadcast FM receiver. It includes control of the RF front +end and all required signal processing. This example uses an RF front +end built from a cable modem tuner and a 20M sample/sec +analog-to-digital converter. + +&fm_demod_example; + +Like the Hello World example, we build a graph, connect the +blocks together and start it. In this case, our source, mc4020.source, +is an interface to the Measurement Computing PCI-DAS 4020/12 +high-speed ADC. We follow it with gr.freq_xlating_fir_filter_scf, a +finite impulse response (FIR) filter that selects the FM station we're +looking for and translates it to baseband (0Hz, DC). With the 20M +sample/sec converter and cable modem tuner, we're really grabbing +something in the neighborhood of a 6 MHz chunk of the spectrum. This +single chunk may contain ten or more FM stations, and +gr.freq_xlating_fir_filter_scf allows us to select the one we +want. + +In this case, we select the one at the exact center of the IF of +the RF front end (5.75 MHz). The output of +gr.freq_xlating_fir_filter_scf is a stream of complex samples at +160,000 samples/second. We feed the complex baseband signal into +gr.quadrature_demod_cf, the block that does the actual FM +demodulation. + +gr.quadrature_demod_cf works by subtracting the angle of +each adjacent complex sample, effectively differentiating the +frequency. The output of gr.quadrature_demod_cf contains the +left-plus-right FM mono audio signal, the stereo pilot tone at 19kHz, +the left-minus-right stereo information centered at 38kHz and any +other sub-carriers above that. For this simplified receiver, we finish +off by low pass filtering and decimating the stream, keeping only the +left-plus-right audio information, and send that to the sound card at +32,000 samples/sec. + +For a more indepth look at how the FM receiver +works, please see "Listening to FM, Step by Step." + + + +Graphical User Interfaces + +Graphical interfaces for GNU Radio applications are built in +Python. Interfaces may be built using any toolkit you can access from +Python; we recommend wxPython to maximize cross-platform +portability. GNU Radio provides blocks that use interprocess +communication to transfer chunks of data from the real-time C++ flow +graph to Python-land. + + + + + +Hardware Requirements + +GNU Radio is reasonably hardware-independent. Today's commodity +multi-gigahertz, super-scalar CPUs with single-cycle floating-point +units mean that serious digital signal processing is possible on the +desktop. A 3 GHz Pentium or Athlon can evaluate 3 billion +floating-point FIR taps/s. We now can build, virtually all in +software, communication systems unthinkable only a few years ago. + +Your computational requirements depend on what you're trying to do, +but generally speaking, a 1 or 2 GHz machine with at least 256 MB of RAM +should suffice. You also need some way to connect the analog world to +your computer. Low-cost options include built-in sound cards and +audiophile quality 96 kHz, 24-bit, add-in cards. With either of these +options, you are limited to processing relatively narrow band signals +and need to use some kind of narrow-band RF front end. + +Another possible solution is an off-the-shelf, high-speed PCI +analog-to-digital board. These are available in the 20M sample/sec +range, but they are expensive, about the cost of a complete PC. For +these high-speed boards, cable modem tuners make reasonable RF front +ends. + +Finding none of these alternatives completely satisfactory, we +designed the Universal Software Radio Peripheral, or USRP for short. + + + + +The Universal Software Radio Peripheral + +Our preferred hardware solution is the Universal Software Radio +Peripheral (USRP). shows the +block diagram of the USRP. The brainchild of Matt Ettus, the USRP is +an extremely flexible USB device that connects your PC to the RF +world. The USRP consists of a small motherboard containing up to four +12-bit 64M sample/sec ADCs, four 14-bit, 128M sample/sec DACs, a +million gate-field programmable gate array (FPGA) and a programmable +USB 2.0 controller. Each fully populated USRP motherboard supports +four daughterboards, two for receive and two for transmit. RF front +ends are implemented on the daughterboards. A variety of +daughterboards is available to handle different frequency bands. For +amateur radio use, low-power daughterboards are available that receive +and transmit in the 440 MHz band and the 1.24 GHz band. A receive-only +daughterboard based on a cable modem tuner is available that covers +the range from 50 MHz to 800 MHz. Daughterboards are designed to be easy +to prototype by hand in order to facilitate experimentation. + +
Universal Software Radio Peripheral + + + + + +
+ +The flexibility of the USRP comes from the two programmable components +on the board and their interaction with the host-side library. To get +a feel for the USRP, let's look at its boot sequence. The USRP itself +contains no ROM-based firmware, merely a few bytes that specify the +vendor ID (VID), product ID (PID) and revision. When the USRP is +plugged in to the USB for the first time, the host-side library sees +an unconfigured USRP. It can tell it's unconfigured by reading the +VID, PID and revision. The first thing the library code does is +download the 8051 code that defines the behavior of the USB peripheral +controller. When this code boots, the USRP simulates a USB disconnect +and reconnect. When it reconnects, the host sees a different device: +the VID, PID and revision are different. The firmware now running +defines the USB endpoints, interfaces and command handlers. One of the +commands the USB controller now understands is load the FPGA. The +library code, after seeing the USRP reconnect as the new device, goes +to the next stage of the boot process and downloads the FPGA +configuration bitstream. + +FPGAs are generic hardware chips whose behavior is determined by the +configuration bitstream that's loaded into them. You can think of the +bitstream as object code. The bitstream is the output of compiling a +high-level description of the design. In our case, the design is coded +in the Verilog hardware description language. This is source code and, +like the rest of the code in GNU Radio, is licensed under the GNU +General Public License. + +
+ +What Goes in the FPGA? + +An FPGA is like a small, massively parallel computer that you design +to do exactly what you want. Programming the FPGA takes a bit of +skill, and mistakes can fry the board permanently. That said, we +provide a standard configuration that is useful for a wide variety of +applications. + +Using a good USB host controller, the USRP can sustain 32 MB/sec across +the USB. The USB is half-duplex. Based on your needs, you partition +the 32 MB/sec between the transmit and the receive directions. In the +receive direction, the standard configuration allows you to select the +part or parts of the digitized spectrum you're interested in, +translate them to baseband and decimate as required. This is exactly +equivalent to what's happening in the RF front end, only now we're +doing it on digitized samples. The block of code that performs this +function is called a digital down converter (). +One advantage of performing this function in the digital domain is we can change the +center frequency instantaneously, which is handy for frequency hopping +spread spectrum systems. + +
Digital Down Converter Block Diagram + + + + + +
+ + +In the transmit direction, the exact inverse is performed. The FPGA +contains multiple instances of the digital up and down +converters. These instances can be connected to the same or different +ADCs, depending on your needs. We don't have room here to cover all +the theory behind them; see the GNU Radio Wiki for more information. + +
+ +GNU Radio Applications + +In addition to the examples discussed above, GNU Radio comes with a +complete HDTV transmitter and receiver, a spectrum analyzer, an +oscilloscope, concurrent multichannel receiver and an ever-growing +collection of modulators and demodulators. + +Projects under investigation or in progress include: + + +A TiVo equivalent for radio, capable of recording multiple stations simultaneously. +Time Division Multiple Access (TDMA) waveforms. +A passive radar system that takes advantage of +broadcast TV for its signal source. For those of you with old TVs +hooked to antennas, think about the flutter you see when airplanes fly +over. +Radio astronomy. +TETRA transceiver. +Digital Radio Mundial (DRM). +Software GPS. +Distributed sensor networks. +Distributed measurement of spectrum utilization. +Amateur radio transceivers. +Ad hoc mesh networks. +RFID detector/reader. +Multiple input multiple output (MIMO) processing. + + + + +Politics + +Every revolution has its political issues. Free software for building +radios is troublesome to some people. In the US, we've run into +opposition from the Motion Picture Association of America and its +attempt with the Broadcast Flag to restrict the kinds of receivers +that can be built for over-the-air digital TV. + +The US Federal Communications Commission has issued a Notice of +Proposed Rule Making (NPRM) concerning Cognitive Radio +Technologies and Software Defined Radios. Several troublesome +issues are raised in the NPRM, including restricting the sale of +high-speed digital-to-analog converters, requirements for digital +signatures or similar methods to keep unauthorized software out of +software radio hardware and new restrictions on radios built for the +amateur radio market. + + + +Summary + +Software radio is an exciting field, and GNU Radio provides the tools +to start exploring. A deep understanding of software radio requires +knowledge from many domains. We're doing our best to lower the +barriers to entry. + + + + +
diff --git a/docs/exploring-gnuradio/fm_demod.py b/docs/exploring-gnuradio/fm_demod.py new file mode 100755 index 00000000..e58407f7 --- /dev/null +++ b/docs/exploring-gnuradio/fm_demod.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import mc4020 +import sys + +def high_speed_adc (fg, input_rate): + # return gr.file_source (gr.sizeof_short, "dummy.dat", False) + return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + +# +# return a gr.flow_graph +# +def build_graph (freq1, freq2): + input_rate = 20e6 + cfir_decimation = 125 + audio_decimation = 5 + + quad_rate = input_rate / cfir_decimation + audio_rate = quad_rate / audio_decimation + + fg = gr.flow_graph () + + # use high speed ADC as input source + src = high_speed_adc (fg, input_rate) + + # compute FIR filter taps for channel selection + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + input_rate, # sampling rate + 250e3, # low pass cutoff freq + 8*100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + + # input: short; output: complex + chan_filter1 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq1, # 1st station freq + input_rate) + + (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, chan_filter1) + fg.connect (chan_filter1, head1) + fg.connect (tail1, (audio_sink, 0)) + + # two stations at once? + if freq2: + # Extract the second station and connect + # it to a second pipeline... + + # input: short; output: complex + chan_filter2 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq2, # 2nd station freq + input_rate) + + (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation) + + fg.connect (src, chan_filter2) + fg.connect (chan_filter2, head2) + fg.connect (tail2, (audio_sink, 1)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverteed complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (args): + nargs = len (args) + if nargs == 1: + freq1 = float (args[0]) * 1e6 + freq2 = None + elif nargs == 2: + freq1 = float (args[0]) * 1e6 + freq2 = float (args[1]) * 1e6 + else: + sys.stderr.write ('usage: fm_demod freq1 [freq2]\n') + sys.exit (1) + + # connect to RF front end + rf_front_end = gr.microtune_4937_eval_board () + if not rf_front_end.board_present_p (): + raise IOError, 'RF front end not found' + + # set front end gain + rf_front_end.set_AGC (300) + IF_freq = rf_front_end.get_output_freq () + IF_freq = 5.75e6 + + if not freq2: # one station + + rf_front_end.set_RF_freq (freq1) + fg = build_graph (IF_freq, None) + + else: # two stations + + if abs (freq1 - freq2) > 5.5e6: + raise IOError, 'freqs too far apart' + + target_freq = (freq1 + freq2) / 2 + actual_freq = rf_front_end.set_RF_freq (target_freq) + #actual_freq = target_freq + + fg = build_graph (IF_freq + freq1 - actual_freq, + IF_freq + freq2 - actual_freq) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main (sys.argv[1:]) + + diff --git a/docs/exploring-gnuradio/fm_demod_example.xml b/docs/exploring-gnuradio/fm_demod_example.xml new file mode 100644 index 00000000..3036f88b --- /dev/null +++ b/docs/exploring-gnuradio/fm_demod_example.xml @@ -0,0 +1,123 @@ + +Broadcast FM Receiver + +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import mc4020 +import sys + +def high_speed_adc (fg, input_rate): + # return gr.file_source (gr.sizeof_short, "dummy.dat", False) + return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + +# +# return a gr.flow_graph +# +def build_graph (freq1, freq2): + input_rate = 20e6 + cfir_decimation = 125 + audio_decimation = 5 + + quad_rate = input_rate / cfir_decimation + audio_rate = quad_rate / audio_decimation + + fg = gr.flow_graph () + + # use high speed ADC as input source + src = high_speed_adc (fg, input_rate) + + # compute FIR filter taps for channel selection + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + input_rate, # sampling rate + 250e3, # low pass cutoff freq + 8*100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + + # input: short; output: complex + chan_filter1 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq1, # 1st station freq + input_rate) + + (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, chan_filter1) + fg.connect (chan_filter1, head1) + fg.connect (tail1, (audio_sink, 0)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverted complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (args): + nargs = len (args) + if nargs == 1: + # get station frequency from command line + freq1 = float (args[0]) * 1e6 + else: + sys.stderr.write ('usage: fm_demod freq\n') + sys.exit (1) + + # connect to RF front end + rf_front_end = gr.microtune_4937_eval_board () + if not rf_front_end.board_present_p (): + raise IOError, 'RF front end not found' + + # set front end gain + rf_front_end.set_AGC (300) + + # determine the front end's "Intermediate Frequency" + IF_freq = rf_front_end.get_output_freq () # 5.75e6 + + # Tell the front end to tune to freq1. + # I.e., freq1 is translated down to the IF frequency + rf_front_end.set_RF_freq (freq1) + + # build the flow graph + fg = build_graph (IF_freq, None) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main (sys.argv[1:]) + + diff --git a/docs/exploring-gnuradio/swr-block-diagram.eps b/docs/exploring-gnuradio/swr-block-diagram.eps new file mode 100644 index 00000000..dd029f35 --- /dev/null +++ b/docs/exploring-gnuradio/swr-block-diagram.eps @@ -0,0 +1,2399 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000800000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000400000000800000000800000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000001000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000002000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000002000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000080000000800000004000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000080000000800000004000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000040000000800000008000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000010000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000020000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000010000000800000020000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000008000000800000040000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000080000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000080000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000002000000800000100000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000002000000800000100000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000001000000800000200000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000400000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000800000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFF +%FFFF000000000000000000000000000000 +%000000000000400000800000800000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000030000000000000000000000 +%0000E00000000000000000000000000000 +%000000000000200000800001000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000080000000000000000000000 +%0000080000000000000000000000000000 +%000000000000000000800002000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000040000000000000000000000000000 +%000000000000100000800002000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000020000000000000000000000000000 +%000000000000080000800004000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000080000800004000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000040000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800010000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000020000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000010000800020000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000008000800040000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800080000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000004000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000002000800100000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000002000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800400000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000400800800000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000200801000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000802000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000100800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000080804000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000080800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000810000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000010820000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000008840000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000880000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000004800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000002900000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000002800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000 +%0000000000000000FFFFFFFFFFFFFFFFFF80000000000000000000000000000380180000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000180380000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000002000000000000000000000000000000000000000000000001C0700000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000004000000000000000000000000000000000000000000000000C0E00000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000E1C07008184600 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000001000000000000000000000000000000000000000000000000061C1FC1818FE00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000002000000000000000000000000000000000000000000000000073838E1818FC00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000003707061838E000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000800000000000000000000000000000000000000000000000003E0E073030E000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000001000000000000000000000000000000000000000000000000001C0C033030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001C0C073030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000400000000000000000000000000000000000000000000000000180C0630318000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000800000000000000000000000000000000000000000000000000180C0670718000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFC00000000000C000000001FF00FFE00000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0E70618000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFF00000000000C000000003FFC0FFE00000000 +%0000000000002000000000000000000000000000000000000000000000000000180E1C70E18000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400E0780000000000C00000000381E0FFE00000000 +%00000000000040000000000000000000000000000000000000000000000000003807783F630000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C000000000000000000038070C0000000000 +%00000000000000000000000000000000000000000000000000000000000000003003F01E630000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C000000000000000000038030C0000000000 +%000000000001000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C1F007C07C0CE060F80038030C0000000000 +%000000000002000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C3FC1FE1FE0C6063FC0038070C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C03860E3873830C60C70600380E0C0000000000 +%000000000008000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFF06063033018C60C607003FFC0FFC00000000 +%000000000010000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFC0C063003018C30C603003FF00FFC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C1C0FFE3003FF8C3187FF0038300C0000000000 +%000000000040000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C0E0FFE3003FF8C1987FF0038180C0000000000 +%000000000080000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C070C003003000C19860000381C0C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C038C063033018C1B060200380E0C0000000000 +%000000000200000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C0386063833838C0F07070038060C0000000000 +%0000000004000001C03FF000FE00000000000000000000000000000000000001F8000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C71E1C61C70C0E038E0038070C0000000000 +%0000000000000001C03FFC03FF00000000000000000000000000000000000007FE000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C00E3FC0FE0FE0C0E01FC0038038C0000000000 +%0000000010000003E0301E07838000000000000000000000000000000000000E0E000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C00E0E00380380C0400700010018C0000000000 +%00000000200000036030060601C000000000000000000000000000000000001C07000000700000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000077030070E00C00000000000000000000000000000000000380301C00C603800 +%0000001000000000000000000000000000 +%000000000000000000800000000000000C00400000000000000000000000000000000000000000 +%0001C000800000063030030C00000000000000000000000000C00000000000300007F03F60FE00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000F80400000000000000000000000000000000000000000 +%0001F001000000063830031C00000000000000000000000000F8000000000070000C3871E1C700 +%0000001000000000000000000000000000 +%000000000000000000800000000000000FF8400000000000000000000000000000000000000000 +%0001FF000000000E1830031C00000000000000000000000000FF800000000060001818E0E30300 +%0000001000000000000000000000000000 +%000000000000000000800000000000000FFE400000000000000000000000000000000000000000 +%0001FFE40000000C1830031C00000000000000000000000000FFE00000000060003018C0C70300 +%0000001000000000000000000000000000 +%0000000000000000007FFFFFFFFFFFFFFFFFC000000000000000000000000000000000003FFFFF +%FFFFFFF80000000C1C30031C00000000007FFFFFFFFFFFFFFFFFF80000000060003019C0C70300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000FF8400000000000000000000000000000000000000000 +%0001FF000000001FFC30030C00000000000000000000000000FF80000000006000301980C7FF00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000FE0400000000000000000000000000000000000000000 +%0001FC020000001FFC30030C00C00000000000000000000000FE00000000006006701980C60000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000F00400000000000000000000000000000000000000000 +%0001F001000000380E30070E00C00000000000000000000000F00000000000700E701981C60000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FF80000000000003FFC00000080000000000 +%00000000000000300630060601C00000000000000000000000000000000000300C303181860600 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FFC0000000006003FFE000000C0000000000 +%000000004000003007301E0783800000000000000000000000000000000000381C3071C3870E00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003800000000000E003800000000C0000000000 +%0000000020000070033FFC03FF0000000000000000000000000000000000001FF81FE0FF83FC00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000000000000E003000000000C0000000000 +%000000000000006003BFF000FC00000000000000000000000000000000000007E00F807981F000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000000000000E003000000000C0000000000 +%000000000800000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000DE1F833E1F80300037C03CC0000000000 +%000000000400000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000FE7FC3FF0E0030003FF0FFC0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000E060E3830E0030003871C3C0000000000 +%000000000100000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FF0E0E063838E003FFC303181C0000000000 +%000000000080000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FF0E0C073038E003FFC303180C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C033038E003000303180C0000000000 +%000000000020000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C033038E003000303180C0000000000 +%000000000010000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C033038E003000303180C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C063038E003000303181C0000000000 +%000000000004000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C06063038E0030003031C1C0000000000 +%0000000000020000000000000000000000000000000000000000000000000038030000000001C0 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C071C30387003FFE3030E7C0000000000 +%0000000000000000000000000000000000000000000000000000000000000038070000000001C0 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C03F830387803FFE30307EC0000000000 +%000000000000800000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%0000000000000000000000000000000000004000030004006030103803FFE30301880000000000 +%000000000000400000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000030060380CC0E0380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000001000000000000000000000000000000000000000000000000070060FE0DE3F8380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000008000000000000000000000000000000000000000000000000700E1C70F061C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000007FFC3030E0C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000020000000000000000000000000000000000000000000000007FFC7039C1C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000001000000000000000000000000000000000000000000000000E00C7FF981FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C01C7FF181FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000400000000000000000000000000000000000000000000000C01C600181800200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C018600381800000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C018606301818000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000001C01870E301C38000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000001C0183FC300FF0E00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000180380F03007C0C00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000400000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%0000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000 +%00000000000000007FFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000008000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000800000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000400000000000000000000000 +%0000010000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000300000000000000000000000 +%0000060000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000080000000000000000000000 +%0000180000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000020000000000000000000000 +%0000200000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000001C000000000000000000000 +%0001800000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FF00000 +%0000006000000001FF800000300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FFC0000 +%0000006000000001FFC0000C300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700C0000 +%000000000000000180E0000C300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E0000 +%00000000000000018060000C300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070060300 +%1C01C062010380018070381F318000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E1FC0 +%7F07F063030FE0018070FE1F3FE000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E38E0 +%E38E3863031C70018061C70C3E7000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FFC3031 +%C19C1C630638300180E3830C383000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FF06031 +%80180C6186301801FFC0030C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000071E07FF1 +%801FFC61863FF801FF80070C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070707FF9 +%801FFC618C3FF8018000FF0C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070386001 +%80180060CC3000018001E30C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070386001 +%80180060CC3000018003830C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000701C3031 +%819C0C60783018018003030C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E3871 +%C18C1C60783830018003070C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E1FE0 +%FF0FF860701FF0018003DF0F303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070070FC0 +%3E03E0603007C0018001F987B03800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000400000000800000000800000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000400000000800000000800000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000200000000800000001000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000002000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000100000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000080000000800000004000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000008000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000010000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000010000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000010000000800000020000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000010000000800000020000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000008000000800000040000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000080000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000004000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000002000000800000100000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000200000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000400000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000400000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000400000800000800000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000038000000000000000000000 +%0000E00000000000000000000000000000 +%000000000000400000800000800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000C0000000000000000000000 +%0000180000000000000000000000000000 +%000000000000200000800001000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000100000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800002000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000400000000000000000000000 +%0000000000000000000000000000000000 +%000000000000100000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000800000000000000000000000 +%0000000000000000000000000000000000 +%000000000000080000800004000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800008000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000800010000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000800010000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000010000800020000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000010000800020000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000008000800040000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800080000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000004000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000002000800100000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000001000800200000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800400000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800400000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000400800800000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000400800800000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000200801000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000802000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000100800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000080804000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000040808000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000810000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000810000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000010820000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000010800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000008840000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000880000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000004900000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000002800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000001A00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000400000 +%000000000000000000000000000000000080000000000000000000000000000380380000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000180700000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000C0700000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000C0E00000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000E1C0F818186E00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000006383FC1818FE00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000007307061818F000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000003706061838E000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001E0E073030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001C0C033030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001C0C073030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0630718000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0670718000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000180380000180001FFC0FFF0000000000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0C70E18000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000001C0700000186001FFE0FFF0000000000000 +%0000000000000000000000000000000000000000000000000000000000000000380E1C71E18000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000000E06000000060018070C000000000000000 +%00000000000080000000000000000000000000000000000000000000000000003007F83F630000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000070C000000060018030C000000000000000 +%00000000000000000000000000000000000000000000000000000000000000003001E01C630000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000031C000000070018030C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000003B81BE7E18FC018030C000000000000000 +%000000000004000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000001F01E7EF1860018070C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000E01C383186001C3E0E000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000E018383186001FFC0FFE0000000000000 +%000000000020000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000001F018383186001FF00FFC0000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000001B8183831860018380C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000003181838318600181C0C000000000000000 +%000000000100000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000071C1838318600180E0C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000000E0E183831860018070C000000000000000 +%000000000400001F80006000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000000C07183831860018070C000000000000000 +%000000000800003FF800F001FE00000000000000000000000000000000000003FC000000300000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000001C07183831878018038C000000000000000 +%000000000000003FFC00F003FF8000000000000000000000000000000000000F9E000000300000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000380398383183C018018C000000000000000 +%00000000200000300E01F007018000000000000000000000000000000000001C07000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000400000300701B80E01C000000000000000000000000000000000001803000000600000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000300301980C00C00000000000000000000000000000000000380303E01E607C00 +%0000001000000000000000000000000000 +%000000000000000000800800000000000000400000000000000000000000000000000000000400 +%00000001000000300303980C0000000000000080000000000000000000000030000FF03F61FE00 +%0000001000000000000000000000000000 +%000000000000000000803800000000000000400000000000000000000000000000000000001C00 +%000000020000003003030C1C0000000000000780000000000000000000000070001C3861E38300 +%0000001000000000000000000000000000 +%00000000000000000081F80000000000000040000000000000000000000000000000000000FC00 +%000000000000003003830C1C0000000000001F80000000000000000000000060003818C0E30300 +%0000001000000000000000000000000000 +%0000000000000000009FF8000000000000004000000000000000000000000000000000000FFC00 +%000000080000003003860E1C000000000001FF80000000000000000000000060003018C0C70300 +%0000001000000000000000000000000000 +%000000000000000000FFFFFFFFFFFFFFFFFFC000000000000000000000000000000000003FFFFF +%FFFFFFFC0000003003070E1C00000000000FFFFFFFFFFFFFFFFFF8000000006000301980C7FF00 +%0000001000000000000000000000000000 +%0000000000000000001FF8000000000000004000000000000000000000000000000000000FFC00 +%0000000000000030030FFF0C000000000001FF8000000000000000000000006000301980C7FF00 +%0000001000000000000000000000000000 +%00000000000000000001F80000000000000040000000000000000000000000000000000000FC00 +%0000000100000030030E070C00C0000000001F8000000000000000000000006006701980C60000 +%0000001000000000000000000000000000 +%000000000000000000007800000000000000400000000000000000000000000000000000001C00 +%0000000080000030070C030E00C00000000007800000000000000000000000700E703981C60600 +%0000001000000000000000000000000000 +%000000000000000000000800000000000000400007FF80000000004007FFC00000180000000400 +%00000000000000300E1C038701C00000000000800000000000000000000000381C303181860600 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FF8000000000C007FFC00000180000000000 +%00000000200000383C180183C78000000000000000000000000000000000003C3838E0C7871C00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007000000000000C00700000000180000000000 +%000000001000003FF83801C1FF0000000000000000000000000000000000000FF01FC0FF83F800 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000000000000C00700000000180000000000 +%000000000000003FE03000C07C00000000000000000000000000000000000003C007003980E000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000880C02303E00700043003180000000000 +%000000000400000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000FC7F86FE3F0070006FC0FD80000000000 +%000000000200000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000FCF3C7CE0C0070007CE1C780000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FE0C0C0C7070C007FF870618380000000000 +%000000000080000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FF0C1C0E7030C007FF860730180000000000 +%000000000040000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FE0C18067030C007FF060730180000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C18067030C00700060730180000000000 +%000000000010000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C18067030C00700060730180000000000 +%000000000008000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C18067030C00700060730180000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C1C0E7030C00700060738380000000000 +%000000000002000000000000000000000000000000000000000000000000001003000000000080 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C0E1C7030C00700060718380000000000 +%0000000000010000000000000000000000000000000000000000000000000038030000000001C0 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C07F87030F007FFC6071FF80000000000 +%000000000000000000000000000000000000000000000000000000000000003007000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C03F070307007FFC60707D80000000000 +%000000000000400000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000200000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000300607C0CE1F0380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000008000000000000000000000000000000000000000000000000700E1FE0FC7F8380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000040000000000000000000000000000000000000000000000007FFE3830E0E0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000007FFC3031C0C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000001000000000000000000000000000000000000000000000000601C7039C1C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000800000000000000000000000000000000000000000000000E00C7FF981FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C01C7FF181FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000200000000000000000000000000000000000000000000000C01C600181800600 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000100000000000000000000000000000000000000000000000C018602381818000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000001C018606301818000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000040000000000000000000000000000000000000000000001C01831C301C70400 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000020000000000000000000000000000000000000000000001C0383F8300FE0E00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000180300E0300380C00 +%0000001000000000000000000000000000 +%0000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000 +%0000000000000000FFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000400000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000100000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000C0000000000000000000000 +%0000180000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000020000000000000000000000 +%0000200000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFF +%FFFE000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000007FFC00000 +%00000000000182003FF80000860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000007FFC00000 +%00000000000186003FFC0001860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018000000 +%0000000000000600301C0001860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018000000 +%0000000000000600300E0001860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806E1F8 +%33C07813C3C19F80300E0F83E67800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001807E3FC +%3FE1FE1FFFE18F80300E3FE3E7FE00000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001807060E +%3871871C78618600300C3061878600000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806060E +%3033821838318600303C6061870700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806000E +%30318018303186003FF80061860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180600FE +%3031F818303186003FE007E1860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180603FE +%30307E183031860030003FE1860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806070E +%30300F183031860030007861860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018060E0E +%303003183031860030006061860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018060C0E +%303383183031860030006061860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018060E1E +%3031871830318600300070E1C60700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180607FE +%3031FE183031878030003FF1F60700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180603C6 +%303078183031838030001E30F60300000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0 lw 1 lj 0.000 c 1905 1905 m 3175 3810 l ps +3175 3810 m 4445 1905 l ps +3175 1905 m 3175 5080 l ps +0.996 c 12565 5080 m 13835 3810 l 16375 3810 l 16375 6350 l 13835 6350 l +12565 5080 l p ef +0.000 c 12565 5080 m 13835 3810 l 16375 3810 l 16375 6350 l 13835 6350 l +12565 5080 l pc +gs +pum +13573 5371 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8255 6350 m 5715 6350 l 5715 3810 l 10795 3810 l 10795 6350 l 8255 6350 l +pc +gs +pum +6033 4895 t +66 0 m 66 -606 l 335 -606 l 389 -606 430 -600 458 -589 ct 486 -579 509 -559 526 -532 ct +542 -504 551 -474 551 -440 ct 551 -397 537 -361 509 -332 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 452 -224 474 -197 495 -165 ct 600 0 l 500 0 l +419 -126 l 396 -162 377 -190 361 -209 ct 346 -228 333 -242 321 -250 ct 309 -257 296 -263 284 -266 ct +275 -268 260 -269 239 -269 ct 146 -269 l 146 0 l p +146 -338 m 319 -338 l 355 -338 384 -342 405 -350 ct 425 -357 441 -369 452 -386 ct +463 -403 468 -421 468 -440 ct 468 -469 458 -493 437 -511 ct 416 -530 383 -539 338 -539 ct +146 -539 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1864 -141 m 1941 -131 l 1929 -86 1906 -52 1874 -27 ct 1841 -2 1799 9 1748 9 ct +1684 9 1633 -9 1595 -49 ct 1557 -88 1539 -144 1539 -215 ct 1539 -289 1558 -347 1596 -387 ct +1634 -428 1683 -449 1744 -449 ct 1802 -449 1850 -429 1888 -389 ct 1925 -349 1943 -292 1943 -220 ct +1943 -216 1943 -209 1943 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1712 -51 1748 -51 ct 1776 -51 1799 -58 1818 -72 ct 1837 -87 l 1853 -110 l +p +1620 -261 m 1865 -261 l 1862 -298 1852 -326 1837 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1682 -376 1658 -353 ct 1635 -330 l 1622 -300 l p ef +2040 -520 m 2040 -606 l 2114 -606 l 2114 -520 l p +2040 0 m 2040 -439 l 2114 -439 l 2114 0 l p ef +2347 0 m 2180 -439 l 2259 -439 l 2353 -176 l 2363 -147 2373 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2507 -439 l 2583 -439 l 2417 0 l p ef +2949 -141 m 3026 -131 l 3014 -86 2991 -52 2959 -27 ct 2926 -2 2884 9 2833 9 ct +2769 9 2718 -9 2680 -49 ct 2642 -88 2624 -144 2624 -215 ct 2624 -289 2643 -347 2681 -387 ct +2719 -428 2768 -449 2829 -449 ct 2887 -449 2935 -429 2973 -389 ct 3010 -349 3028 -292 3028 -220 ct +3028 -216 3028 -209 3028 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2797 -51 2833 -51 ct 2861 -51 2884 -58 2903 -72 ct 2922 -87 l 2938 -110 l +p +2705 -261 m 2950 -261 l 2947 -298 2937 -326 2922 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2767 -376 2743 -353 ct 2720 -330 l 2707 -300 l p ef +3373 0 m 3373 -606 l 3642 -606 l 3696 -606 3737 -600 3765 -589 ct 3793 -579 3816 -559 3833 -532 ct +3849 -504 3858 -474 3858 -440 ct 3858 -397 3844 -361 3816 -332 ct 3788 -302 3745 -283 3687 -275 ct +3708 -265 3724 -255 3735 -245 ct 3759 -224 3781 -197 3802 -165 ct 3907 0 l 3807 0 l +3726 -126 l 3703 -162 3684 -190 3668 -209 ct 3653 -228 3640 -242 3628 -250 ct +3616 -257 3603 -263 3591 -266 ct 3582 -268 3567 -269 3546 -269 ct 3453 -269 l +3453 0 l p +3453 -338 m 3626 -338 l 3662 -338 3691 -342 3712 -350 ct 3732 -357 3748 -369 3759 -386 ct +3770 -403 3775 -421 3775 -440 ct 3775 -469 3765 -493 3744 -511 ct 3723 -530 3690 -539 3645 -539 ct +3453 -539 l p ef +3985 0 m 3985 -606 l 4394 -606 l 4394 -534 l 4065 -534 l 4065 -346 l +4350 -346 l 4350 -275 l 4065 -275 l 4065 0 l p ef +pom +pum +6364 5848 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +584 0 m 584 -439 l 651 -439 l 651 -372 l 668 -403 683 -424 698 -434 ct +712 -444 728 -449 746 -449 ct 771 -449 796 -441 822 -425 ct 797 -356 l 778 -366 760 -372 742 -372 ct +726 -372 711 -367 698 -357 ct 685 -347 676 -334 670 -316 ct 662 -290 658 -261 658 -229 ct +658 0 l p ef +848 -219 m 848 -300 870 -361 915 -400 ct 953 -432 999 -449 1054 -449 ct 1114 -449 1163 -429 1202 -389 ct +1240 -350 1259 -295 1259 -225 ct 1259 -169 1251 -124 1234 -92 ct 1217 -60 1192 -34 1160 -16 ct +1127 0 1092 9 1054 9 ct 992 9 942 -9 904 -49 ct 867 -88 l 848 -145 l p +924 -219 m 924 -163 936 -121 961 -93 ct 985 -65 1016 -51 1054 -51 ct 1091 -51 1121 -65 1146 -93 ct +1170 -121 1183 -164 1183 -222 ct 1183 -276 1170 -317 1146 -345 ct 1121 -373 1090 -387 1054 -387 ct +1016 -387 985 -373 961 -345 ct 936 -317 l 924 -275 l p ef +1351 0 m 1351 -439 l 1418 -439 l 1418 -376 l 1451 -425 1497 -449 1558 -449 ct +1585 -449 1609 -444 1631 -434 ct 1653 -425 1670 -412 1681 -397 ct 1692 -382 1700 -363 1704 -342 ct +1707 -328 1708 -304 1708 -270 ct 1708 0 l 1634 0 l 1634 -267 l 1634 -297 1631 -320 1625 -335 ct +1619 -350 1609 -362 1594 -371 ct 1580 -380 1562 -384 1542 -384 ct 1511 -384 1483 -374 1460 -354 ct +1437 -334 1426 -296 1426 -239 ct 1426 0 l p ef +1991 -66 m 2002 0 l 1981 3 1962 5 1945 5 ct 1918 5 1897 1 1883 -7 ct 1868 -15 1857 -26 1851 -40 ct +1845 -54 1842 -83 1842 -128 ct 1842 -381 l 1787 -381 l 1787 -439 l 1842 -439 l +1842 -547 l 1916 -592 l 1916 -439 l 1991 -439 l 1991 -381 l 1916 -381 l +1916 -124 l 1916 -103 1917 -89 1920 -83 ct 1923 -77 1927 -72 1933 -69 ct 1939 -65 1947 -63 1958 -63 ct +1966 -63 l 1977 -64 l p ef +2316 0 m 2316 -606 l 2754 -606 l 2754 -534 l 2396 -534 l 2396 -349 l +2731 -349 l 2731 -277 l 2396 -277 l 2396 -71 l 2768 -71 l 2768 0 l +p ef +2886 0 m 2886 -439 l 2953 -439 l 2953 -376 l 2986 -425 3032 -449 3093 -449 ct +3120 -449 3144 -444 3166 -434 ct 3188 -425 3205 -412 3216 -397 ct 3227 -382 3235 -363 3239 -342 ct +3242 -328 3243 -304 3243 -270 ct 3243 0 l 3169 0 l 3169 -267 l 3169 -297 3166 -320 3160 -335 ct +3154 -350 3144 -362 3129 -371 ct 3115 -380 3097 -384 3077 -384 ct 3046 -384 3018 -374 2995 -354 ct +2972 -334 2961 -296 2961 -239 ct 2961 0 l p ef +3647 0 m 3647 -55 l 3619 -11 3579 9 3524 9 ct 3489 9 3457 0 3428 -19 ct 3399 -38 3376 -65 3360 -99 ct +3344 -134 3335 -174 3335 -219 ct 3335 -263 3343 -302 3357 -338 ct 3372 -374 3394 -401 3423 -420 ct +3452 -439 3485 -449 3521 -449 ct 3548 -449 3571 -443 3592 -432 ct 3613 -421 3629 -406 3642 -388 ct +3642 -606 l 3716 -606 l 3716 0 l p +3412 -219 m 3412 -162 3424 -120 3448 -93 ct 3471 -65 3499 -51 3531 -51 ct 3564 -51 3592 -64 3614 -91 ct +3637 -117 3649 -158 3649 -212 ct 3649 -273 3637 -317 3614 -345 ct 3591 -373 3562 -387 3528 -387 ct +3495 -387 3467 -374 3445 -346 ct 3423 -319 l 3412 -277 l p ef +pom +gr +21272 7620 m 19550 7620 l 19274 7620 19050 7396 19050 7120 ct 19050 3040 l +19050 2764 19274 2540 19550 2540 ct 22995 2540 l 23271 2540 23495 2764 23495 3040 ct +23495 7120 l 23495 7396 23271 7620 22995 7620 ct 21272 7620 l pc +gs +pum +20360 4418 t +236 0 m 285 -234 l 98 -606 l 185 -606 l 275 -429 l 294 -390 313 -349 332 -305 ct +352 -342 380 -383 415 -428 ct 557 -606 l 654 -606 l 365 -228 l 317 0 l +p ef +597 -166 m 597 -252 622 -323 673 -379 ct 714 -425 769 -449 836 -449 ct 889 -449 932 -432 964 -399 ct +997 -366 1013 -321 1013 -265 ct 1013 -215 1003 -168 982 -124 ct 962 -81 933 -47 895 -24 ct +858 -1 818 9 776 9 ct 742 9 711 2 683 -11 ct 655 -26 634 -47 619 -74 ct 604 -100 l +597 -131 l p +672 -174 m 672 -132 682 -101 701 -80 ct 721 -58 747 -47 777 -47 ct 793 -47 809 -51 825 -57 ct +840 -64 855 -74 869 -87 ct 882 -100 894 -115 903 -132 ct 913 -149 920 -167 926 -187 ct +935 -214 939 -240 939 -265 ct 939 -305 929 -336 909 -358 ct 889 -380 864 -391 833 -391 ct +810 -391 789 -385 769 -374 ct 750 -363 733 -346 717 -325 ct 701 -303 690 -278 683 -250 ct +675 -221 l 672 -196 l p ef +1359 -79 m 1307 -19 1253 9 1198 9 ct 1164 9 1136 0 1116 -19 ct 1095 -38 1084 -62 1084 -90 ct +1084 -109 1089 -140 1099 -185 ct 1151 -439 l 1226 -439 l 1168 -158 l 1163 -134 1160 -116 1160 -103 ct +1160 -87 1165 -74 1175 -65 ct 1185 -55 1200 -51 1220 -51 ct 1241 -51 1261 -56 1281 -66 ct +1301 -76 1318 -90 1333 -107 ct 1347 -125 1359 -145 1368 -169 ct 1374 -184 1381 -211 1389 -249 ct +1429 -439 l 1504 -439 l 1412 0 l 1343 0 l p ef +1536 0 m 1627 -439 l 1694 -439 l 1675 -349 l 1698 -383 1720 -408 1741 -424 ct +1763 -441 1785 -449 1808 -449 ct 1823 -449 1841 -443 1863 -433 ct 1832 -363 l +1819 -372 1805 -377 1790 -377 ct 1763 -377 1736 -362 1709 -333 ct 1681 -304 1660 -252 1644 -176 ct +1607 0 l p ef +pom +pum +20241 5371 t +510 -213 m 591 -202 l 565 -132 528 -79 480 -43 ct 431 -7 377 10 316 10 ct +243 10 184 -12 141 -57 ct 98 -102 76 -166 76 -250 ct 76 -359 109 -449 175 -521 ct +233 -584 306 -616 393 -616 ct 457 -616 509 -599 549 -564 ct 589 -530 612 -484 618 -425 ct +543 -418 l 535 -462 518 -495 493 -517 ct 468 -538 436 -549 397 -549 ct 322 -549 262 -516 217 -450 ct +177 -394 157 -326 157 -248 ct 157 -186 172 -138 203 -105 ct 234 -73 273 -56 323 -56 ct +364 -56 402 -70 436 -97 ct 470 -124 l 495 -163 l p ef +650 -166 m 650 -252 675 -323 726 -379 ct 767 -425 822 -449 889 -449 ct 942 -449 985 -432 1017 -399 ct +1050 -366 1066 -321 1066 -265 ct 1066 -215 1056 -168 1035 -124 ct 1015 -81 986 -47 948 -24 ct +911 -1 871 9 829 9 ct 795 9 764 2 736 -11 ct 708 -26 687 -47 672 -74 ct 657 -100 l +650 -131 l p +725 -174 m 725 -132 735 -101 754 -80 ct 774 -58 800 -47 830 -47 ct 846 -47 862 -51 878 -57 ct +893 -64 908 -74 922 -87 ct 935 -100 947 -115 956 -132 ct 966 -149 973 -167 979 -187 ct +988 -214 992 -240 992 -265 ct 992 -305 982 -336 962 -358 ct 942 -380 917 -391 886 -391 ct +863 -391 842 -385 822 -374 ct 803 -363 786 -346 770 -325 ct 754 -303 743 -278 736 -250 ct +728 -221 l 725 -196 l p ef +1409 -63 m 1366 -14 1321 9 1275 9 ct 1233 9 1198 -5 1171 -36 ct 1143 -66 1129 -111 1129 -169 ct +1129 -223 1140 -272 1162 -316 ct 1184 -360 1211 -394 1244 -416 ct 1277 -438 1310 -449 1343 -449 ct +1398 -449 1439 -422 1467 -370 ct 1517 -606 l 1591 -606 l 1465 0 l 1396 0 l +p +1204 -184 m 1204 -153 1207 -129 1213 -111 ct 1219 -94 1229 -79 1244 -67 ct +1258 -55 1276 -50 1296 -50 ct 1330 -50 1361 -67 1388 -102 ct 1425 -149 1444 -207 1444 -276 ct +1444 -311 1435 -338 1417 -358 ct 1398 -377 1376 -387 1348 -387 ct 1330 -387 1314 -383 1299 -375 ct +1284 -367 1270 -353 1255 -334 ct 1241 -315 1228 -291 1219 -261 ct 1209 -232 l +1204 -206 l p ef +1911 -149 m 1984 -141 l 1974 -105 1949 -71 1912 -38 ct 1874 -6 1829 9 1777 9 ct +1745 9 1715 2 1688 -12 ct 1661 -27 1640 -49 1626 -78 ct 1611 -106 1604 -139 1604 -176 ct +1604 -224 1615 -270 1638 -315 ct 1660 -360 1689 -394 1724 -416 ct 1759 -438 1797 -449 1838 -449 ct +1891 -449 1933 -432 1964 -400 ct 1995 -367 2011 -323 2011 -267 ct 2011 -245 2009 -223 2005 -201 ct +1682 -201 l 1681 -192 1680 -184 1680 -177 ct 1680 -136 1689 -105 1708 -83 ct +1727 -62 1750 -51 1778 -51 ct 1803 -51 1829 -59 1853 -76 ct 1878 -93 l 1897 -117 l +p +1694 -258 m 1940 -258 l 1940 -265 1941 -271 1941 -274 ct 1941 -312 1931 -340 1912 -360 ct +1894 -380 1870 -390 1840 -390 ct 1808 -390 1779 -379 1753 -357 ct 1726 -335 l +1707 -302 l p ef +pom +pum +20214 6324 t +35 0 m 162 -606 l 243 -606 l 190 -354 l 504 -354 l 557 -606 l 638 -606 l +512 0 l 430 0 l 490 -285 l 176 -285 l 116 0 l p ef +959 -149 m 1032 -141 l 1022 -105 997 -71 960 -38 ct 922 -6 877 9 825 9 ct +793 9 763 2 736 -12 ct 709 -27 688 -49 674 -78 ct 659 -106 652 -139 652 -176 ct +652 -224 663 -270 686 -315 ct 708 -360 737 -394 772 -416 ct 807 -438 845 -449 886 -449 ct +939 -449 981 -432 1012 -400 ct 1043 -367 1059 -323 1059 -267 ct 1059 -245 1057 -223 1053 -201 ct +730 -201 l 729 -192 728 -184 728 -177 ct 728 -136 737 -105 756 -83 ct 775 -62 798 -51 826 -51 ct +851 -51 877 -59 901 -76 ct 926 -93 l 945 -117 l p +742 -258 m 988 -258 l 988 -265 989 -271 989 -274 ct 989 -312 979 -340 960 -360 ct +942 -380 918 -390 888 -390 ct 856 -390 827 -379 801 -357 ct 774 -335 l 755 -302 l +p ef +1113 0 m 1204 -439 l 1271 -439 l 1252 -349 l 1275 -383 1297 -408 1318 -424 ct +1340 -441 1362 -449 1385 -449 ct 1400 -449 1418 -443 1440 -433 ct 1409 -363 l +1396 -372 1382 -377 1367 -377 ct 1340 -377 1313 -362 1286 -333 ct 1258 -304 1237 -252 1221 -176 ct +1184 0 l p ef +1726 -149 m 1799 -141 l 1789 -105 1764 -71 1727 -38 ct 1689 -6 1644 9 1592 9 ct +1560 9 1530 2 1503 -12 ct 1476 -27 1455 -49 1441 -78 ct 1426 -106 1419 -139 1419 -176 ct +1419 -224 1430 -270 1453 -315 ct 1475 -360 1504 -394 1539 -416 ct 1574 -438 1612 -449 1653 -449 ct +1706 -449 1748 -432 1779 -400 ct 1810 -367 1826 -323 1826 -267 ct 1826 -245 1824 -223 1820 -201 ct +1497 -201 l 1496 -192 1495 -184 1495 -177 ct 1495 -136 1504 -105 1523 -83 ct +1542 -62 1565 -51 1593 -51 ct 1618 -51 1644 -59 1668 -76 ct 1693 -93 l 1712 -117 l +p +1509 -258 m 1755 -258 l 1755 -265 1756 -271 1756 -274 ct 1756 -312 1746 -340 1727 -360 ct +1709 -380 1685 -390 1655 -390 ct 1623 -390 1594 -379 1568 -357 ct 1541 -335 l +1522 -302 l p ef +1946 -153 m 1992 -482 l 2018 -606 l 2109 -606 l 2081 -471 l 1993 -153 l +p +1899 0 m 1917 -84 l 2001 -84 l 1983 0 l p ef +pom +gr +5715 5080 m 5264 4930 l 5265 5230 l 5715 5080 l p ef +1 lw 0 lj 3175 5080 m 5355 5080 l ps +12565 5080 m 12114 4930 l 12115 5230 l 12565 5080 l p ef +10795 5080 m 12205 5080 l ps +19050 5080 m 18599 4930 l 18600 5230 l 19050 5080 l p ef +16375 5080 m 18690 5080 l ps +gs +pum +10425 8413 t +66 0 m 66 -606 l 335 -606 l 389 -606 430 -600 458 -589 ct 486 -579 509 -559 526 -532 ct +542 -504 551 -474 551 -440 ct 551 -397 537 -361 509 -332 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 452 -224 474 -197 495 -165 ct 600 0 l 500 0 l +419 -126 l 396 -162 377 -190 361 -209 ct 346 -228 333 -242 321 -250 ct 309 -257 296 -263 284 -266 ct +275 -268 260 -269 239 -269 ct 146 -269 l 146 0 l p +146 -338 m 319 -338 l 355 -338 384 -342 405 -350 ct 425 -357 441 -369 452 -386 ct +463 -403 468 -421 468 -440 ct 468 -469 458 -493 437 -511 ct 416 -530 383 -539 338 -539 ct +146 -539 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1864 -141 m 1941 -131 l 1929 -86 1906 -52 1874 -27 ct 1841 -2 1799 9 1748 9 ct +1684 9 1633 -9 1595 -49 ct 1557 -88 1539 -144 1539 -215 ct 1539 -289 1558 -347 1596 -387 ct +1634 -428 1683 -449 1744 -449 ct 1802 -449 1850 -429 1888 -389 ct 1925 -349 1943 -292 1943 -220 ct +1943 -216 1943 -209 1943 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1712 -51 1748 -51 ct 1776 -51 1799 -58 1818 -72 ct 1837 -87 l 1853 -110 l +p +1620 -261 m 1865 -261 l 1862 -298 1852 -326 1837 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1682 -376 1658 -353 ct 1635 -330 l 1622 -300 l p ef +2040 -520 m 2040 -606 l 2114 -606 l 2114 -520 l p +2040 0 m 2040 -439 l 2114 -439 l 2114 0 l p ef +2347 0 m 2180 -439 l 2259 -439 l 2353 -176 l 2363 -147 2373 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2507 -439 l 2583 -439 l 2417 0 l p ef +2949 -141 m 3026 -131 l 3014 -86 2991 -52 2959 -27 ct 2926 -2 2884 9 2833 9 ct +2769 9 2718 -9 2680 -49 ct 2642 -88 2624 -144 2624 -215 ct 2624 -289 2643 -347 2681 -387 ct +2719 -428 2768 -449 2829 -449 ct 2887 -449 2935 -429 2973 -389 ct 3010 -349 3028 -292 3028 -220 ct +3028 -216 3028 -209 3028 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2797 -51 2833 -51 ct 2861 -51 2884 -58 2903 -72 ct 2922 -87 l 2938 -110 l +p +2705 -261 m 2950 -261 l 2947 -298 2937 -326 2922 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2767 -376 2743 -353 ct 2720 -330 l 2707 -300 l p ef +3372 0 m 3372 -606 l 3601 -606 l 3641 -606 3672 -604 3693 -600 ct 3723 -595 3748 -586 3768 -572 ct +3788 -558 3804 -538 3816 -513 ct 3829 -488 3835 -461 3835 -430 ct 3835 -379 3818 -335 3785 -300 ct +3753 -264 3693 -246 3608 -246 ct 3452 -246 l 3452 0 l p +3452 -318 m 3609 -318 l 3661 -318 3697 -327 3719 -346 ct 3741 -366 3752 -393 3752 -428 ct +3752 -453 3746 -475 3733 -493 ct 3720 -511 3703 -523 3682 -529 ct 3669 -532 3644 -534 3607 -534 ct +3452 -534 l p ef +4205 -54 m 4177 -30 4151 -14 4125 -4 ct 4100 5 4072 9 4043 9 ct 3995 9 3958 -1 3932 -25 ct +3906 -49 3893 -79 3893 -115 ct 3893 -137 3898 -156 3908 -174 ct 3918 -192 3930 -206 3946 -217 ct +3962 -228 3980 -236 4000 -241 ct 4014 -245 4036 -249 4066 -253 ct 4126 -260 4170 -268 4199 -278 ct +4199 -288 4199 -295 4199 -298 ct 4199 -328 4192 -349 4178 -362 ct 4159 -379 4131 -387 4093 -387 ct +4058 -387 4032 -381 4016 -369 ct 3999 -356 3987 -335 3979 -303 ct 3906 -313 l +3913 -345 3923 -370 3939 -389 ct 3954 -408 3976 -423 4004 -433 ct 4033 -443 4066 -449 4104 -449 ct +4142 -449 4172 -444 4195 -435 ct 4219 -427 4236 -415 4247 -402 ct 4258 -389 4266 -372 4270 -351 ct +4273 -339 4274 -316 4274 -283 ct 4274 -184 l 4274 -114 4276 -71 4279 -52 ct +4282 -34 4288 -16 4298 0 ct 4220 0 l 4212 -15 l 4207 -33 l p +4199 -220 m 4172 -209 4131 -200 4077 -192 ct 4047 -187 4025 -182 4012 -177 ct +4000 -171 3990 -163 3983 -153 ct 3976 -142 3973 -130 3973 -117 ct 3973 -98 3980 -81 3995 -68 ct +4010 -55 4032 -48 4061 -48 ct 4090 -48 4115 -54 4138 -67 ct 4160 -79 4176 -96 4187 -118 ct +4195 -135 4199 -160 4199 -193 ct p ef +4531 -66 m 4542 0 l 4521 3 4502 5 4485 5 ct 4458 5 4437 1 4423 -7 ct 4408 -15 4397 -26 4391 -40 ct +4385 -54 4382 -83 4382 -128 ct 4382 -381 l 4327 -381 l 4327 -439 l 4382 -439 l +4382 -547 l 4456 -592 l 4456 -439 l 4531 -439 l 4531 -381 l 4456 -381 l +4456 -124 l 4456 -103 4457 -89 4460 -83 ct 4463 -77 4467 -72 4473 -69 ct 4479 -65 4487 -63 4498 -63 ct +4506 -63 l 4517 -64 l p ef +4606 0 m 4606 -606 l 4681 -606 l 4681 -388 l 4716 -429 4759 -449 4812 -449 ct +4845 -449 4873 -442 4897 -429 ct 4921 -417 4938 -399 4949 -376 ct 4959 -354 4964 -321 4964 -278 ct +4964 0 l 4890 0 l 4890 -278 l 4890 -315 4882 -342 4865 -359 ct 4849 -376 4827 -385 4797 -385 ct +4775 -385 4754 -379 4735 -367 ct 4715 -356 4701 -340 4693 -321 ct 4685 -301 4681 -274 4681 -240 ct +4681 0 l p ef +pom +gr +0 lw 1 lj 1905 12030 m 3175 13935 l ps +3175 13935 m 4445 12030 l ps +3175 12030 m 3175 15205 l ps +0.996 c 12565 15205 m 13835 13935 l 16375 13935 l 16375 16475 l 13835 16475 l +12565 15205 l p ef +0.000 c 12565 15205 m 13835 13935 l 16375 13935 l 16375 16475 l 13835 16475 l +12565 15205 l pc +gs +pum +13573 15504 t +65 0 m 65 -606 l 274 -606 l 321 -606 357 -603 382 -597 ct 416 -589 446 -575 471 -554 ct +503 -527 526 -492 542 -450 ct 558 -408 566 -360 566 -306 ct 566 -260 561 -219 550 -184 ct +539 -148 525 -119 509 -95 ct 492 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +353 -3 320 0 284 0 ct p +145 -71 m 275 -71 l 315 -71 346 -75 369 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 457 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -371 473 -419 452 -453 ct +431 -487 406 -510 376 -522 ct 355 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -606 l 927 -606 l 1175 0 l 1083 0 l 1013 -183 l 759 -183 l +692 0 l p +782 -248 m 988 -248 l 924 -416 l 905 -467 891 -509 881 -542 ct 874 -503 863 -465 849 -426 ct +p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8255 16475 m 5715 16475 l 5715 13935 l 10795 13935 l 10795 16475 l +8255 16475 l pc +gs +pum +6708 15028 t +3 0 m 238 -315 l 31 -606 l 126 -606 l 236 -450 l 259 -418 276 -393 285 -376 ct +299 -398 315 -421 333 -445 ct 455 -606 l 543 -606 l 330 -320 l 559 0 l +460 0 l 307 -216 l 299 -228 290 -242 281 -256 ct 267 -234 258 -219 252 -211 ct +100 0 l p ef +611 0 m 611 -439 l 678 -439 l 678 -377 l 692 -399 710 -416 733 -429 ct +756 -442 782 -449 811 -449 ct 844 -449 870 -442 891 -428 ct 912 -415 927 -396 935 -372 ct +970 -423 1015 -449 1071 -449 ct 1114 -449 1148 -437 1171 -412 ct 1195 -388 1206 -351 1206 -301 ct +1206 0 l 1132 0 l 1132 -276 l 1132 -306 1130 -327 1125 -340 ct 1120 -354 1112 -364 1099 -372 ct +1086 -380 1071 -384 1054 -384 ct 1023 -384 998 -374 977 -353 ct 957 -333 947 -300 947 -255 ct +947 0 l 872 0 l 872 -285 l 872 -318 866 -343 854 -359 ct 842 -376 822 -384 795 -384 ct +774 -384 754 -379 736 -368 ct 719 -357 706 -340 698 -319 ct 690 -298 686 -267 686 -227 ct +686 0 l p ef +1326 -520 m 1326 -606 l 1400 -606 l 1400 -520 l p +1326 0 m 1326 -439 l 1400 -439 l 1400 0 l p ef +1673 -66 m 1684 0 l 1663 3 1644 5 1627 5 ct 1600 5 1579 1 1565 -7 ct 1550 -15 1539 -26 1533 -40 ct +1527 -54 1524 -83 1524 -128 ct 1524 -381 l 1469 -381 l 1469 -439 l 1524 -439 l +1524 -547 l 1598 -592 l 1598 -439 l 1673 -439 l 1673 -381 l 1598 -381 l +1598 -124 l 1598 -103 1599 -89 1602 -83 ct 1605 -77 1609 -72 1615 -69 ct 1621 -65 1629 -63 1640 -63 ct +1648 -63 l 1659 -64 l p ef +1997 0 m 1997 -606 l 2266 -606 l 2320 -606 2361 -600 2389 -589 ct 2417 -579 2440 -559 2457 -532 ct +2473 -504 2482 -474 2482 -440 ct 2482 -397 2468 -361 2440 -332 ct 2412 -302 2369 -283 2311 -275 ct +2332 -265 2348 -255 2359 -245 ct 2383 -224 2405 -197 2426 -165 ct 2531 0 l 2431 0 l +2350 -126 l 2327 -162 2308 -190 2292 -209 ct 2277 -228 2264 -242 2252 -250 ct +2240 -257 2227 -263 2215 -266 ct 2206 -268 2191 -269 2170 -269 ct 2077 -269 l +2077 0 l p +2077 -338 m 2250 -338 l 2286 -338 2315 -342 2336 -350 ct 2356 -357 2372 -369 2383 -386 ct +2394 -403 2399 -421 2399 -440 ct 2399 -469 2389 -493 2368 -511 ct 2347 -530 2314 -539 2269 -539 ct +2077 -539 l p ef +2609 0 m 2609 -606 l 3018 -606 l 3018 -534 l 2689 -534 l 2689 -346 l +2974 -346 l 2974 -275 l 2689 -275 l 2689 0 l p ef +pom +pum +6350 15981 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +584 0 m 584 -439 l 651 -439 l 651 -372 l 668 -403 683 -424 698 -434 ct +712 -444 728 -449 746 -449 ct 771 -449 796 -441 822 -425 ct 797 -356 l 778 -366 760 -372 742 -372 ct +726 -372 711 -367 698 -357 ct 685 -347 676 -334 670 -316 ct 662 -290 658 -261 658 -229 ct +658 0 l p ef +848 -219 m 848 -300 870 -361 915 -400 ct 953 -432 999 -449 1054 -449 ct 1114 -449 1163 -429 1202 -389 ct +1240 -350 1259 -295 1259 -225 ct 1259 -169 1251 -124 1234 -92 ct 1217 -60 1192 -34 1160 -16 ct +1127 0 1092 9 1054 9 ct 992 9 942 -9 904 -49 ct 867 -88 l 848 -145 l p +924 -219 m 924 -163 936 -121 961 -93 ct 985 -65 1016 -51 1054 -51 ct 1091 -51 1121 -65 1146 -93 ct +1170 -121 1183 -164 1183 -222 ct 1183 -276 1170 -317 1146 -345 ct 1121 -373 1090 -387 1054 -387 ct +1016 -387 985 -373 961 -345 ct 936 -317 l 924 -275 l p ef +1351 0 m 1351 -439 l 1418 -439 l 1418 -376 l 1451 -425 1497 -449 1558 -449 ct +1585 -449 1609 -444 1631 -434 ct 1653 -425 1670 -412 1681 -397 ct 1692 -382 1700 -363 1704 -342 ct +1707 -328 1708 -304 1708 -270 ct 1708 0 l 1634 0 l 1634 -267 l 1634 -297 1631 -320 1625 -335 ct +1619 -350 1609 -362 1594 -371 ct 1580 -380 1562 -384 1542 -384 ct 1511 -384 1483 -374 1460 -354 ct +1437 -334 1426 -296 1426 -239 ct 1426 0 l p ef +1991 -66 m 2002 0 l 1981 3 1962 5 1945 5 ct 1918 5 1897 1 1883 -7 ct 1868 -15 1857 -26 1851 -40 ct +1845 -54 1842 -83 1842 -128 ct 1842 -381 l 1787 -381 l 1787 -439 l 1842 -439 l +1842 -547 l 1916 -592 l 1916 -439 l 1991 -439 l 1991 -381 l 1916 -381 l +1916 -124 l 1916 -103 1917 -89 1920 -83 ct 1923 -77 1927 -72 1933 -69 ct 1939 -65 1947 -63 1958 -63 ct +1966 -63 l 1977 -64 l p ef +2316 0 m 2316 -606 l 2754 -606 l 2754 -534 l 2396 -534 l 2396 -349 l +2731 -349 l 2731 -277 l 2396 -277 l 2396 -71 l 2768 -71 l 2768 0 l +p ef +2886 0 m 2886 -439 l 2953 -439 l 2953 -376 l 2986 -425 3032 -449 3093 -449 ct +3120 -449 3144 -444 3166 -434 ct 3188 -425 3205 -412 3216 -397 ct 3227 -382 3235 -363 3239 -342 ct +3242 -328 3243 -304 3243 -270 ct 3243 0 l 3169 0 l 3169 -267 l 3169 -297 3166 -320 3160 -335 ct +3154 -350 3144 -362 3129 -371 ct 3115 -380 3097 -384 3077 -384 ct 3046 -384 3018 -374 2995 -354 ct +2972 -334 2961 -296 2961 -239 ct 2961 0 l p ef +3647 0 m 3647 -55 l 3619 -11 3579 9 3524 9 ct 3489 9 3457 0 3428 -19 ct 3399 -38 3376 -65 3360 -99 ct +3344 -134 3335 -174 3335 -219 ct 3335 -263 3343 -302 3357 -338 ct 3372 -374 3394 -401 3423 -420 ct +3452 -439 3485 -449 3521 -449 ct 3548 -449 3571 -443 3592 -432 ct 3613 -421 3629 -406 3642 -388 ct +3642 -606 l 3716 -606 l 3716 0 l p +3412 -219 m 3412 -162 3424 -120 3448 -93 ct 3471 -65 3499 -51 3531 -51 ct 3564 -51 3592 -64 3614 -91 ct +3637 -117 3649 -158 3649 -212 ct 3649 -273 3637 -317 3614 -345 ct 3591 -373 3562 -387 3528 -387 ct +3495 -387 3467 -374 3445 -346 ct 3423 -319 l 3412 -277 l p ef +pom +gr +21272 17745 m 19550 17745 l 19274 17745 19050 17521 19050 17245 ct 19050 13165 l +19050 12889 19274 12665 19550 12665 ct 22995 12665 l 23271 12665 23495 12889 23495 13165 ct +23495 17245 l 23495 17521 23271 17745 22995 17745 ct 21272 17745 l pc +gs +pum +20360 14552 t +236 0 m 285 -234 l 98 -606 l 185 -606 l 275 -429 l 294 -390 313 -349 332 -305 ct +352 -342 380 -383 415 -428 ct 557 -606 l 654 -606 l 365 -228 l 317 0 l +p ef +597 -166 m 597 -252 622 -323 673 -379 ct 714 -425 769 -449 836 -449 ct 889 -449 932 -432 964 -399 ct +997 -366 1013 -321 1013 -265 ct 1013 -215 1003 -168 982 -124 ct 962 -81 933 -47 895 -24 ct +858 -1 818 9 776 9 ct 742 9 711 2 683 -11 ct 655 -26 634 -47 619 -74 ct 604 -100 l +597 -131 l p +672 -174 m 672 -132 682 -101 701 -80 ct 721 -58 747 -47 777 -47 ct 793 -47 809 -51 825 -57 ct +840 -64 855 -74 869 -87 ct 882 -100 894 -115 903 -132 ct 913 -149 920 -167 926 -187 ct +935 -214 939 -240 939 -265 ct 939 -305 929 -336 909 -358 ct 889 -380 864 -391 833 -391 ct +810 -391 789 -385 769 -374 ct 750 -363 733 -346 717 -325 ct 701 -303 690 -278 683 -250 ct +675 -221 l 672 -196 l p ef +1359 -79 m 1307 -19 1253 9 1198 9 ct 1164 9 1136 0 1116 -19 ct 1095 -38 1084 -62 1084 -90 ct +1084 -109 1089 -140 1099 -185 ct 1151 -439 l 1226 -439 l 1168 -158 l 1163 -134 1160 -116 1160 -103 ct +1160 -87 1165 -74 1175 -65 ct 1185 -55 1200 -51 1220 -51 ct 1241 -51 1261 -56 1281 -66 ct +1301 -76 1318 -90 1333 -107 ct 1347 -125 1359 -145 1368 -169 ct 1374 -184 1381 -211 1389 -249 ct +1429 -439 l 1504 -439 l 1412 0 l 1343 0 l p ef +1536 0 m 1627 -439 l 1694 -439 l 1675 -349 l 1698 -383 1720 -408 1741 -424 ct +1763 -441 1785 -449 1808 -449 ct 1823 -449 1841 -443 1863 -433 ct 1832 -363 l +1819 -372 1805 -377 1790 -377 ct 1763 -377 1736 -362 1709 -333 ct 1681 -304 1660 -252 1644 -176 ct +1607 0 l p ef +pom +pum +20241 15505 t +510 -213 m 591 -202 l 565 -132 528 -79 480 -43 ct 431 -7 377 10 316 10 ct +243 10 184 -12 141 -57 ct 98 -102 76 -166 76 -250 ct 76 -359 109 -449 175 -521 ct +233 -584 306 -616 393 -616 ct 457 -616 509 -599 549 -564 ct 589 -530 612 -484 618 -425 ct +543 -418 l 535 -462 518 -495 493 -517 ct 468 -538 436 -549 397 -549 ct 322 -549 262 -516 217 -450 ct +177 -394 157 -326 157 -248 ct 157 -186 172 -138 203 -105 ct 234 -73 273 -56 323 -56 ct +364 -56 402 -70 436 -97 ct 470 -124 l 495 -163 l p ef +650 -166 m 650 -252 675 -323 726 -379 ct 767 -425 822 -449 889 -449 ct 942 -449 985 -432 1017 -399 ct +1050 -366 1066 -321 1066 -265 ct 1066 -215 1056 -168 1035 -124 ct 1015 -81 986 -47 948 -24 ct +911 -1 871 9 829 9 ct 795 9 764 2 736 -11 ct 708 -26 687 -47 672 -74 ct 657 -100 l +650 -131 l p +725 -174 m 725 -132 735 -101 754 -80 ct 774 -58 800 -47 830 -47 ct 846 -47 862 -51 878 -57 ct +893 -64 908 -74 922 -87 ct 935 -100 947 -115 956 -132 ct 966 -149 973 -167 979 -187 ct +988 -214 992 -240 992 -265 ct 992 -305 982 -336 962 -358 ct 942 -380 917 -391 886 -391 ct +863 -391 842 -385 822 -374 ct 803 -363 786 -346 770 -325 ct 754 -303 743 -278 736 -250 ct +728 -221 l 725 -196 l p ef +1409 -63 m 1366 -14 1321 9 1275 9 ct 1233 9 1198 -5 1171 -36 ct 1143 -66 1129 -111 1129 -169 ct +1129 -223 1140 -272 1162 -316 ct 1184 -360 1211 -394 1244 -416 ct 1277 -438 1310 -449 1343 -449 ct +1398 -449 1439 -422 1467 -370 ct 1517 -606 l 1591 -606 l 1465 0 l 1396 0 l +p +1204 -184 m 1204 -153 1207 -129 1213 -111 ct 1219 -94 1229 -79 1244 -67 ct +1258 -55 1276 -50 1296 -50 ct 1330 -50 1361 -67 1388 -102 ct 1425 -149 1444 -207 1444 -276 ct +1444 -311 1435 -338 1417 -358 ct 1398 -377 1376 -387 1348 -387 ct 1330 -387 1314 -383 1299 -375 ct +1284 -367 1270 -353 1255 -334 ct 1241 -315 1228 -291 1219 -261 ct 1209 -232 l +1204 -206 l p ef +1911 -149 m 1984 -141 l 1974 -105 1949 -71 1912 -38 ct 1874 -6 1829 9 1777 9 ct +1745 9 1715 2 1688 -12 ct 1661 -27 1640 -49 1626 -78 ct 1611 -106 1604 -139 1604 -176 ct +1604 -224 1615 -270 1638 -315 ct 1660 -360 1689 -394 1724 -416 ct 1759 -438 1797 -449 1838 -449 ct +1891 -449 1933 -432 1964 -400 ct 1995 -367 2011 -323 2011 -267 ct 2011 -245 2009 -223 2005 -201 ct +1682 -201 l 1681 -192 1680 -184 1680 -177 ct 1680 -136 1689 -105 1708 -83 ct +1727 -62 1750 -51 1778 -51 ct 1803 -51 1829 -59 1853 -76 ct 1878 -93 l 1897 -117 l +p +1694 -258 m 1940 -258 l 1940 -265 1941 -271 1941 -274 ct 1941 -312 1931 -340 1912 -360 ct +1894 -380 1870 -390 1840 -390 ct 1808 -390 1779 -379 1753 -357 ct 1726 -335 l +1707 -302 l p ef +pom +pum +20214 16458 t +35 0 m 162 -606 l 243 -606 l 190 -354 l 504 -354 l 557 -606 l 638 -606 l +512 0 l 430 0 l 490 -285 l 176 -285 l 116 0 l p ef +959 -149 m 1032 -141 l 1022 -105 997 -71 960 -38 ct 922 -6 877 9 825 9 ct +793 9 763 2 736 -12 ct 709 -27 688 -49 674 -78 ct 659 -106 652 -139 652 -176 ct +652 -224 663 -270 686 -315 ct 708 -360 737 -394 772 -416 ct 807 -438 845 -449 886 -449 ct +939 -449 981 -432 1012 -400 ct 1043 -367 1059 -323 1059 -267 ct 1059 -245 1057 -223 1053 -201 ct +730 -201 l 729 -192 728 -184 728 -177 ct 728 -136 737 -105 756 -83 ct 775 -62 798 -51 826 -51 ct +851 -51 877 -59 901 -76 ct 926 -93 l 945 -117 l p +742 -258 m 988 -258 l 988 -265 989 -271 989 -274 ct 989 -312 979 -340 960 -360 ct +942 -380 918 -390 888 -390 ct 856 -390 827 -379 801 -357 ct 774 -335 l 755 -302 l +p ef +1113 0 m 1204 -439 l 1271 -439 l 1252 -349 l 1275 -383 1297 -408 1318 -424 ct +1340 -441 1362 -449 1385 -449 ct 1400 -449 1418 -443 1440 -433 ct 1409 -363 l +1396 -372 1382 -377 1367 -377 ct 1340 -377 1313 -362 1286 -333 ct 1258 -304 1237 -252 1221 -176 ct +1184 0 l p ef +1726 -149 m 1799 -141 l 1789 -105 1764 -71 1727 -38 ct 1689 -6 1644 9 1592 9 ct +1560 9 1530 2 1503 -12 ct 1476 -27 1455 -49 1441 -78 ct 1426 -106 1419 -139 1419 -176 ct +1419 -224 1430 -270 1453 -315 ct 1475 -360 1504 -394 1539 -416 ct 1574 -438 1612 -449 1653 -449 ct +1706 -449 1748 -432 1779 -400 ct 1810 -367 1826 -323 1826 -267 ct 1826 -245 1824 -223 1820 -201 ct +1497 -201 l 1496 -192 1495 -184 1495 -177 ct 1495 -136 1504 -105 1523 -83 ct +1542 -62 1565 -51 1593 -51 ct 1618 -51 1644 -59 1668 -76 ct 1693 -93 l 1712 -117 l +p +1509 -258 m 1755 -258 l 1755 -265 1756 -271 1756 -274 ct 1756 -312 1746 -340 1727 -360 ct +1709 -380 1685 -390 1655 -390 ct 1623 -390 1594 -379 1568 -357 ct 1541 -335 l +1522 -302 l p ef +1946 -153 m 1992 -482 l 2018 -606 l 2109 -606 l 2081 -471 l 1993 -153 l +p +1899 0 m 1917 -84 l 2001 -84 l 1983 0 l p ef +pom +gr +3175 15240 m 3625 15389 l 3624 15089 l 3175 15240 l p ef +1 lw 0 lj 5715 15240 m 3535 15240 l ps +10795 15240 m 11245 15389 l 11244 15089 l 10795 15240 l p ef +12565 15240 m 11155 15240 l ps +16510 15240 m 16960 15389 l 16959 15089 l 16510 15240 l p ef +19050 15240 m 16870 15240 l ps +gs +pum +10319 18547 t +219 0 m 219 -534 l 19 -534 l 19 -606 l 500 -606 l 500 -534 l 299 -534 l +299 0 l p ef +584 0 m 584 -439 l 651 -439 l 651 -372 l 668 -403 683 -424 698 -434 ct +712 -444 728 -449 746 -449 ct 771 -449 796 -441 822 -425 ct 797 -356 l 778 -366 760 -372 742 -372 ct +726 -372 711 -367 698 -357 ct 685 -347 676 -334 670 -316 ct 662 -290 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -49 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -253 ct 1083 -260 1127 -268 1156 -278 ct +1156 -288 1156 -295 1156 -298 ct 1156 -328 1149 -349 1135 -362 ct 1116 -379 1088 -387 1050 -387 ct +1015 -387 989 -381 973 -369 ct 956 -356 944 -335 936 -303 ct 863 -313 l 870 -345 880 -370 896 -389 ct +911 -408 933 -423 961 -433 ct 990 -443 1023 -449 1061 -449 ct 1099 -449 1129 -444 1152 -435 ct +1176 -427 1193 -415 1204 -402 ct 1215 -389 1223 -372 1227 -351 ct 1230 -339 1231 -316 1231 -283 ct +1231 -184 l 1231 -114 1233 -71 1236 -52 ct 1239 -34 1245 -16 1255 0 ct 1177 0 l +1169 -15 l 1164 -33 l p +1156 -220 m 1129 -209 1088 -200 1034 -192 ct 1004 -187 982 -182 969 -177 ct +957 -171 947 -163 940 -153 ct 933 -142 930 -130 930 -117 ct 930 -98 937 -81 952 -68 ct +967 -55 989 -48 1018 -48 ct 1047 -48 1072 -54 1095 -67 ct 1117 -79 1133 -96 1144 -118 ct +1152 -135 1156 -160 1156 -193 ct p ef +1325 0 m 1325 -439 l 1392 -439 l 1392 -376 l 1425 -425 1471 -449 1532 -449 ct +1559 -449 1583 -444 1605 -434 ct 1627 -425 1644 -412 1655 -397 ct 1666 -382 1674 -363 1678 -342 ct +1681 -328 1682 -304 1682 -270 ct 1682 0 l 1608 0 l 1608 -267 l 1608 -297 1605 -320 1599 -335 ct +1593 -350 1583 -362 1568 -371 ct 1554 -380 1536 -384 1516 -384 ct 1485 -384 1457 -374 1434 -354 ct +1411 -334 1400 -296 1400 -239 ct 1400 0 l p ef +1772 -131 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1899 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2052 -86 2060 -102 2060 -121 ct 2060 -138 2053 -151 2038 -160 ct +2028 -167 2002 -175 1962 -186 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -301 1784 -322 ct 1784 -342 1788 -360 1797 -376 ct 1806 -393 1819 -407 1834 -418 ct +1846 -427 1861 -434 1881 -440 ct 1901 -446 1923 -449 1946 -449 ct 1980 -449 2010 -444 2036 -434 ct +2063 -424 2082 -410 2094 -393 ct 2107 -376 2115 -354 2120 -325 ct 2047 -315 l +2044 -338 2034 -356 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -382 1878 -370 ct +1863 -359 1856 -346 1856 -331 ct 1856 -321 1859 -312 1865 -305 ct 1871 -297 1881 -290 1894 -285 ct +1901 -282 1923 -276 1959 -266 ct 2012 -252 2049 -240 2070 -231 ct 2090 -222 2107 -209 2119 -192 ct +2130 -175 2136 -154 2136 -129 ct 2136 -104 2129 -80 2115 -58 ct 2100 -37 2079 -20 2052 -8 ct +2025 3 1994 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -439 l 2265 -439 l 2265 -377 l 2279 -399 2297 -416 2320 -429 ct +2343 -442 2369 -449 2398 -449 ct 2431 -449 2457 -442 2478 -428 ct 2499 -415 2514 -396 2522 -372 ct +2557 -423 2602 -449 2658 -449 ct 2701 -449 2735 -437 2758 -412 ct 2782 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2717 -327 2712 -340 ct 2707 -354 2699 -364 2686 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2585 -374 2564 -353 ct 2544 -333 2534 -300 2534 -255 ct +2534 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -343 2441 -359 ct 2429 -376 2409 -384 2382 -384 ct +2361 -384 2341 -379 2323 -368 ct 2306 -357 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -606 l 2988 -606 l 2988 -520 l p +2914 0 m 2914 -439 l 2988 -439 l 2988 0 l p ef +3261 -66 m 3272 0 l 3251 3 3232 5 3215 5 ct 3188 5 3167 1 3153 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -381 l 3057 -381 l 3057 -439 l 3112 -439 l +3112 -547 l 3186 -592 l 3186 -439 l 3261 -439 l 3261 -381 l 3186 -381 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3193 -77 3197 -72 3203 -69 ct 3209 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +3584 0 m 3584 -606 l 3813 -606 l 3853 -606 3884 -604 3905 -600 ct 3935 -595 3960 -586 3980 -572 ct +4000 -558 4016 -538 4028 -513 ct 4041 -488 4047 -461 4047 -430 ct 4047 -379 4030 -335 3997 -300 ct +3965 -264 3905 -246 3820 -246 ct 3664 -246 l 3664 0 l p +3664 -318 m 3821 -318 l 3873 -318 3909 -327 3931 -346 ct 3953 -366 3964 -393 3964 -428 ct +3964 -453 3958 -475 3945 -493 ct 3932 -511 3915 -523 3894 -529 ct 3881 -532 3856 -534 3819 -534 ct +3664 -534 l p ef +4417 -54 m 4389 -30 4363 -14 4337 -4 ct 4312 5 4284 9 4255 9 ct 4207 9 4170 -1 4144 -25 ct +4118 -49 4105 -79 4105 -115 ct 4105 -137 4110 -156 4120 -174 ct 4130 -192 4142 -206 4158 -217 ct +4174 -228 4192 -236 4212 -241 ct 4226 -245 4248 -249 4278 -253 ct 4338 -260 4382 -268 4411 -278 ct +4411 -288 4411 -295 4411 -298 ct 4411 -328 4404 -349 4390 -362 ct 4371 -379 4343 -387 4305 -387 ct +4270 -387 4244 -381 4228 -369 ct 4211 -356 4199 -335 4191 -303 ct 4118 -313 l +4125 -345 4135 -370 4151 -389 ct 4166 -408 4188 -423 4216 -433 ct 4245 -443 4278 -449 4316 -449 ct +4354 -449 4384 -444 4407 -435 ct 4431 -427 4448 -415 4459 -402 ct 4470 -389 4478 -372 4482 -351 ct +4485 -339 4486 -316 4486 -283 ct 4486 -184 l 4486 -114 4488 -71 4491 -52 ct +4494 -34 4500 -16 4510 0 ct 4432 0 l 4424 -15 l 4419 -33 l p +4411 -220 m 4384 -209 4343 -200 4289 -192 ct 4259 -187 4237 -182 4224 -177 ct +4212 -171 4202 -163 4195 -153 ct 4188 -142 4185 -130 4185 -117 ct 4185 -98 4192 -81 4207 -68 ct +4222 -55 4244 -48 4273 -48 ct 4302 -48 4327 -54 4350 -67 ct 4372 -79 4388 -96 4399 -118 ct +4407 -135 4411 -160 4411 -193 ct p ef +4742 -66 m 4753 0 l 4732 3 4713 5 4696 5 ct 4669 5 4648 1 4634 -7 ct 4619 -15 4608 -26 4602 -40 ct +4596 -54 4593 -83 4593 -128 ct 4593 -381 l 4538 -381 l 4538 -439 l 4593 -439 l +4593 -547 l 4667 -592 l 4667 -439 l 4742 -439 l 4742 -381 l 4667 -381 l +4667 -124 l 4667 -103 4668 -89 4671 -83 ct 4674 -77 4678 -72 4684 -69 ct 4690 -65 4698 -63 4709 -63 ct +4717 -63 l 4728 -64 l p ef +4818 0 m 4818 -606 l 4893 -606 l 4893 -388 l 4928 -429 4971 -449 5024 -449 ct +5057 -449 5085 -442 5109 -429 ct 5133 -417 5150 -399 5161 -376 ct 5171 -354 5176 -321 5176 -278 ct +5176 0 l 5102 0 l 5102 -278 l 5102 -315 5094 -342 5077 -359 ct 5061 -376 5039 -385 5009 -385 ct +4987 -385 4966 -379 4947 -367 ct 4927 -356 4913 -340 4905 -321 ct 4897 -301 4893 -274 4893 -240 ct +4893 0 l p ef +pom +gr +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/docs/exploring-gnuradio/swr-block-diagram.png b/docs/exploring-gnuradio/swr-block-diagram.png new file mode 100644 index 00000000..580aa687 Binary files /dev/null and b/docs/exploring-gnuradio/swr-block-diagram.png differ diff --git a/docs/exploring-gnuradio/usrp-block-diagram.eps b/docs/exploring-gnuradio/usrp-block-diagram.eps new file mode 100644 index 00000000..190b9dee --- /dev/null +++ b/docs/exploring-gnuradio/usrp-block-diagram.eps @@ -0,0 +1,2785 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFE300707800000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFE380E1FE00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C001C0C30700000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E1830300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E3820300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00077000300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0003E000300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0001C000700000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFC01C000E00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFC03E001C00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00037003800000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0006700F000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E381C000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C001C1C18000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00180C30000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00380E7FF00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0070077FF00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300701F80FF80007C00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300707FE0FFE000FF00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300706070C060018380000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070E038C030010180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070C000C030030180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070E000C030000180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300707C00C070000380000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300703FC0FFE0000300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000003007007E0FFC0000700000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000003007000F0FFF0000E00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300700038C030003C00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030071C018C038007000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000038061C018C01800E000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000018060E038C03801C000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000001C0E0F070C070018000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000FFC07FE0FFF003FF80000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000007F001FC0FFC003FF80000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080007E00000000000000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08001FF80000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800381C0000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800700C0000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800600E03808E07C8C0E03180E023000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0000FE0FF8FCFE3F83183F83F800000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0001C70F3C30FC71C31871C3F000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0003038E0C30E0E0E318E0E38000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0003018C0C30C0C06318C0630000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0007018C0C30C0C06318FFE30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0007018C0C30C0C07318FFE30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0067018C0C30C0C07318C0030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800600E7018C0C30C0C06318C0030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800700C3038C0C30C0C06318C0630000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800381C3830C0C30C0E0E318E0E30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08001FF81FF0C0C3CC07FC3187FC30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080007E00FC0C0C1CC01F03181F030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%007FFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000000FFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000010000 +%004000000000000000000000000000020000040000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000200000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000400000000000000000000 +%004000000000000000000000000000020000000000000000000001000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000C000000000000000000000 +%004000000000000000000000000000020000000000000000000000180000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000010000000000000000000000 +%004000000000000000000000000000020000000000000000000000040000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000020001C03FF800FE0000000000 +%00400000000000000000000000000002000000000003C03FF001FE000200000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000040001E03FFC03FF8000000000 +%00400000000000000000000000000002000000000003C03FFC03FF000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000360300E07038000000000 +%00400000000000000000000000000002000000000003C0301C0703800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000036030060601C000000000 +%0040000000000000000000000000000200000000000760300E0E01800040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000073030070C00C000000000 +%004000000000000000000000000000020000000000066030060C01C00020000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000063030030C000000000000 +%004000000000000000000000000000020000000000067030071C00000010000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000063830031C000000000000 +%0040000000000000000000000000000200000000000C3030071800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000E1830031C00000000FFFF +%FFC0000000000000000000000000000200000000000C3030031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400200000C1830031C00000000FFFF +%FFC0000000000000000000000000000200000000001C1830031800000003FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000C1C30031C000000000000 +%00400000000000000000000000000003FFFFF800001C1830031800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFC30030C000000000000 +%0040000000000000000000000000000200000000001FFC30071800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFE30070C00C000000000 +%0040000000000000000000000000000200000000003FFC30061C00C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380630070E00C000000000 +%004000000000000000000000000000020000000000300E30060C01C00000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400020003006300E0701C000000000 +%004000000000000000000000000000020000000000300E300E0E03800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400010003007301E07838000000000 +%0040000000000000000000000000000200000000006006301C0707800040000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000070033FF801FF0000000000 +%00400000000000000000000000000002000000000060073FF803FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400004006003BFE0007C0000000000 +%004000000000000000000000000000020000000000E0033FE000FC000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000400000000000000000000000 +%004000000000000000000000000000020000000000000000000000001000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000003FF800000000003000000000000000000400000080000000000000000000000 +%00400000000000000000000000000002000000000000000000000000800000008000000000003F +%F800000000003000000000000000000400 +%0008000000000003FFC00000000003000000000000000000400000040000000000000000000000 +%00400000000000000000000000000002000000000000000000000001000000008000000000003F +%FC00000000003000000000000000000400 +%000800000000000300E00000000002000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000038 +%0E00000000002000000000000000000400 +%000800000000000300600000000000000000000000000000400000018000000000000000000000 +%0040000000000000000000000000000200000000000000000000000C0000000080000000000030 +%0700000000000000000000000000000400 +%000800000000000300700000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000100000000080000000000030 +%0700000000000000000000000000000400 +%00080000000000030070FE03F03F0330187E000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000030 +%0707E03F03F8338187F000000000000400 +%00080000000000030061EF073873833838E7000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000030 +%070E7073873C31818E7800000000000400 +%000800000000000301E1830E1CE0C3183181800000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000038 +%1E1838E0CE0C31831C1800000000000400 +%0008000000000003FF83018C0CC0E3183181C00000000000400000000400000000000000000000 +%00400000000000000000000000000002000000000000000000000100000000008000000000003F +%FC3018C0CC0631C3180C00000000000400 +%0008000000000003FE03019C01C0E30C6381C00000000000400000000200000000000000000000 +%00400000000000000000000000000002000000000000000000000200000000008000000000003F +%F03018C00C0630C3181C00000000000400 +%00080000000000030703FF9C01FFE30C63FFC00000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000030 +%383FF8C00FFE30C61FFC00000000000400 +%00080000000000030383001C01C0030C6380000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000030 +%183000C00C003066180000000000000400 +%000800000000000301C3001C01C00306C380000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000030 +%1C3000C00C003066180000000000000400 +%000800000000000300E3018C0CC04306C181800000000000400000000000000000000000010000 +%004000000000000000000000000000020000040000000000000000000000000080000000000030 +%0E3818C0CC06306C180C00000000000400 +%000800000000000300E1838E1CE0C307C1C1800000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%071838E0CE0E303C1C1C00000000000400 +%00080000000000030071E7073873C30380E7800000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%071E707387BC30380F7800000000000400 +%00080000000000030030FE03F03F8303807F000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%0387E03F03F8303807F000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800FFC0000000000030000000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFC00000000 +%00030000000000C0000000000000C00400 +%000800FFF000000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF00000000 +%0003000C000000C0000000000000C00400 +%000800E07800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E0780000000 +%0003000C000000C0000000000000C00400 +%000800E01800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C0000000 +%0003000C000000C0000000000000C00400 +%000800E01C00000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00C0000000 +%0003000E000000C0000000000000C00400 +%000800E00C1FC38183FC37E3F0FC1FCDF03F81FE1FC7FC00400000000000000000000000010000 +%0040000000000000000000000000000200000400000000000000000000000000800E00C1FE1818 +%3FE37E1F0FC0FCDF01FC0FE1FC7EC00400 +%000800E00C39E381873C3CE0C1CE1FCF3879C3CF1F8E7C00400000000020000000000000000000 +%0040000000000000000000000000000200000000000000000000200000000000800E00E38E1818 +%73E3EF0C1CF0FCFB879E1CF1F8E7C00400 +%000800E00E7063818C1C3870C3031C0E1C60E3031C1C3C00400000000040000000000000000000 +%0040000000000000000000000000000200000000000000000000100000000000800E00E3071818 +%E1E3830C3030E0E1C6063831C1C1C00400 +%000800E00E0063818C0C3030C7031C0C0CC0600318181C00400000000100000000000000000000 +%0040000000000000000000000000000200000000000000000000040000000000800E00E0071818 +%C0E3030C3038C0C0CE070031C181C00400 +%000800E00E006381980C3030C7039C0C0CC0700718181C00400000000200000000000000000000 +%0040000000000000000000000000000200000000000000000000020000000000800E00E0071818 +%C0E3030C7038C0C0CC0300718180C00400 +%000800E00C1FE381980C3030C7FF9C0C0CC030FF18381C00400000000400000000000000000000 +%0040000000000000000000000000000200000000000000000000010000000000800E00E0FF1819 +%C0E3030C7FF8C0C0EC030FF18180C00400 +%000800E00C3E6381980C3030C7001C0C0CC033E318381C00400000000800000000000000000000 +%0040000000000000000000000000000200000000000000000000008000000000800E00E3E71819 +%C0E3030C7000C0C0EC031E318180C00400 +%000800E00C7063839C0C3030C6001C0C0CC0730318181C00400000001000000000000000000000 +%0040000000000000000000000000000200000000000000000000004000000000800E00C7071818 +%C0E3030C7000C0C0CC0330318180C00400 +%000800E01C6063838C0C3030C7031C0C0CE0670318181C00400000002000000000000000000000 +%0040000000000000000000000000000200000000000000000000002000000000800E01C6071838 +%C0E3030C3030C0C0CE0730318181C00400 +%000800E03860E1878C1C3030C3871C0E1860E707181C3C00400000008000000000000000000000 +%0040000000000000000000000000000200000000000000000000001800000000800E0386071838 +%E1E3030C3830C0E1C706307180C1C00400 +%000800FFF071E1FF877C3030F1CE1C0F3879C39F180E7C00400000010000000000000000000000 +%0040000000000000000000000000000200000000000000000000000400000000800FFF039F1FF8 +%73E3030F1EF0C0FB839E39F180F7C00400 +%000800FFE03F30F983EC303070FC1C0DF01F81FB1807FC00400000020000000000000000000000 +%0040000000000000000000000000000200000000000000000000000200000000800FFE03F30FD8 +%3FE303078FE0C0DF01F81FB9807EC00400 +%0008000000000000000C0000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%00E0000000000000000000000000000400 +%0008000000000000080C0000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%C0C0000000000000000000000000000400 +%00080000000000000C1C0000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%E1C0000000000000000000000000000400 +%000800000000000007F80000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%7F80000000000000000000000000000400 +%000800000000000003E00000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%1E00000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000020001C03FF801FE0000000000 +%00400000000000000000000000000002000000000003C03FF801FE000200000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000040001E03FFC03FF8000000000 +%00400000000000000000000000000002000000000003C03FFC03FF000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000360300E07018000000000 +%00400000000000000000000000000002000000000003E0301C0703800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000036030070E01C000000000 +%0040000000000000000000000000000200000000000660300E0E01800040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000073030070C00C000000000 +%004000000000000000000000000000020000000000066030060C00800020000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000063030030C000000000000 +%004000000000000000000000000000020000000000067030071C00000010000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040010000063830031C000000000000 +%0040000000000000000000000000000200000000000C3030031800000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000E1830031C00000000FFFF +%FFC0000000000000000000000000000200000000000C3830031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000C1C30031C00000000FFFF +%FFC0000000000000000000000000000200000800001C1830031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400200000C1C30031C000000000000 +%00400000000000000000000000000003FFFFF800001C1830031800000002000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFC30030C000000000000 +%0040000000000000000000000000000200000000001FFC30071C00000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFE30070C00C000000000 +%0040000000000000000000000000000200000000003FFC30060C00C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380630070E00C000000000 +%004000000000000000000000000000020000000000300E30060C01C00000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400020003007300E0701C000000000 +%004000000000000000000000000000020000000000300E300E0E03800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003007383C03C78000000000 +%0040000000000000000000000000000200000000006006303C0787000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000070033FF801FF0000000000 +%00400000000000000000000000000002000000000060073FF803FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400004006003BFE0007C0000000000 +%004000000000000000000000000000020000000000E0033FE000F8000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000400000000000000000000000 +%004000000000000000000000000000020000000000000000000000001000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000018000000000000000000000 +%0040000000000000000000000000000200000000000000000000000C0000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000004000000000000000000000 +%004000000000000000000000000000020000000000000000000000100000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000400000000000000000000 +%004000000000000000000000000000020000000000000000000001000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000200000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000FFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF9FF8007C001C000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF9FFE01FF801C000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007001C0F0383C03E000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C070700C036000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C030E00C036000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C030C000063000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C031C000063000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007001C071C0000E3800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF1FFE1C0FE0C1800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FE1FFC1C0FE0C1800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C001C00E1FFC00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000C0061FFC00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000C006380E00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000E006300600000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000781E300700000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C0003FFC700700000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C0000FF0600300000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000007FFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000008000000000000000000000 +%004000000000000000000000000000020000000000000000000000080000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000010000000000000000000000 +%004000000000000000000000000000020000000000000000000000040000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001003FE00060007C0000000000 +%0040000000000000000000000000000200000000003FE000E00078000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002003FF800F001FF0000000000 +%0040000000000000000000000000000200000000003FF800E001FE000200000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000400383E00F003C78000000000 +%004000000000000000000000000000020000000000303C01E00787000100000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000800380E01F80701C000000000 +%004000000000000000000000000000020000000000300E01B00E03800080000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380701980E00C000000000 +%004000000000000000000000000000020000000000300601B00C01C00040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000380301980C008000000000 +%004000000000000000000000000000020000000000300703181C00800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400080003803039C0C000000000000 +%004000000000000000000000000000020000000000300303181C00000008000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400100003803830C1C000000000000 +%0040000000000000000000000000000200000000003003071C1800000004000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003803830C1C000000008000 +%0040000000000000000000000000000200000800003003060C1800000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFC0000380386061C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040020000380387FE1C000000000000 +%00400000000000000000000000000002000000000030030FFE1800000002000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038030FFF0C000000000000 +%00400000000000000000000000000002000000000030070FFE1C00000004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000C00038030C030C00C000000000 +%00400000000000000000000000000002000000000030061C070C00C00018000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038070C030E01C000000000 +%004000000000000000000000000000020000000000300618030E01C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380E1C038701C000000000 +%004000000000000000000000000000020000000000300E18038703800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400008003FFC180183FF8000000000 +%0040000000000000000000000000000200000000003FFC380387FF000080000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003FF83801C1FE0000000000 +%0040000000000000000000000000000200000000003FF8300181FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000007FFE00000000000000000C100000000000400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800000000003FF +%E00000000000000000C100000000000400 +%000800000000003FFE00000000000000000C300000000000400000004000000000000000000000 +%0040000000000000000000000000000200000000000000000000001000000000800000000003FF +%E00000000000000000C300000000000400 +%0008000000000001C0000000000000000000300000000000400000002000000000000000000000 +%00400000000000000000000000000002000000000000000000000020000000008000000000000C +%0000000000000000000300000000000400 +%0008000000000001C0000000000000000000300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0000000000000000000300000000000400 +%0008000000000001C0670F833C03C19E1C0CFC0000000000400000000800000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0270F811C03C09E1C0CFC0000000000400 +%0008000000000001C07F3FE3FF0FE1FF7F0CFC0000000000400000000400000000000000000000 +%00400000000000000000000000000002000000000000000000000100000000008000000000000C +%07F1FE1FF0FF1FF3F0CFC0000000000400 +%0008000000000001C07A30E3C31C31E3C70C300000000000400000000100000000000000000000 +%00400000000000000000000000000002000000000000000000000400000000008000000000000C +%0783061C38C31E3E30C300000000000400 +%0008000000000001C0707063839831C1830C300000000000400000000080000000000000000000 +%00400000000000000000000000000002000000000000000000000800000000008000000000000C +%0703071819C11C1C38C300000000000400 +%0008000000000001C0700063819C01C1830C300000000000400000000040000000000000000000 +%00400000000000000000000000000002000000000000000000001000000000008000000000000C +%0700071819C01C1818C300000000000400 +%0008000000000001C06003E3818F8181830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%07001F1818F81C1818C300000000000400 +%0008000000000001C0603FE38187F181830C30000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC000000000008000000000000C +%0701FF18187F1C1818C300000000000400 +%0008000000000001C06078638180F181830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0703C718180F9C1818C300000000000400 +%0008000000000001C060606381803981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0707071818019C1818C300000000000400 +%0008000000000001C060606381981981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0706071819819C1818C300000000000400 +%0008000000000001C06060E3819C3981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%07070F1819C39C1818C300000000000400 +%0008000000000001C0607FE3818FF181830C3C0000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0703FF1818FF1C1818C3C0000000000400 +%0008000000000001C0601E338187C181830C1C0000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0701F318183E1C1818C1C0000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800FFE0000000000030004000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFE00000000 +%00030004000000C0000000000000C00400 +%000800FFF000000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF00000000 +%0003000C000000C0000000000000C00400 +%000800E03800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E0380000000 +%0003000C000000C0000000000000C00400 +%000800E01C00000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C0000000 +%0003000C000000C0000000000000C00400 +%000800E00C0F838181EC33C3F07819CCE00F007C1B83CC0040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC00000000000800E00C0F81818 +%1E633C1F0780DCCE00F007C1BC3CC00400 +%000800E00C3FE38187FC3FE3F1FE1FCFF83FC1FE1F8FFC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E1FE1818 +%7FE3FE1F1FE0FCFF83FC1FE1FC7FC00400 +%000800E00E30E3818E1C3870C3871E0E1870E3871E9C3C00400000000040000000000000000000 +%0040000000000000000000000000000200000000000000000000100000000000800E00E3061818 +%61E3870C3870E0F1C70E3871E0C3C00400 +%000800E00E7063818C0C3030C3031C0E1CE063031C181C00400000000080000000000000000000 +%0040000000000000000000000000000200000000000000000000080000000000800E00E3071818 +%C0E3030C3030C0E0C6063031C1C1C00400 +%000800E00E0063819C0C3030C6031C0C0CC0700318181C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E0071818 +%C0E3030C3038C0C0CC0300318181C00400 +%000800E00E03E381980C3030C7FF9C0C0CC0303F18381C00400000000400000000000000000000 +%0040000000000000000000000000000200000000000000000000010000000000800E00E03F1819 +%C0E3030C7FF8C0C0EC0301F18180C00400 +%000800E00C3FE381980C3030C7FF9C0C0CC031FF18381C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E1FF1819 +%C0E3030C7FF8C0C0EC031FF18180C00400 +%000800E00C786383980C3030C6001C0C0CC033C318381C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00C3871819 +%C0E3030C7000C0C0EC033C318180C00400 +%000800E01C6063839C0C3030C7001C0C0CC0770318181C00400000002000000000000000000000 +%0040000000000000000000000000000200000000000000000000002000000000800E00C7071818 +%C0E3030C7000C0C0CC0330318180C00400 +%000800E0186063838C0C3030C3031C0C1CE0670718181C00400000004000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C6071838 +%C0E3030C3038C0E0C606303181C1C00400 +%000800E07870E1878E1C3030C3871C0E1870E70F180C3C00400000008000000000000000000000 +%0040000000000000000000000000000200000000000000000000000800000000800E07870F1C78 +%E1E3030C3870C0E1C70E307180C3C00400 +%000800FFF03FF1FD87FC3030F1FE1C0FF03FC3FF180FFC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF03FF0FD8 +%7FE3030F1FE0C0FF83FC3FF1807FC00400 +%000800FFC01E307981EC303070781C0DE01F01F39803CC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFC01F30798 +%1EE3030787C0C0CE00F00F19803CC00400 +%0008000000000000000C0000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%00C0000000000000000000000000000400 +%00080000000000000C0C0000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%C0C0000000000000000000000000000400 +%00080000000000000E380000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%F3C0000000000000000000000000000400 +%000800000000000007F00000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%7F80000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001003FF00060007C0000000000 +%0040000000000000000000000000000200000000003FE000E000FC000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002003FFC00F001FF0000000000 +%0040000000000000000000000000000200000000003FF800E003FE000200000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000381E00F003838000000000 +%004000000000000000000000000000020000000000301C01F00787800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000800380601F80701C000000000 +%004000000000000000000000000000020000000000300E01B00E03800080000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380701980E00C000000000 +%004000000000000000000000000000020000000000300603B00C01C00040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000380301980C000000000000 +%004000000000000000000000000000020000000000300703181C00000010000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400080003803031C0C000000000000 +%004000000000000000000000000000020000000000300303181800000008000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400100003803830C1C000000000000 +%0040000000000000000000000000000200000000003003071C1800000004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFA00003803870E1C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000003FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFC0000380386061C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040020000380307FE0C000000000000 +%00400000000000000000000000000002000000000030030FFE1800000002000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004001000038030FFF0C00C000000000 +%00400000000000000000000000000002000000000030070FFE1C00800004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000C00038030C030C00C000000000 +%00400000000000000000000000000002000000000030061C070C01C00018000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038070C038601C000000000 +%004000000000000000000000000000020000000000300E18030E01800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380E1C0387038000000000 +%004000000000000000000000000000020000000000301E18038703800040000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400008003FFC180183FF8000000000 +%0040000000000000000000000000000200000000003FFC380387FF000080000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003FF83801C1FE0000000000 +%0040000000000000000000000000000200000000003FF0300181FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000007FFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%007FFFFFFFFFFFFFFFFFFFFFFFFFFFFE0000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0.996 c 7835 7938 m 8893 6985 l 11010 6985 l 11010 8890 l 8893 8890 l +7835 7938 l p ef +0 lw 1 lj 0.000 c 7835 7938 m 8893 6985 l 11010 6985 l 11010 8890 l 8893 8890 l +7835 7938 l pc +gs +pum +8520 8228 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +13955 5080 m 11733 5080 l 11733 1270 l 16178 1270 l 16178 5080 l 13955 5080 l +pc +gs +pum +13176 2513 t +69 0 m 69 -605 l 477 -605 l 477 -534 l 149 -534 l 149 -346 l 433 -346 l +433 -275 l 149 -275 l 149 0 l p ef +532 0 m 766 -315 l 560 -605 l 655 -605 l 765 -450 l 788 -418 804 -393 814 -375 ct +827 -397 843 -420 862 -444 ct 984 -605 l 1071 -605 l 858 -320 l 1087 0 l +988 0 l 836 -216 l 827 -228 818 -241 809 -256 ct 796 -234 786 -219 780 -211 ct +628 0 l p ef +1510 -71 m 1510 0 l 1110 0 l 1110 -17 1112 -35 1119 -51 ct 1129 -78 1145 -105 1168 -132 ct +1190 -158 1223 -189 1265 -223 ct 1331 -277 1375 -320 1398 -352 ct 1422 -383 1433 -413 1433 -441 ct +1433 -471 1423 -495 1402 -516 ct 1380 -536 1353 -546 1319 -546 ct 1283 -546 1255 -535 1233 -514 ct +1212 -492 1201 -463 1201 -425 ct 1124 -432 l 1129 -489 1149 -533 1183 -563 ct +1217 -593 1263 -608 1321 -608 ct 1379 -608 1425 -591 1459 -559 ct 1493 -527 1510 -487 1510 -439 ct +1510 -415 1505 -391 1495 -368 ct 1485 -345 1468 -320 1445 -294 ct 1422 -268 1384 -233 1331 -187 ct +1286 -150 1257 -125 1245 -111 ct 1232 -98 1222 -84 1213 -71 ct p ef +pom +pum +12713 3466 t +462 -605 m 542 -605 l 542 -255 l 542 -194 535 -146 522 -110 ct 508 -74 483 -45 447 -23 ct +411 0 364 10 306 10 ct 249 10 202 0 166 -19 ct 130 -38 105 -66 89 -103 ct 74 -140 66 -191 66 -255 ct +66 -605 l 146 -605 l 146 -256 l 146 -203 151 -164 161 -139 ct 171 -114 187 -95 211 -82 ct +235 -68 264 -61 299 -61 ct 358 -61 400 -75 425 -102 ct 450 -128 462 -180 462 -256 ct +p ef +673 -194 m 748 -201 l 752 -170 760 -146 773 -126 ct 786 -107 806 -91 834 -79 ct +862 -67 893 -61 927 -61 ct 958 -61 985 -66 1008 -75 ct 1031 -84 1049 -96 1060 -112 ct +1072 -128 1077 -145 1077 -164 ct 1077 -183 1072 -200 1061 -214 ct 1050 -228 1032 -240 1006 -249 ct +990 -256 954 -266 898 -279 ct 843 -292 804 -305 782 -317 ct 753 -332 731 -351 717 -373 ct +703 -396 696 -421 696 -449 ct 696 -479 704 -508 722 -534 ct 739 -561 764 -581 798 -595 ct +831 -609 868 -615 909 -615 ct 954 -615 993 -608 1028 -594 ct 1062 -579 1088 -558 1107 -530 ct +1125 -502 1135 -470 1136 -434 ct 1060 -429 l 1055 -467 1041 -496 1018 -515 ct +994 -535 959 -545 912 -545 ct 864 -545 828 -536 806 -518 ct 784 -500 773 -479 773 -454 ct +773 -432 781 -414 796 -400 ct 812 -386 852 -372 917 -357 ct 982 -342 1027 -329 1051 -318 ct +1087 -302 1113 -282 1129 -257 ct 1146 -232 1155 -203 1155 -171 ct 1155 -138 1145 -108 1127 -79 ct +1108 -51 1082 -29 1047 -13 ct 1013 2 974 10 931 10 ct 876 10 830 2 793 -13 ct 756 -29 727 -53 706 -85 ct +685 -117 l 674 -154 l p ef +1278 0 m 1278 -605 l 1506 -605 l 1552 -605 1589 -599 1617 -587 ct 1645 -574 1667 -556 1683 -530 ct +1699 -505 1706 -478 1706 -450 ct 1706 -424 1699 -400 1685 -377 ct 1671 -354 1650 -336 1622 -322 ct +1658 -311 1687 -293 1706 -267 ct 1726 -241 1736 -210 1736 -175 ct 1736 -147 1730 -120 1718 -96 ct +1706 -72 1691 -53 1673 -40 ct 1656 -26 1634 -16 1607 -10 ct 1580 -3 1548 0 1509 0 ct +p +1359 -351 m 1490 -351 l 1525 -351 1551 -353 1566 -358 ct 1586 -364 1602 -374 1612 -388 ct +1622 -402 1628 -419 1628 -441 ct 1628 -461 1623 -478 1613 -494 ct 1603 -509 1590 -520 1572 -525 ct +1554 -531 1523 -534 1480 -534 ct 1359 -534 l p +1359 -71 m 1509 -71 l 1535 -71 1553 -72 1564 -74 ct 1582 -77 1598 -83 1610 -90 ct +1623 -98 1633 -109 1641 -124 ct 1649 -139 1653 -156 1653 -175 ct 1653 -198 1647 -217 1635 -234 ct +1624 -251 1608 -262 1587 -269 ct 1567 -276 1537 -279 1499 -279 ct 1359 -279 l +p ef +2436 -71 m 2436 0 l 2036 0 l 2036 -17 2038 -35 2045 -51 ct 2055 -78 2071 -105 2094 -132 ct +2116 -158 2149 -189 2191 -223 ct 2257 -277 2301 -320 2324 -352 ct 2348 -383 2359 -413 2359 -441 ct +2359 -471 2349 -495 2328 -516 ct 2306 -536 2279 -546 2245 -546 ct 2209 -546 2181 -535 2159 -514 ct +2138 -492 2127 -463 2127 -425 ct 2050 -432 l 2055 -489 2075 -533 2109 -563 ct +2143 -593 2189 -608 2247 -608 ct 2305 -608 2351 -591 2385 -559 ct 2419 -527 2436 -487 2436 -439 ct +2436 -415 2431 -391 2421 -368 ct 2411 -345 2394 -320 2371 -294 ct 2348 -268 2310 -233 2257 -187 ct +2212 -150 2183 -125 2171 -111 ct 2158 -98 2148 -84 2139 -71 ct p ef +pom +pum +12091 4419 t +497 -212 m 577 -192 l 560 -126 530 -76 486 -41 ct 443 -6 389 10 326 10 ct +261 10 208 -2 167 -29 ct 126 -56 95 -94 74 -145 ct 52 -195 42 -249 42 -307 ct 42 -370 54 -425 78 -472 ct +102 -519 136 -554 181 -579 ct 225 -603 274 -615 327 -615 ct 388 -615 439 -600 480 -569 ct +522 -538 550 -495 567 -439 ct 488 -420 l 474 -465 453 -497 427 -517 ct 400 -537 366 -547 326 -547 ct +279 -547 240 -536 209 -513 ct 178 -491 156 -461 143 -424 ct 131 -386 124 -347 124 -307 ct +124 -256 132 -211 147 -172 ct 162 -134 185 -105 217 -86 ct 248 -67 283 -58 320 -58 ct +365 -58 403 -71 434 -97 ct 465 -122 l 486 -161 l p ef +663 -219 m 663 -300 685 -360 730 -399 ct 768 -432 814 -448 868 -448 ct 929 -448 978 -428 1016 -389 ct +1054 -349 1074 -295 1074 -225 ct 1074 -169 1065 -124 1048 -92 ct 1031 -59 1007 -34 974 -16 ct +942 0 907 9 868 9 ct 807 9 757 -9 719 -49 ct 682 -88 l 663 -145 l p +739 -219 m 739 -163 751 -121 776 -93 ct 800 -65 831 -51 868 -51 ct 905 -51 936 -65 960 -93 ct +985 -121 997 -164 997 -221 ct 997 -276 985 -317 960 -345 ct 936 -373 905 -387 868 -387 ct +831 -387 800 -373 776 -345 ct 751 -317 l 739 -275 l p ef +1166 0 m 1166 -438 l 1233 -438 l 1233 -376 l 1265 -424 1312 -448 1373 -448 ct +1399 -448 1424 -443 1446 -434 ct 1468 -424 1484 -412 1495 -396 ct 1507 -381 1514 -363 1519 -342 ct +1521 -328 1523 -304 1523 -269 ct 1523 0 l 1448 0 l 1448 -266 l 1448 -297 1446 -319 1440 -334 ct +1434 -349 1424 -361 1409 -370 ct 1394 -379 1377 -384 1357 -384 ct 1325 -384 1298 -374 1275 -354 ct +1252 -333 1241 -295 1241 -239 ct 1241 0 l p ef +1806 -66 m 1816 0 l 1795 3 1777 5 1760 5 ct 1733 5 1712 1 1697 -7 ct 1683 -15 1672 -26 1666 -40 ct +1660 -54 1657 -83 1657 -128 ct 1657 -380 l 1602 -380 l 1602 -438 l 1657 -438 l +1657 -547 l 1731 -591 l 1731 -438 l 1806 -438 l 1806 -380 l 1731 -380 l +1731 -124 l 1731 -103 1732 -89 1735 -83 ct 1737 -77 1742 -72 1748 -68 ct 1753 -65 1762 -63 1773 -63 ct +1781 -63 l 1792 -64 l p ef +1880 0 m 1880 -438 l 1947 -438 l 1947 -372 l 1964 -403 1980 -423 1995 -433 ct +2009 -443 2025 -448 2042 -448 ct 2067 -448 2093 -440 2119 -424 ct 2093 -355 l +2075 -366 2057 -371 2039 -371 ct 2022 -371 2008 -366 1995 -357 ct 1982 -347 1973 -333 1967 -316 ct +1959 -289 1955 -261 1955 -229 ct 1955 0 l p ef +2145 -219 m 2145 -300 2167 -360 2212 -399 ct 2250 -432 2296 -448 2350 -448 ct +2411 -448 2460 -428 2498 -389 ct 2536 -349 2556 -295 2556 -225 ct 2556 -169 2547 -124 2530 -92 ct +2513 -59 2489 -34 2456 -16 ct 2424 0 2389 9 2350 9 ct 2289 9 2239 -9 2201 -49 ct +2164 -88 l 2145 -145 l p +2221 -219 m 2221 -163 2233 -121 2258 -93 ct 2282 -65 2313 -51 2350 -51 ct 2387 -51 2418 -65 2442 -93 ct +2467 -121 2479 -164 2479 -221 ct 2479 -276 2467 -317 2442 -345 ct 2418 -373 2387 -387 2350 -387 ct +2313 -387 2282 -373 2258 -345 ct 2233 -317 l 2221 -275 l p ef +2647 0 m 2647 -605 l 2721 -605 l 2721 0 l p ef +2832 0 m 2832 -605 l 2906 -605 l 2906 0 l p ef +3319 -141 m 3395 -131 l 3383 -86 3361 -52 3328 -27 ct 3295 -2 3253 9 3203 9 ct +3138 9 3087 -9 3050 -49 ct 3012 -88 2993 -144 2993 -215 ct 2993 -289 3012 -346 3050 -387 ct +3089 -428 3138 -448 3198 -448 ct 3257 -448 3305 -428 3342 -388 ct 3379 -348 3398 -292 3398 -220 ct +3398 -215 3398 -209 3397 -200 ct 3070 -200 l 3073 -152 3087 -115 3111 -89 ct +3136 -64 3166 -51 3203 -51 ct 3230 -51 3253 -58 3273 -72 ct 3292 -87 l 3307 -109 l +p +3074 -261 m 3319 -261 l 3316 -298 3307 -326 3291 -344 ct 3268 -373 3237 -387 3199 -387 ct +3165 -387 3136 -376 3113 -353 ct 3090 -330 l 3077 -299 l p ef +3494 0 m 3494 -438 l 3561 -438 l 3561 -372 l 3578 -403 3594 -423 3609 -433 ct +3623 -443 3639 -448 3656 -448 ct 3681 -448 3707 -440 3733 -424 ct 3707 -355 l +3689 -366 3671 -371 3653 -371 ct 3636 -371 3622 -366 3609 -357 ct 3596 -347 3587 -333 3581 -316 ct +3573 -289 3569 -261 3569 -229 ct 3569 0 l p ef +pom +gr +13956 19115 m 11900 19115 l 11900 6350 l 16013 6350 l 16013 19115 l +13956 19115 l pc +gs +pum +12806 13017 t +69 0 m 69 -605 l 477 -605 l 477 -534 l 149 -534 l 149 -346 l 433 -346 l +433 -275 l 149 -275 l 149 0 l p ef +594 0 m 594 -605 l 822 -605 l 862 -605 893 -603 914 -599 ct 944 -594 969 -585 989 -571 ct +1009 -557 1025 -538 1038 -513 ct 1050 -488 1056 -460 1056 -430 ct 1056 -378 1040 -335 1007 -299 ct +974 -264 915 -246 829 -246 ct 674 -246 l 674 0 l p +674 -317 m 830 -317 l 882 -317 919 -327 941 -346 ct 963 -365 973 -392 973 -427 ct +973 -453 967 -474 954 -493 ct 941 -511 925 -522 904 -528 ct 890 -532 865 -534 829 -534 ct +674 -534 l p ef +1433 -237 m 1433 -308 l 1690 -308 l 1690 -84 l 1650 -52 1610 -29 1568 -13 ct +1526 2 1483 10 1439 10 ct 1379 10 1325 -2 1277 -27 ct 1228 -53 1191 -90 1167 -138 ct +1142 -186 1130 -240 1130 -299 ct 1130 -358 1142 -413 1167 -464 ct 1191 -516 1227 -553 1273 -578 ct +1319 -603 1372 -615 1433 -615 ct 1477 -615 1516 -608 1551 -594 ct 1587 -580 1615 -560 1635 -535 ct +1655 -510 1670 -476 1681 -436 ct 1608 -416 l 1599 -447 1588 -471 1574 -489 ct +1561 -506 1542 -520 1517 -531 ct 1492 -542 1464 -547 1433 -547 ct 1397 -547 1365 -541 1338 -530 ct +1311 -519 1290 -504 1273 -486 ct 1257 -468 1244 -448 1235 -426 ct 1220 -389 1212 -348 1212 -304 ct +1212 -250 1221 -205 1240 -169 ct 1259 -133 1286 -106 1321 -88 ct 1357 -70 1394 -61 1434 -61 ct +1469 -61 1503 -68 1536 -82 ct 1569 -95 1594 -109 1611 -124 ct 1611 -237 l p ef +1745 0 m 1977 -605 l 2063 -605 l 2311 0 l 2220 0 l 2149 -183 l 1896 -183 l +1829 0 l p +1919 -248 m 2124 -248 l 2061 -416 l 2042 -467 2028 -509 2018 -541 ct 2010 -503 2000 -464 1986 -426 ct +p ef +pom +gr +0.996 c 7835 17258 m 8893 16305 l 11010 16305 l 11010 18210 l 8893 18210 l +7835 17258 l p ef +0.000 c 7835 17258 m 8893 16305 l 11010 16305 l 11010 18210 l 8893 18210 l +7835 17258 l pc +gs +pum +8520 17542 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 7835 10478 m 8893 9525 l 11010 9525 l 11010 11430 l 8893 11430 l +7835 10478 l p ef +0.000 c 7835 10478 m 8893 9525 l 11010 9525 l 11010 11430 l 8893 11430 l +7835 10478 l pc +gs +pum +8520 10768 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 7835 14618 m 8893 13665 l 11010 13665 l 11010 15570 l 8893 15570 l +7835 14618 l p ef +0.000 c 7835 14618 m 8893 13665 l 11010 13665 l 11010 15570 l 8893 15570 l +7835 14618 l pc +gs +pum +8520 14896 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 7938 m 18926 6985 l 16809 6985 l 16809 8890 l 18926 8890 l +19984 7938 l p ef +0.000 c 19984 7938 m 18926 6985 l 16809 6985 l 16809 8890 l 18926 8890 l +19984 7938 l pc +gs +pum +17489 8228 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 17258 m 18926 16305 l 16809 16305 l 16809 18210 l 18926 18210 l +19984 17258 l p ef +0.000 c 19984 17258 m 18926 16305 l 16809 16305 l 16809 18210 l 18926 18210 l +19984 17258 l pc +gs +pum +17489 17542 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 10478 m 18926 9525 l 16809 9525 l 16809 11430 l 18926 11430 l +19984 10478 l p ef +0.000 c 19984 10478 m 18926 9525 l 16809 9525 l 16809 11430 l 18926 11430 l +19984 10478 l pc +gs +pum +17489 10768 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 14618 m 18926 13665 l 16809 13665 l 16809 15570 l 18926 15570 l +19984 14618 l p ef +0.000 c 19984 14618 m 18926 13665 l 16809 13665 l 16809 15570 l 18926 15570 l +19984 14618 l pc +gs +pum +17489 14896 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +23767 18828 m 20592 18828 l 20592 13113 l 26942 13113 l 26942 18828 l +23767 18828 l pc +gs +pum +22133 15795 t +219 0 m 219 -534 l 19 -534 l 19 -605 l 499 -605 l 499 -534 l 299 -534 l +299 0 l p ef +583 0 m 583 -438 l 650 -438 l 650 -372 l 667 -403 683 -423 698 -433 ct +712 -443 728 -448 745 -448 ct 770 -448 796 -440 822 -424 ct 796 -355 l 778 -366 760 -371 742 -371 ct +725 -371 711 -366 698 -357 ct 685 -347 676 -333 670 -316 ct 662 -289 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -48 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -252 ct 1083 -259 1127 -268 1155 -278 ct +1156 -288 1156 -295 1156 -297 ct 1156 -328 1149 -349 1135 -361 ct 1116 -378 1087 -387 1050 -387 ct +1015 -387 989 -380 973 -368 ct 956 -356 944 -334 936 -303 ct 863 -313 l 869 -344 880 -369 896 -388 ct +911 -408 933 -422 961 -433 ct 990 -443 1023 -448 1061 -448 ct 1098 -448 1129 -444 1152 -435 ct +1175 -426 1193 -415 1204 -402 ct 1215 -388 1222 -371 1227 -351 ct 1229 -338 1231 -316 1231 -282 ct +1231 -183 l 1231 -114 1232 -70 1235 -52 ct 1238 -34 1245 -16 1254 0 ct 1176 0 l +1169 -15 l 1164 -33 l p +1155 -220 m 1128 -209 1088 -199 1034 -192 ct 1003 -187 982 -182 969 -177 ct +956 -171 947 -163 940 -153 ct 933 -142 929 -130 929 -117 ct 929 -97 937 -81 952 -68 ct +967 -54 989 -48 1018 -48 ct 1046 -48 1072 -54 1094 -67 ct 1117 -79 1133 -96 1143 -118 ct +1151 -135 1155 -160 1155 -192 ct p ef +1325 0 m 1325 -438 l 1392 -438 l 1392 -376 l 1424 -424 1471 -448 1532 -448 ct +1558 -448 1583 -443 1605 -434 ct 1627 -424 1643 -412 1654 -396 ct 1666 -381 1673 -363 1678 -342 ct +1680 -328 1682 -304 1682 -269 ct 1682 0 l 1607 0 l 1607 -266 l 1607 -297 1605 -319 1599 -334 ct +1593 -349 1583 -361 1568 -370 ct 1553 -379 1536 -384 1516 -384 ct 1484 -384 1457 -374 1434 -354 ct +1411 -333 1400 -295 1400 -239 ct 1400 0 l p ef +1772 -130 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1898 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2051 -85 2059 -102 2059 -121 ct 2059 -137 2052 -151 2038 -160 ct +2027 -167 2002 -175 1962 -185 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -300 1784 -322 ct 1784 -341 1788 -359 1797 -376 ct 1806 -393 1818 -407 1834 -418 ct +1845 -426 1861 -433 1881 -439 ct 1901 -445 1923 -448 1945 -448 ct 1980 -448 2010 -443 2036 -433 ct +2062 -423 2081 -410 2094 -393 ct 2106 -376 2115 -353 2119 -325 ct 2047 -315 l +2043 -338 2034 -355 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -381 1878 -370 ct +1863 -359 1856 -346 1856 -330 ct 1856 -321 1859 -312 1865 -304 ct 1871 -296 1880 -290 1893 -285 ct +1901 -282 1923 -275 1959 -266 ct 2012 -251 2048 -240 2069 -231 ct 2090 -222 2106 -209 2118 -192 ct +2130 -175 2136 -154 2136 -128 ct 2136 -104 2129 -80 2114 -58 ct 2100 -36 2079 -20 2052 -8 ct +2024 3 1993 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -438 l 2265 -438 l 2265 -377 l 2279 -398 2297 -415 2320 -428 ct +2343 -442 2369 -448 2398 -448 ct 2430 -448 2457 -441 2478 -428 ct 2499 -414 2513 -396 2522 -371 ct +2556 -423 2602 -448 2657 -448 ct 2701 -448 2734 -436 2758 -412 ct 2781 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2716 -327 2712 -340 ct 2707 -353 2698 -364 2685 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2584 -373 2564 -353 ct 2543 -332 2533 -300 2533 -254 ct +2533 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -342 2441 -359 ct 2429 -375 2409 -384 2381 -384 ct +2360 -384 2341 -378 2323 -367 ct 2305 -356 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -605 l 2988 -605 l 2988 -520 l p +2914 0 m 2914 -438 l 2988 -438 l 2988 0 l p ef +3261 -66 m 3271 0 l 3250 3 3232 5 3215 5 ct 3188 5 3167 1 3152 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -380 l 3057 -380 l 3057 -438 l 3112 -438 l +3112 -547 l 3186 -591 l 3186 -438 l 3261 -438 l 3261 -380 l 3186 -380 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3192 -77 3197 -72 3203 -68 ct 3208 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +pom +pum +20955 16748 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +23767 12065 m 20592 12065 l 20592 6350 l 26942 6350 l 26942 12065 l +23767 12065 l pc +gs +pum +22239 9022 t +66 0 m 66 -605 l 335 -605 l 389 -605 430 -600 458 -589 ct 486 -578 508 -559 525 -531 ct +542 -504 550 -473 550 -440 ct 550 -397 536 -361 508 -331 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 451 -223 473 -197 494 -164 ct 600 0 l 499 0 l +419 -125 l 395 -162 376 -190 361 -209 ct 346 -228 332 -242 320 -249 ct 308 -257 296 -263 284 -266 ct +275 -267 260 -268 239 -268 ct 146 -268 l 146 0 l p +146 -338 m 318 -338 l 355 -338 384 -342 404 -349 ct 425 -357 441 -369 451 -386 ct +462 -402 468 -420 468 -440 ct 468 -468 457 -492 436 -510 ct 416 -529 383 -538 338 -538 ct +146 -538 l p ef +965 -141 m 1041 -131 l 1029 -86 1007 -52 974 -27 ct 941 -2 899 9 849 9 ct +784 9 733 -9 696 -49 ct 658 -88 639 -144 639 -215 ct 639 -289 658 -346 696 -387 ct +735 -428 784 -448 844 -448 ct 903 -448 951 -428 988 -388 ct 1025 -348 1044 -292 1044 -220 ct +1044 -215 1044 -209 1043 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 812 -51 849 -51 ct +876 -51 899 -58 919 -72 ct 938 -87 l 953 -109 l p +720 -261 m 965 -261 l 962 -298 953 -326 937 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 782 -376 759 -353 ct 736 -330 l 723 -299 l p ef +1427 -160 m 1500 -151 l 1492 -100 1471 -61 1438 -32 ct 1405 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -48 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -377 1181 -404 1213 -421 ct 1245 -439 1280 -448 1317 -448 ct 1365 -448 1404 -436 1434 -412 ct +1465 -388 1484 -354 1493 -309 ct 1420 -298 l 1413 -328 1401 -350 1384 -365 ct +1366 -380 1345 -387 1320 -387 ct 1283 -387 1252 -374 1229 -347 ct 1206 -320 1194 -277 1194 -219 ct +1194 -160 1205 -118 1228 -91 ct 1250 -64 1280 -51 1316 -51 ct 1345 -51 1370 -60 1389 -78 ct +1409 -95 l 1421 -123 l p ef +1864 -141 m 1940 -131 l 1928 -86 1906 -52 1873 -27 ct 1840 -2 1798 9 1748 9 ct +1683 9 1632 -9 1595 -49 ct 1557 -88 1538 -144 1538 -215 ct 1538 -289 1557 -346 1595 -387 ct +1634 -428 1683 -448 1743 -448 ct 1802 -448 1850 -428 1887 -388 ct 1924 -348 1943 -292 1943 -220 ct +1943 -215 1943 -209 1942 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1711 -51 1748 -51 ct 1775 -51 1798 -58 1818 -72 ct 1837 -87 l 1852 -109 l +p +1619 -261 m 1864 -261 l 1861 -298 1852 -326 1836 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1681 -376 1658 -353 ct 1635 -330 l 1622 -299 l p ef +2040 -520 m 2040 -605 l 2114 -605 l 2114 -520 l p +2040 0 m 2040 -438 l 2114 -438 l 2114 0 l p ef +2347 0 m 2180 -438 l 2259 -438 l 2353 -175 l 2363 -147 2372 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2506 -438 l 2583 -438 l 2417 0 l p ef +2949 -141 m 3025 -131 l 3013 -86 2991 -52 2958 -27 ct 2925 -2 2883 9 2833 9 ct +2768 9 2717 -9 2680 -49 ct 2642 -88 2623 -144 2623 -215 ct 2623 -289 2642 -346 2680 -387 ct +2719 -428 2768 -448 2828 -448 ct 2887 -448 2935 -428 2972 -388 ct 3009 -348 3028 -292 3028 -220 ct +3028 -215 3028 -209 3027 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2796 -51 2833 -51 ct 2860 -51 2883 -58 2903 -72 ct 2922 -87 l 2937 -109 l +p +2704 -261 m 2949 -261 l 2946 -298 2937 -326 2921 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2766 -376 2743 -353 ct 2720 -330 l 2707 -299 l p ef +pom +pum +20955 9975 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +4245 18828 m 1070 18828 l 1070 13113 l 7420 13113 l 7420 18828 l 4245 18828 l +pc +gs +pum +2607 15795 t +219 0 m 219 -534 l 19 -534 l 19 -605 l 499 -605 l 499 -534 l 299 -534 l +299 0 l p ef +583 0 m 583 -438 l 650 -438 l 650 -372 l 667 -403 683 -423 698 -433 ct +712 -443 728 -448 745 -448 ct 770 -448 796 -440 822 -424 ct 796 -355 l 778 -366 760 -371 742 -371 ct +725 -371 711 -366 698 -357 ct 685 -347 676 -333 670 -316 ct 662 -289 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -48 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -252 ct 1083 -259 1127 -268 1155 -278 ct +1156 -288 1156 -295 1156 -297 ct 1156 -328 1149 -349 1135 -361 ct 1116 -378 1087 -387 1050 -387 ct +1015 -387 989 -380 973 -368 ct 956 -356 944 -334 936 -303 ct 863 -313 l 869 -344 880 -369 896 -388 ct +911 -408 933 -422 961 -433 ct 990 -443 1023 -448 1061 -448 ct 1098 -448 1129 -444 1152 -435 ct +1175 -426 1193 -415 1204 -402 ct 1215 -388 1222 -371 1227 -351 ct 1229 -338 1231 -316 1231 -282 ct +1231 -183 l 1231 -114 1232 -70 1235 -52 ct 1238 -34 1245 -16 1254 0 ct 1176 0 l +1169 -15 l 1164 -33 l p +1155 -220 m 1128 -209 1088 -199 1034 -192 ct 1003 -187 982 -182 969 -177 ct +956 -171 947 -163 940 -153 ct 933 -142 929 -130 929 -117 ct 929 -97 937 -81 952 -68 ct +967 -54 989 -48 1018 -48 ct 1046 -48 1072 -54 1094 -67 ct 1117 -79 1133 -96 1143 -118 ct +1151 -135 1155 -160 1155 -192 ct p ef +1325 0 m 1325 -438 l 1392 -438 l 1392 -376 l 1424 -424 1471 -448 1532 -448 ct +1558 -448 1583 -443 1605 -434 ct 1627 -424 1643 -412 1654 -396 ct 1666 -381 1673 -363 1678 -342 ct +1680 -328 1682 -304 1682 -269 ct 1682 0 l 1607 0 l 1607 -266 l 1607 -297 1605 -319 1599 -334 ct +1593 -349 1583 -361 1568 -370 ct 1553 -379 1536 -384 1516 -384 ct 1484 -384 1457 -374 1434 -354 ct +1411 -333 1400 -295 1400 -239 ct 1400 0 l p ef +1772 -130 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1898 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2051 -85 2059 -102 2059 -121 ct 2059 -137 2052 -151 2038 -160 ct +2027 -167 2002 -175 1962 -185 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -300 1784 -322 ct 1784 -341 1788 -359 1797 -376 ct 1806 -393 1818 -407 1834 -418 ct +1845 -426 1861 -433 1881 -439 ct 1901 -445 1923 -448 1945 -448 ct 1980 -448 2010 -443 2036 -433 ct +2062 -423 2081 -410 2094 -393 ct 2106 -376 2115 -353 2119 -325 ct 2047 -315 l +2043 -338 2034 -355 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -381 1878 -370 ct +1863 -359 1856 -346 1856 -330 ct 1856 -321 1859 -312 1865 -304 ct 1871 -296 1880 -290 1893 -285 ct +1901 -282 1923 -275 1959 -266 ct 2012 -251 2048 -240 2069 -231 ct 2090 -222 2106 -209 2118 -192 ct +2130 -175 2136 -154 2136 -128 ct 2136 -104 2129 -80 2114 -58 ct 2100 -36 2079 -20 2052 -8 ct +2024 3 1993 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -438 l 2265 -438 l 2265 -377 l 2279 -398 2297 -415 2320 -428 ct +2343 -442 2369 -448 2398 -448 ct 2430 -448 2457 -441 2478 -428 ct 2499 -414 2513 -396 2522 -371 ct +2556 -423 2602 -448 2657 -448 ct 2701 -448 2734 -436 2758 -412 ct 2781 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2716 -327 2712 -340 ct 2707 -353 2698 -364 2685 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2584 -373 2564 -353 ct 2543 -332 2533 -300 2533 -254 ct +2533 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -342 2441 -359 ct 2429 -375 2409 -384 2381 -384 ct +2360 -384 2341 -378 2323 -367 ct 2305 -356 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -605 l 2988 -605 l 2988 -520 l p +2914 0 m 2914 -438 l 2988 -438 l 2988 0 l p ef +3261 -66 m 3271 0 l 3250 3 3232 5 3215 5 ct 3188 5 3167 1 3152 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -380 l 3057 -380 l 3057 -438 l 3112 -438 l +3112 -547 l 3186 -591 l 3186 -438 l 3261 -438 l 3261 -380 l 3186 -380 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3192 -77 3197 -72 3203 -68 ct 3208 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +pom +pum +1429 16748 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +4245 12065 m 1070 12065 l 1070 6350 l 7420 6350 l 7420 12065 l 4245 12065 l +pc +gs +pum +2713 9022 t +66 0 m 66 -605 l 335 -605 l 389 -605 430 -600 458 -589 ct 486 -578 508 -559 525 -531 ct +542 -504 550 -473 550 -440 ct 550 -397 536 -361 508 -331 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 451 -223 473 -197 494 -164 ct 600 0 l 499 0 l +419 -125 l 395 -162 376 -190 361 -209 ct 346 -228 332 -242 320 -249 ct 308 -257 296 -263 284 -266 ct +275 -267 260 -268 239 -268 ct 146 -268 l 146 0 l p +146 -338 m 318 -338 l 355 -338 384 -342 404 -349 ct 425 -357 441 -369 451 -386 ct +462 -402 468 -420 468 -440 ct 468 -468 457 -492 436 -510 ct 416 -529 383 -538 338 -538 ct +146 -538 l p ef +965 -141 m 1041 -131 l 1029 -86 1007 -52 974 -27 ct 941 -2 899 9 849 9 ct +784 9 733 -9 696 -49 ct 658 -88 639 -144 639 -215 ct 639 -289 658 -346 696 -387 ct +735 -428 784 -448 844 -448 ct 903 -448 951 -428 988 -388 ct 1025 -348 1044 -292 1044 -220 ct +1044 -215 1044 -209 1043 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 812 -51 849 -51 ct +876 -51 899 -58 919 -72 ct 938 -87 l 953 -109 l p +720 -261 m 965 -261 l 962 -298 953 -326 937 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 782 -376 759 -353 ct 736 -330 l 723 -299 l p ef +1427 -160 m 1500 -151 l 1492 -100 1471 -61 1438 -32 ct 1405 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -48 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -377 1181 -404 1213 -421 ct 1245 -439 1280 -448 1317 -448 ct 1365 -448 1404 -436 1434 -412 ct +1465 -388 1484 -354 1493 -309 ct 1420 -298 l 1413 -328 1401 -350 1384 -365 ct +1366 -380 1345 -387 1320 -387 ct 1283 -387 1252 -374 1229 -347 ct 1206 -320 1194 -277 1194 -219 ct +1194 -160 1205 -118 1228 -91 ct 1250 -64 1280 -51 1316 -51 ct 1345 -51 1370 -60 1389 -78 ct +1409 -95 l 1421 -123 l p ef +1864 -141 m 1940 -131 l 1928 -86 1906 -52 1873 -27 ct 1840 -2 1798 9 1748 9 ct +1683 9 1632 -9 1595 -49 ct 1557 -88 1538 -144 1538 -215 ct 1538 -289 1557 -346 1595 -387 ct +1634 -428 1683 -448 1743 -448 ct 1802 -448 1850 -428 1887 -388 ct 1924 -348 1943 -292 1943 -220 ct +1943 -215 1943 -209 1942 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1711 -51 1748 -51 ct 1775 -51 1798 -58 1818 -72 ct 1837 -87 l 1852 -109 l +p +1619 -261 m 1864 -261 l 1861 -298 1852 -326 1836 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1681 -376 1658 -353 ct 1635 -330 l 1622 -299 l p ef +2040 -520 m 2040 -605 l 2114 -605 l 2114 -520 l p +2040 0 m 2040 -438 l 2114 -438 l 2114 0 l p ef +2347 0 m 2180 -438 l 2259 -438 l 2353 -175 l 2363 -147 2372 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2506 -438 l 2583 -438 l 2417 0 l p ef +2949 -141 m 3025 -131 l 3013 -86 2991 -52 2958 -27 ct 2925 -2 2883 9 2833 9 ct +2768 9 2717 -9 2680 -49 ct 2642 -88 2623 -144 2623 -215 ct 2623 -289 2642 -346 2680 -387 ct +2719 -428 2768 -448 2828 -448 ct 2887 -448 2935 -428 2972 -388 ct 3009 -348 3028 -292 3028 -220 ct +3028 -215 3028 -209 3027 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2796 -51 2833 -51 ct 2860 -51 2883 -58 2903 -72 ct 2922 -87 l 2937 -109 l +p +2704 -261 m 2949 -261 l 2946 -298 2937 -326 2921 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2766 -376 2743 -353 ct 2720 -330 l 2707 -299 l p ef +pom +pum +1429 9975 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +51 lw 13970 5080 m 13970 6350 l ps +11010 7920 m 11900 7920 l ps +11010 10460 m 11900 10460 l ps +11010 14605 m 11900 14605 l ps +11010 17245 m 11900 17245 l ps +7835 7955 m 7420 7955 l ps +7835 10460 m 7420 10460 l ps +7835 14605 m 7420 14605 l ps +7835 17245 m 7420 17245 l ps +16013 7955 m 16809 7955 l ps +19984 7920 m 20592 7920 l ps +19984 10460 m 20592 10460 l ps +16013 10495 m 16809 10495 l ps +16013 14605 m 16809 14605 l ps +16013 17245 m 16809 17245 l ps +19984 14605 m 20592 14605 l ps +19984 17245 m 20592 17245 l ps +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/docs/exploring-gnuradio/usrp-block-diagram.png b/docs/exploring-gnuradio/usrp-block-diagram.png new file mode 100644 index 00000000..55a0f0b3 Binary files /dev/null and b/docs/exploring-gnuradio/usrp-block-diagram.png differ diff --git a/docs/howto-write-a-block/README b/docs/howto-write-a-block/README new file mode 100644 index 00000000..73b8e602 --- /dev/null +++ b/docs/howto-write-a-block/README @@ -0,0 +1,3 @@ +If you're looking for howto-write-a-block, it was moved into it's own +tarball: gr-howto-write-a-block. It includes the document source +and a full build tree, Makefiles, examples, etc. diff --git a/dtools/COPYING b/dtools/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/dtools/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/dtools/README b/dtools/README new file mode 100644 index 00000000..e0c76588 --- /dev/null +++ b/dtools/README @@ -0,0 +1,25 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This is a collection of tools that are useful for building tarball +distributions of GNU Radio. They're probably not of general interest. + +To use, add dtools/bin to PATH and dtools/python to PYTHONPATH diff --git a/dtools/bin/check-config-files b/dtools/bin/check-config-files new file mode 100755 index 00000000..7111c951 --- /dev/null +++ b/dtools/bin/check-config-files @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# usage: takes list of directories on command line + +import sys +import os +import os.path +from itertools import ifilter, ifilterfalse, imap, izip +import md5 +from pprint import pprint +from sets import Set + +class info(object): + def __init__(self, dir, name, md5sum): + self.dir = dir + self.name = name + self.md5sum = md5sum + def __repr__(self): + return '<%r, %r, %r>' % (self.dir, self.name, self.md5sum) + + +def md5sum_file(filename): + f = open(filename, 'r') + m = md5.new(f.read()) + return m.hexdigest() + +def process_dir(dir): + files = list(ifilterfalse(lambda s: s.endswith('~'), + _filter(os.listdir(dir), ('CVS','Makefile', 'Makefile.in', '.svn')))) + return [info(dir, f, md5sum_file(os.path.join(dir, f))) for f in files] + + +# Return a copy with items that occur in skip removed. +# +def _filter(flist, skip): + return list(ifilterfalse(skip.__contains__, flist)) + +def main(): + dirs = sys.argv[1:] + r = [] + for d in dirs: + r += process_dir(d) + + names = Set([x.name for x in r]) + #pprint(names) + + # check for missing files across the union of names + for d in dirs: + names_in_dir = Set([x.name for x in r if x.dir == d]) + diff = names.difference(names_in_dir) + if len(diff) != 0: + print "%s is missing %r" % (d, diff) + + # check for different versions of files + name_list = [n for n in names] + name_list.sort() + + for name in name_list: + vers = {} + pairs = [(x.dir, x.md5sum) for x in r if x.name == name] + for (dir, sum) in pairs: + if vers.has_key(sum): + vers[sum].append(dir) + else: + vers[sum] = [ dir ] + if len(vers) != 1: # multiple versions + print "Multiple versions of %s:" % (name,) + pprint(vers) + + # pprint(r) + +if __name__ == '__main__': + main() diff --git a/dtools/bin/check-imports b/dtools/bin/check-imports new file mode 100755 index 00000000..75ca547d --- /dev/null +++ b/dtools/bin/check-imports @@ -0,0 +1,4 @@ +#!/bin/bash + +find . -name '*.py' | xargs grep -h -E '^(from|import)' | sort -u + diff --git a/dtools/bin/check-tarball-h-files b/dtools/bin/check-tarball-h-files new file mode 100755 index 00000000..f94832c2 --- /dev/null +++ b/dtools/bin/check-tarball-h-files @@ -0,0 +1,23 @@ +#!/bin/bash + +tarball=$1 +if [ "x$tarball" == "x" ] +then + echo "usage: $0 tarball" 1>&2 + exit 1 +fi + +path=${tarball%%.tar.gz} + +tar tzf $tarball \ + | grep -E '\.(h|py|v)$' \ + | sed -e "s/$path/./" \ + | sort >/tmp/tarball-h-files + +find . \( -name '*.h' -o -name '*.py' \) -print | grep -v ./$path | sort >/tmp/build-h-files + +comm -23 /tmp/build-h-files /tmp/tarball-h-files + +# rm /tmp/tarball-h-files /tmp/build-h-files + + diff --git a/dtools/bin/get-config-files b/dtools/bin/get-config-files new file mode 100755 index 00000000..9bdffc12 --- /dev/null +++ b/dtools/bin/get-config-files @@ -0,0 +1,6 @@ +#!/bin/bash + +# fetch latest config.guess and config.sub + +wget http://savannah.gnu.org/cgi-bin/viewcvs/config/config/config.guess?rev=HEAD&content-type=text/plain +wget http://savannah.gnu.org/cgi-bin/viewcvs/config/config/config.sub?rev=HEAD&content-type=text/plain diff --git a/dtools/bin/incr_release b/dtools/bin/incr_release new file mode 100755 index 00000000..167192e2 --- /dev/null +++ b/dtools/bin/incr_release @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from optparse import OptionParser +import release_tools +import os.path + +def main(): + parser = OptionParser() + parser.add_option('-f', '--final', action='store_true', default=False) + (options, args) = parser.parse_args() + + for f in args: + release_tools.incr_release(os.path.join(f, 'configure.ac'), options.final) + +if __name__ == '__main__': + main() + diff --git a/dtools/bin/make-upload b/dtools/bin/make-upload new file mode 100755 index 00000000..73a0feb6 --- /dev/null +++ b/dtools/bin/make-upload @@ -0,0 +1,12 @@ +#!/bin/bash + +read -s -p "GPG Passphrase: " passphrase + +for file in "$@" +do + echo "directory: gnuradio" > $file.directive + echo "$passphrase" | gpg --passphrase-fd 0 --clearsign $file.directive + rm $file.directive + echo "$passphrase" | gpg --passphrase-fd 0 -b $file +done +passphrase="XYZabcdefhghakdsj;lasjdf;ajfdiuiwjr;lajv;laoisfuaoieurlkajdsflkajsdfoiuew" diff --git a/dtools/bin/show_release b/dtools/bin/show_release new file mode 100755 index 00000000..a4eff605 --- /dev/null +++ b/dtools/bin/show_release @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from optparse import OptionParser +import release_tools +import os.path + +def main(): + parser = OptionParser() + (options, args) = parser.parse_args() + + for f in args: + print release_tools.get_release(os.path.join(f, 'configure.ac')) + +if __name__ == '__main__': + main() + diff --git a/dtools/bin/tag_release b/dtools/bin/tag_release new file mode 100755 index 00000000..883b94b4 --- /dev/null +++ b/dtools/bin/tag_release @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from optparse import OptionParser +import release_tools +import os +import os.path +import sys + +def main(): + parser = OptionParser() + (options, args) = parser.parse_args() + + exit_code = 0 + for d in args: + f = os.path.join(d, 'configure.ac') + rel = release_tools.get_release(f) + if rel is None: + raise ValueError, "%s: couldn't find version" % (f,) + tag = release_tools.make_tag(rel) + cmd = '(cd %s; cvs tag %s)' % (d, tag) + print cmd + exit_code = exit_code | os.system(cmd) + + sys.exit(exit_code) + +if __name__ == '__main__': + main() diff --git a/dtools/python/release_tools.py b/dtools/python/release_tools.py new file mode 100644 index 00000000..788ede55 --- /dev/null +++ b/dtools/python/release_tools.py @@ -0,0 +1,87 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +import os + +def get_release(configure_ac_filename): + f = open(configure_ac_filename,'r') + contents = f.read() + pat = re.compile('^AM_INIT_AUTOMAKE\((.*),(\d+)\.(\d+)(.*)\)', re.M) + mo = pat.search(contents) + if mo: + return mo.groups() + +def set_release(configure_ac_filename, new_release): + f = open(configure_ac_filename,'r') + contents = f.read() + pat = re.compile('^AM_INIT_AUTOMAKE\(((.*),(\d+)\.(\d+)(.*))\)', re.M) + repl = ''.join(('AM_INIT_AUTOMAKE(', + new_release[0], + ',', + new_release[1], + '.', + new_release[2],new_release[3],')')) + new = pat.sub(repl, contents) + return new + +def incr_release(configure_ac_filename, final=False): + cur = get_release(configure_ac_filename) + if cur is None: + raise ValueError, "%s: couldn't find version" % (configure_ac_filename,) + new = set_release(configure_ac_filename, up_rev(cur, final)) + os.rename(configure_ac_filename, configure_ac_filename + '.bak') + f = open(configure_ac_filename,'w') + f.write(new) + f.close() + +def up_rev(current_rev, final=False): + """ + X.Y -> X.Ycvs + if final: + X.Ycvs -> X.(Y+1)rc1 + else: + X.Ycvs -> X.(Y+1) + if final: + X.YrcN -> X.Y + else + X.YrcN -> X.Yrc(N+1) + """ + pkg, major, minor, suffix = current_rev + + if len(suffix) == 0: + if final: + raise RuntimeError, ("Can't go from current to final. current = " + str(current_rev)) + return (pkg, major, minor, "cvs") + if suffix == "cvs": + if final: + return (pkg, major, str(int(minor)+1), "") + return (pkg, major, str(int(minor)+1), "rc1") + elif suffix.startswith('rc'): + if final: + return (pkg, major, minor, "") + return (pkg, major, minor, "rc" + (str(int(suffix[2:]) + 1))) + +def make_tag(current_rev): + pkg, major, minor, suffix = current_rev + if suffix == "cvs": + raise ValueError, "You tried to tag a X.Ycvs release..." + return 'REL_%s_%s%s' % (major, minor, suffix) diff --git a/gnuradio-core/ChangeLog b/gnuradio-core/ChangeLog new file mode 100644 index 00000000..776ab8ca --- /dev/null +++ b/gnuradio-core/ChangeLog @@ -0,0 +1,1893 @@ +2006-07-06 Tom Rondeau + + * src/python/gnuradio/blksimpl/gmsk2.py: + Added AGC to GMSK code. + +2006-07-06 Tom Rondeau + + * src/python/gnuradio/blksimpl/Makefile.am: + Call to gmsk.py was causing error after removal of gmsk.py file. + Removed call in Makefile.am to this. + +2006-07-05 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk.py: Removed long deprecated + code. We'll give this a week or so for the dust to settle, then + we'll rename gmsk2.py to gmsk.py + +2006-06-29 Tom Rondeau + + * src/lib/general/gr_correlate_access_code_bb.cc (work): + Removed branches; cleaned up code to only deal with a 180 degree phase shift in + BPSK. + +2006-06-28 Tom Rondeau + + * src/python/gnuradio/gr/qa_correlate_access_code.py (test_correlate_access_code.test_001): + Changes to access code correlator to handle BPSK phase reversal + killed qa_correlate_access_code. Modified the access code search in + test_001 to all the test to pass properly. + +2006-06-28 Tom Rondeau + + * src/lib/general/gr_constellation_decoder_cb.cc: + Set Compute_EVN=false by default (to clean up the output) + +2006-06-20 Tom Rondeau + + * src/lib/general/gr_costas_loop_cc.{h,cc,i}: modified to support + both BPSK and QPSK via "order" constructor argument. Removed + unused ref_phase ctor arg. + +2006-06-20 Eric Blossom + + * src/lib/general/gr_probe_avg_mag_sqrd_{f,c}.{h,cc,i}: added accessor + for threshold. + + * src/python/gnuradio/blksimpl/pkt.py: result of refactoring + gmsk2_pkt.py. This is the common packet handling framework, and + is modulation independent. gmsk2_pkt is now deprecated. + + * src/python/gnuradio/blksimpl/gmsk2_pkt.py: added deprecation warning. + + * src/python/gnuradio/packet_utils.py (make_packet): added + bits_per_baud parameter to handle QPSK, etc in the future. + +2006-06-17 Eric Blossom + + * src/lib/runtime/gr_realtime.{h,cc,i}: new function to enable + realtime scheduling. + +2006-06-15 Eric Blossom + + * src/lib/io/gr_oscope_guts.{h,cc,i}, + src/lib/io/gr_oscope_sink_x.{h,cc}: added set_sample_rate method. + + * src/lib/general/gr_keep_one_in_n.{h,cc,i}: added set_n method. + +2006-06-13 Eric Blossom + + * src/lib/general/gr_binary_slicer_fb.h: corrected calling sequence. + +2006-06-08 Eric Blossom + + * src/lib/general/gr_feval.{h,cc,i}, + src/python/gnuradio/gr/qa_feval.py: new C++/python helper that + allows C++ code to evaluate a function defined in Python. Uses + SWIG directors. + +2006-06-06 Eric Blossom + + * src/lib/general/gr_unpack_k_bits_bb.cc (work): bug fix. Was + computing the wrong answer and writing *way* too much data if k was > 1. + * src/python/gnuradio/gr/qa_unpack_k_bits.py: new ;) + + * src/lib/general/gr_diff_decoder_bb.{h,cc,i}: new. differential + decoder. constellation index in / constellation index out. + + * src/lib/general/gr_map_bb.{h,cc,i}: new. map any byte into any + other byte. + +2006-06-01 Eric Blossom + + * src/lib/filter/ccomplex_dotprod_3dnow64.S, + src/lib/filter/3dnow_float_dotprod_really_simple.S, + src/lib/filter/3dnow_float_dotprod_simple.S, + src/lib/filter/assembly.h, + src/lib/filter/ccomplex_dotprod_3dnow.S, + src/lib/filter/ccomplex_dotprod_3dnow64.S, + src/lib/filter/ccomplex_dotprod_3dnowext.S, + src/lib/filter/ccomplex_dotprod_3dnowext64.S, + src/lib/filter/ccomplex_dotprod_sse.S, + src/lib/filter/ccomplex_dotprod_sse64.S, + src/lib/filter/complex_dotprod_3dnow.S, + src/lib/filter/complex_dotprod_3dnow64.S, + src/lib/filter/complex_dotprod_3dnowext.S, + src/lib/filter/complex_dotprod_3dnowext64.S, + src/lib/filter/complex_dotprod_sse.S, + src/lib/filter/complex_dotprod_sse64.S, + src/lib/filter/fcomplex_dotprod_3dnow.S, + src/lib/filter/fcomplex_dotprod_3dnow64.S, + src/lib/filter/fcomplex_dotprod_sse.S, + src/lib/filter/fcomplex_dotprod_sse64.S, + src/lib/filter/float_dotprod_3dnow.S, + src/lib/filter/float_dotprod_3dnow64.S, + src/lib/filter/float_dotprod_sse.S, + src/lib/filter/float_dotprod_sse64.S, + src/lib/filter/short_dotprod_mmx.S, + src/lib/filter/short_dotprod_mmx64.S: changed all occurrences of + .align 16 to .p2align 4 to avoid ambiguous interpretation of .align + argument. + + +2006-05-29 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk2_pkt.py: now uses string of 1's + and 0's for access_code representation. Refactored to use + correlate_access_code_bb and frame_sink_1 instead of packet_sink. + + * src/lib/general/gr_binary_slicer_fb.{h,cc,i}: new + * src/lib/general/gr_qpsk_slicer_cb.{h,cc,i}: deleted. Use + gr_constellation_decoder_cb instead. + +2006-05-29 Eric Blossom + + * src/lib/general/gr_clock_recovery_mm_cc.cc: revised + implementation based on 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. + Thanks Tom! + + * src/utils/cool.m, src/utils/db_width.m, src/utils/filter_tools.m, + src/utils/read_char_binary.m, src/utils/read_complex_binary.m, + src/utils/read_float_binary.m, src/utils/read_int_binary.m, + src/utils/read_short_binary.m: modified to be compatible with + MATLAB. + +2006-05-26 Eric Blossom + + * src/lib/general/gr_framer_sink_1.{h,cc,i}: new. Refactored from + gr_packet_sink. Use in combination with gr_correlate_access_code_bb. + +2006-05-24 Eric Blossom + + * src/lib/general/gr_diff_encoder_bb.{h,cc,i}: new. differential encoder. + + * src/lib/general/gr_constellation_decoder_cb.{h,cc,i}: new. + Maps i/q value to closest constellation point and return value + associated with the point. This probably obsoletes + gr_qpsk_slicer_cb. + + * src/lib/general/gr_qpsk_slicer_cb.{h,cc,i}: new. + * src/lib/general/gr_unpack_k_bits_bb.{h,cc,i}: unpack bytes + containing k valid bits, into bytes, 1 bit per byte. + + * src/lib/general/gr_correlate_access_code_bb.{h,cc,i}: new. + General purpose block for searching for access codes (sync + vectors). Can handle any sync vector between 1 and 64 bits. + +2006-05-23 Eric Blossom + + * src/lib/general/gr_diff_phasor_cc.{h,cc,i}: new. Compute phase + difference as a complex number between adjacent complex items in + stream. This is useful for demodulating differentially encoded PSK. + + * src/python/gnuradio/gruimpl/mathmisc.py (log2): new function. + + * src/lib/general/gr_firdes.cc (root_raised_cosine): force ntaps + to be odd. + +2006-05-21 Martin Dudok van Heel + + Added generic test class gr_test. + gr_test is a gnuradio block meant to be used in a flow_graph. + It doesn't do much processing, but you can specify from python every parameter you need to for testing. + For example history, output_multiple, input and output signature, decimation and such. + Especially handy for testing setting up the buffers. + It also touches every available input and output to check for segfaults. + You can also instruct it to not consume all ninput_items or not produce all noutput_items. + + There is also a new script test_buffers.py in src/tests which uses gr_test to test setting up the buffers. + It is NOT automatically run by make check yet, because it will fail with an assert when it reaches circbuf memory limit of the system. + (On linux: Trying to setup a buffer >shmmax + Note that you can set the smmax limit manually on a linux 2.6 system in the following way in a root console) + #set shmmax limit manually to 300MB + echo 300000000 >/proc/sys/kernel/shmmax + + * src/lib/general/Makefile.am: added gr_test + * src/lib/general/general.i: added gr_test + * src/lib/general/gr_test.cc: new + * src/lib/general/gr_test.h: new + * src/lib/general/gr_test.i: new + * src/lib/general/gr_test_types.h: new + * src/tests/test_buffers.py: new script to test setting up the buffers using gr_test + +2006-05-21 Martin Dudok van Heel + + Solved the following bugs which result from incorrect buffersize setup: + sched: is requesting more input data + than we can provide. + ninput_items_required = 8192 + max_possible_items_available = 8191 + If this is a filter, consider reducing the number of taps. + + python: src/lib/runtime/gr_buffer.h:108: unsigned int gr_buffer::index_sub(unsigned int, unsigned int): + Assertion `(unsigned) s < d_bufsize' failed. + Aborted + + * src/python/gnuradio/gr/flow_graph.py: resolved above bugs by adding + mdown.history() to nitems when appropriate + +2006-04-24 Eric Blossom + + * src/lib/general/gr_chunks_to_symbols_XX.{h,cc,i}.t, + src/lib/general/gr_packed_to_unpacked_XX.{h,cc,i}.t, + src/lib/general/gr_unpacked_to_packed_XX.{h,cc,i}.t: + new pseudo-templates for generating family of blocks. Patch + submitted by Achilleas Anastasopoulos , touched + up by Eric. + +2006-04-24 Martin Dudok van Heel + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate): + increase buffer size allocation for blocks with a large + output_multiple, not just those that are decimators. + +2006-04-05 Eric Blossom + + * src/lib/general/gr_pll_carriertracking_cc.i: added + squelch_enable and set_lock_threshold methods. + + * src/lib/general/gr_clock_recovery_mm_cc.h: removed erroneous + class prefix to method. GCC 4.1.0 complains ;) + +2006-04-03 Eric Blossom + + * src/lib/general/gr_pll_carriertracking_cc.cc (phase_detector): + fixed typo. + + * src/python/gnuradio/gr/prefs.py: don't load prefs if + GR_DONT_LOAD_PREFS environment variable is set. run_tests sets + this to avoid interactions with system and user prefs during + make check. + + * src/python/gnuradio/gr/qa_rational_resampler.py: disabled two + tests that were causing hangs on SuSE 10.0. Should be investigated. + +2006-03-30 Eric Blossom + + * src/lib/filter/gr_fft_filter_ccc.{h,cc}, + src/lib/filter/gr_fft_filter_fff.{h,cc}: reworked to allow + safer setting of new taps after instantiation. + +2006-03-29 Eric Blossom + + * src/lib/general/gr_prefix.{h,cc,i}: new function that returns + installation prefix directory (--prefix argument to configure). + + * src/lib/general/gr_prefs.{h,cc,i}: reworked implementation to + use python ConfigParser. + * src/python/gnuradio/gr/prefs.py: moved from + src/python/gnuradio/prefs.py to solve initialization problem. + + * src/lib/general/gr_stream_to_vector.{h,cc,i}: renamed from gr_serial_to_parallel + * src/lib/general/gr_vector_to_stream.{h,cc,i}: renamed from gr_parallel_to_serial + * src/lib/python/gnuradio/gr/__init__.py: new aliases for + backwards compatibility with rename. + + * src/lib/swig/Makefile.am: cleanup for make distcheck. + + * src/lib/atsc/GrAtscBitTimingLoop.cc, GrAtscBitTimingLoop.h, + GrAtscBitTimingLoop2.cc, GrAtscBitTimingLoop2.h, + GrAtscBitTimingLoop3.cc, GrAtscBitTimingLoop3.h, + GrAtscConvert2xTo20.cc, GrAtscConvert2xTo20.h, + GrAtscDataSegToSoftDataSeg.cc, GrAtscDataSegToSoftDataSeg.h, + GrAtscDeinterleaver.cc, GrAtscDeinterleaver.h, + GrAtscDerandomizer.cc, GrAtscDerandomizer.h, + GrAtscEqualizer.cc, GrAtscEqualizer.h, GrAtscFPLL.cc, + GrAtscFPLL.h, GrAtscFieldSyncChecker.cc, + GrAtscFieldSyncChecker.h, GrAtscFieldSyncCorrelator.cc, + GrAtscFieldSyncCorrelator.h, GrAtscFieldSyncDemux.cc, + GrAtscFieldSyncDemux.h, GrAtscFieldSyncMux.cc, + GrAtscFieldSyncMux.h, GrAtscInterleaver.cc, + GrAtscInterleaver.h, GrAtscRSDecoder.cc, GrAtscRSDecoder.h, + GrAtscRSEncoder.cc, GrAtscRSEncoder.h, GrAtscRandomizer.cc, + GrAtscRandomizer.h, GrAtscSegSymSync.cc, GrAtscSegSymSync.h, + GrAtscSegSymSyncImpl.cc, GrAtscSegSymSyncImpl.h, + GrAtscSegSymSyncImpl_export.h, GrAtscSymbolMapper.h, + GrAtscTrellisEncoder.cc, GrAtscTrellisEncoder.h, + GrAtscViterbiDecoder.cc, GrAtscViterbiDecoder.h, Makefile.am, + README, atsc_basic_trellis_encoder.cc, + atsc_basic_trellis_encoder.h, atsc_consts.h, + atsc_data_interleaver.cc, atsc_data_interleaver.h, + atsc_diag_output.h, atsc_equalizer.cc, atsc_equalizer.h, + atsc_equalizer_lms.cc, atsc_equalizer_lms.h, + atsc_equalizer_lms2.cc, atsc_equalizer_lms2.h, + atsc_equalizer_nop.cc, atsc_equalizer_nop.h, atsc_exp2_lp.cc, + atsc_exp2_lp.h, atsc_exp2_lp20.dat, atsc_exp2_lp2x.dat, + atsc_fake_single_viterbi.cc, atsc_fake_single_viterbi.h, + atsc_fs_checker.cc, atsc_fs_checker.h, + atsc_fs_checker_naive.cc, atsc_fs_checker_naive.h, + atsc_fs_correlator.cc, atsc_fs_correlator.h, + atsc_fs_correlator_naive.cc, atsc_fs_correlator_naive.h, + atsc_pnXXX.cc, atsc_pnXXX.h, atsc_randomizer.cc, + atsc_randomizer.h, atsc_reed_solomon.cc, atsc_reed_solomon.h, + atsc_root_raised_cosine.cc, atsc_root_raised_cosine.h, + atsc_root_raised_cosine_bandpass.cc, + atsc_root_raised_cosine_bandpass.h, atsc_single_viterbi.cc, + atsc_single_viterbi.h, atsc_slicer_agc.h, + atsc_sliding_correlator.cc, atsc_sliding_correlator.h, + atsc_sssr.cc, atsc_sssr.h, atsc_syminfo.h, atsc_sync_tag.h, + atsc_trellis_encoder.cc, atsc_trellis_encoder.h, atsc_types.h, + atsc_viterbi_decoder.cc, atsc_viterbi_decoder.h, + atsc_viterbi_gen.cc, atsc_vsbtx_lp.cc, atsc_vsbtx_lp.dat, + atsc_vsbtx_lp.h, convolutional_interleaver.h, + create_atsc_equalizer.cc, create_atsc_equalizer.h, + create_atsc_fs_checker.cc, create_atsc_fs_checker.h, + create_atsc_fs_correlator.cc, create_atsc_fs_correlator.h, + fpll_btloop_coupling.h, gen_encoder.py, interleaver_fifo.h, + plinfo.cc, qa_atsc.cc, qa_atsc.h, + qa_atsc_basic_trellis_encoder.cc, + qa_atsc_basic_trellis_encoder.h, qa_atsc_data_interleaver.cc, + qa_atsc_data_interleaver.h, qa_atsc_equalizer_nop.cc, + qa_atsc_equalizer_nop.h, qa_atsc_fake_single_viterbi.cc, + qa_atsc_fake_single_viterbi.h, qa_atsc_fs_correlator.cc, + qa_atsc_fs_correlator.h, qa_atsc_randomizer.cc, + qa_atsc_randomizer.h, qa_atsc_reed_solomon.cc, + qa_atsc_reed_solomon.h, qa_atsc_single_viterbi.cc, + qa_atsc_single_viterbi.h, qa_atsc_sliding_correlator.cc, + qa_atsc_sliding_correlator.h, qa_atsc_trellis_encoder.cc, + qa_atsc_trellis_encoder.h, + qa_atsc_trellis_encoder_t1_input.dat, + qa_atsc_trellis_encoder_t1_output.dat, + qa_atsc_viterbi_decoder.cc, qa_atsc_viterbi_decoder.h, + qa_atsc_viterbi_decoder_t1_input.dat, + qa_atsc_viterbi_decoder_t1_output.dat, + qa_convolutional_interleaver.cc, + qa_convolutional_interleaver.h, qa_interleaver_fifo.cc, + qa_interleaver_fifo.h: Moved all atsc code from src/lib/atsc to + new gr-atsc CVS module. + + * src/lib/general/gri_ringbuffer.{h,cc}: removed. Use + gr_buffer/gr_buffer_reader instead. + +2006-03-27 Eric Blossom + + * src/lib/general/gr_prefs.{h,cc,i}: renamed parameter from "val" to + "v" to work around issue in SWIG 1.3.{28,29} and/or g++ 4.0.2. + + * src/lib/general/gr_prefs.{h,cc,i}, src/python/gnuradio/prefs.py: + new class for user preferences. This uses SWIG directors (serious + magic), to have the actual implementation be in python, but + callable transparently from C++. We'll use this for user prefs + such as audio module, audio module options, etc. + +2006-03-25 Eric Blossom + + * src/lib/io/gri_logger.h (class gri_logger): new class that can + safely log to a file from within a JACK or portaudio callback. + Uses a ringbuffer to communicate with a separate thread that + writes the file. + +2006-03-17 Eric Blossom + + * src/lib/runtime/gr_buffer.cc (gr_buffer_reader): added missing + drop_reader call to destructor. Fixed latent bug. + +2006-03-15 Eric Blossom + + * src/lib/omnithread.h, + src/lib/omnithread/ot_posix.h, src/lib/omnithread/posix.cc, + src/lib/omnithread/nt.cc: mods to + allow specifying a max count on semaphores. This allows the + construction of binary semaphores by passing max_count=1 to the ctor. + The default behavior is unchanged. + +2006-03-13 Eric Blossom + + * src/lib/general/gr_pll_carriertracking_cc.cc (work): refactored + loop control. + +2006-03-12 Stephane Fillod + * src/lib/general/gri_ringbuffer.{cc,h}, + src/lib/general/Makefile.am: new lockless ringbuffer (single + reader/single writer) taken from JACK software (GPL). + * * src/lib/omnithread/omnithread.h: add omni_mutex::trylock + * * src/lib/omnithread/ot_posix.h: POSIX trylock implementation + * * src/lib/omnithread/ot_nt.h: Win32 trylock implementation + +2006-03-12 Eric Blossom + + * src/lib/general/gr_firdes.h, src/lib/io/gr_file_source.h: Fix + for g++ 4.1. Removed extra class:: qualification. Patch + submitted by Martin Michlmayr + +2006-03-10 Eric Blossom + + * src/lib/general/gr_dd_mpsk_sync_cc.cc: doc fixes. reworked + delay line handling. + * src/lib/general/gr_dd_mpsk_sync_cc.h: doc fixes. Added DLLEN const. + * src/lib/general/gr_costas_loop_cc.h: doc fixes. + * src/lib/general/gr_costas_loop_cc.cc (work): cosmetic tweak to + loop control. + +2006-03-07 Eric Blossom + + * src/lib/general/gr_multiply_const_XX.h.t, + src/lib/general/gr_quadrature_demod_cf.h, + src/lib/general/gr_frequency_modulator_fc.h, + src/lib/general/gr_packed_to_unpacked_bb.h, + src/lib/general/gr_unpacked_to_packed_bb.h, + src/lib/general/gr_chunks_to_symbols_bf.h, + src/lib/general/gr_chunks_to_symbols_bc.h: doc fixs. + +2006-02-22 Martin Dudok van Heel + + Addded new blocks gr_single_pole_iir_filter_cc + gr_agc_cc + gr_phase_modulator_fc + Changed gr_single_pole_iir.h to make this work + Bugfix, to make make_check work again. + + * src/lib/filter/Makefile.am: Added gr_single_pole_iir_filter_cc + Added missing gr_single_pole_avg.h and gr_single_pole_rec.h (fix make check bug) + * src/lib/filter/filter.i: changed. Added gr_single_pole_iir_filter_cc + * src/lib/filter/gr_single_pole_iir.h: changed template to have + partial specialization for . Needed + because calculations and temporary variables have to be + gr_complexd in this special case + * src/lib/filter/gr_single_pole_iir_filter_cc.cc: new + * src/lib/filter/gr_single_pole_iir_filter_cc.h: new + * src/lib/filter/gr_single_pole_iir_filter_cc.i: new + * src/lib/general/Makefile.am: changed. Added gr_agc_cc, gr_phase_modulator_fc,gri_agc_cc + * src/lib/general/general.i: changed. Added gr_agc_cc, gr_phase_modulator_fc + * src/lib/general/gr_agc_cc.cc: new + * src/lib/general/gr_agc_cc.h: new + * src/lib/general/gr_agc_cc.i: new + * src/lib/general/gr_phase_modulator_fc.cc: new + * src/lib/general/gr_phase_modulator_fc.h: new + * src/lib/general/gr_phase_modulator_fc.i: new + * src/lib/general/gri_agc_cc.h: new + * src/lib/general/gri_agc_cc.i: new + * src/python/gnuradio/gr/Makefile.am: changed. Added qa_single_pole_iir_cc.py + * src/python/gnuradio/gr/qa_single_pole_iir_cc.py: new + +2006-02-17 Stephane Fillod + + * configure.ac, src/lib/filter/ccomplex_dotprod_generic.cc, + src/lib/filter/complex_dotprod_generic.cc, + src/lib/filter/generate_gr_fir_sysconfig.py, + src/lib/filter/generate_gr_fir_sysconfig_generic.py, + src/lib/filter/generate_gr_fir_util.py, + src/lib/filter/gr_fir_XXX.cc.t, + src/lib/filter/gr_fir_XXX_generic.cc.t, + src/lib/filter/gr_fir_ccc_simd.cc, + src/lib/filter/gr_fir_ccc_x86.cc, + src/lib/filter/gr_fir_ccf_simd.cc, + src/lib/filter/gr_fir_ccf_x86.cc, + src/lib/filter/gr_fir_fcc_simd.cc, + src/lib/filter/gr_fir_fcc_x86.cc, + src/lib/filter/gr_fir_fff_simd.cc, + src/lib/filter/gr_fir_fff_x86.cc, + src/lib/filter/gr_fir_fsf_simd.cc, + src/lib/filter/gr_fir_fsf_x86.cc, + src/lib/filter/gr_fir_scc_simd.cc, + src/lib/filter/gr_fir_scc_x86.cc, + src/lib/filter/gr_fir_sysconfig_x86.cc, + src/lib/filter/gri_mmse_fir_interpolator.cc, + src/lib/filter/gri_mmse_fir_interpolator_cc.cc, + src/lib/filter/sysconfig_x86.cc, + src/lib/general/gr_align_on_samplenumbers_ss.cc, + src/lib/general/gr_crc32.cc, + src/lib/general/gr_head.cc, + src/lib/general/gr_lfsr_32k_source_s.cc, + src/lib/general/gr_noise_source_X.cc.t, + src/lib/general/gr_nop.cc, + src/lib/general/gr_reverse.cc, + src/lib/general/gr_sig_source_X.cc.t, + src/lib/general/gr_simple_correlator.cc, + src/lib/general/gr_simple_framer.cc, + src/lib/general/gr_skiphead.cc, + src/lib/general/gr_vector_sink_X.cc.t, + src/lib/general/gr_vector_source_X.cc.t, + src/lib/general/qa_gr_fxpt.cc, + src/lib/general/qa_gr_fxpt_nco.cc, + src/lib/general/qa_gr_fxpt_vco.cc, + src/lib/io/gr_oscope_guts.cc, + src/lib/runtime/gr_io_signature.cc, + src/lib/runtime/gr_types.h, + src/lib/runtime/qa_gr_block.cc, + src/lib/runtime/qa_gr_buffer.cc, + src/lib/runtime/qa_gr_io_signature.cc: added proper config check + for stdint.h to define gr_int* types. + +2006-02-16 Eric Blossom + + * src/lib/runtime/gr_types.h: added typedef for gr_int64 and + gr_uint64. Need proper autoconf fix for these. + +2006-02-08 Eric Blossom + + * src/lib/io/gr_file_sink.{h,cc,i}: added new methods: enable & + disable. Thanks Marcus! + +2006-02-06 Eric Blossom + + * src/lib/general/gr_kludge_copy.{h,cc,i}: new. Copies input to output. + * src/python/gnuradio/gr/qa_kludge_copy.py: new QA code. + +2006-02-05 Eric Blossom + + * src/python/gnuradio/gr/qa_iir.py (test_iir.test_iir_direct_008): + accept either RuntimeError or ValueError in test case. The return + value changed in swig 1.3.28. + + * src/lib/swig/gnuradio.i: now use anonymous templates for + std::vector's. This was a tip from one of the SWIG developers. + It generates less code. + +2006-02-02 Eric Blossom + + * src/python/gnuradio/gruimpl/seq_with_cursor.py: added method to + select closest index by value. + +2006-01-30 Eric Blossom + + * src/lib/general/gr_packet_sink.{h,i}: Added new "carrier_sensed" + method. Naive implementation, but it just might work ;) + * src/python/gnuradio/blksimpl/gmsk2_pkt.py (carrier_sensed): new method. + +2006-01-28 Eric Blossom + + * src/lib/general/gr_pa_2x2_phase_combiner.{h,cc,i}: new. + four antenna phase combiner for phased array experiments. + + * src/lib/general/gr_simple_squelch_cc.{h,cc,i}: added threshold + and squelch_range methods. + +2006-01-24 Eric Blossom + + * src/lib/general/gr_sync_block.cc (forecast): removed duplicated code. + * src/lib/general/gr_sync_interpolator.cc (forecast): removed duplicated code. + * src/lib/general/gr_sync_decimation.cc (forecast): removed duplicated code. + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + take advantage of fixed_rate() method so that we can consume all + available input. Fixed bad audio sound with encdec. + +2005-12-23 Eric Blossom + + * src/lib/general/gr_interleaved_short_to_complex.i (class + gr_interleaved_short_to_complex): corrected superclass spec. + +2005-12-19 Martin Dudok van Heel + + Addded a new blocks to convert from unsigned char to float and for char to float. + Added new agc block gr_agc_ff based on existing gr_agc block + (which can't be directly used in a flowgraph). All needed for + tv-reception. + + * src/lib/general/gr_uchar_to_float.{cc,h,i}: new + * src/lib/general/gri_uchar_to_float.{cc,h}: new + * src/lib/general/gr_char_to_float.{cc,h,i}: new + * src/lib/general/gri_char_to_float.{cc,h}: new + * src/lib/general/gr_agc_ff.cc: new + * src/lib/general/gr_agc_ff.h: new + * src/lib/general/gr_agc_ff.i: new + * src/lib/general/Makefile.am: changed. Added gr_agc_ff, + gr_(u)char_to_float and gri_(u)char_to_float. + * src/lib/general/general.i: changed. Added + gr_agc_ff,gr_(u)char_to_float and gri_(u)char_to_float. + +2005-12-17 Eric Blossom + + * src/lib/general/gr_quadrature_demod_cf.cc: use fast arctan code. + +2005-12-17 Bob McGwier N4HY + + * src/lib/general/gr_lms_dfe_cc.{h,cc,i}: new. + * src/lib/general/gr_fast_atan2f.cc: new. Fast arc tangent using + table lookup and interpolation. Declaration added to gr_math.h + +2005-12-17 Eric Blossom + + * src/lib/general/gr_lms_dfe_ff.h: doc fix. + * src/lib/general/gr_lms_dfe_ff.cc: refactored. Moved common + functions to gr_misc + * src/lib/general/gr_misc.{h,cc}: new. Collect misc functions in + one place. + * doc/Makefile.am: --enable-doxygen default is now "no" + +2005-12-16 Eric Blossom + + * src/lib/swig/gnuradio_swig_bug_workaround.h: removed from CVS. + It's generated when it's needed. + +2005-12-09 Eric Blossom + + made 2.6 release. + +2005-12-08 Chuck Swiger + + * src/lib/general/gr_probe_signal_f.{h,cc,i}: new. Return a + single sample from the stream. + +2005-12-07 Chuck Swiger + + * src/lib/general/gr_probe_avg_mag_sqrd_{f,c}.{h,cc,i}: new. + Sinks that measure the average magnitude squared and allow the + value to be retrieved via accessors. + +2005-12-06 Eric Blossom + + * src/lib/general/gr_clock_recovery_mm_ff.cc: doc fix: added reference to book. + +2005-12-01 Eric Blossom + + * src/lib/general/gr_packet_sink.h (class gr_packet_sink): changed + d_threshold to unsigned to eliminate warning. + * src/lib/general/gr_simple_correlator.cc: removed duplicate + definition of slice. + +2005-12-01 Stephane Fillod + + * src/lib/general/gr_count_bits.cc (gr_count_bits32): faster + implementation. No branching. + +2005-11-22 Ramakrishnan Muthukrishnan + + * src/python/gnuradio/gr/qa_filter_delay_fc.py, + src/python/gnuradio/gr/qa_hilbert.py: updated QA code to reflect + change in delay line handling. + +2005-11-21 Eric Blossom + + * config/gr_boost.m4: reworked to look for latest version if + installed in version-specific subdir of /usr/local/include. + * src/lib/swig/Makefile.am (DISTCLEANFILES): added gnuradio_swig_python.d + +2005-11-19 Eric Blossom + + * config/usrp_libusb.m4 (USRP_LIBUSB): add -lIOKit under darwin. + * config/gr_no_undefinedm4, config/gr_set_md_cpu.m4, + config/gr_x86_64.m3, config/usrp_fusb_tech.m4, + config/usrp_libusb.m4: changed incorrect use of + AC_CANONICAL_TARGET to HOST. + +2005-11-18 Eric Blossom + + These changes enabled discontinous transmission of usrp packets. + The treatment of history was slightly changed. Now we provide + zeros for the initial delay lines and produce N outputs for N + inputs. In the past we would produce N-history-1 outputs for N inputs. + + * src/python/gnuradio/packet_utils.py: ensure at least a single + byte of padding to flush filters. + * src/lib/runtime/gr_block.{h,cc,i}, + src/lib/general/gr_sync_block.{h,cc,i}, + src/lib/general/gr_sync_decimator.{h,cc,i}, + src/lib/general/gr_sync_interpolator.{h,cc,i}: moved history into + gr_block from gr_sync_block. Added new methods to support fast + path through scheduler: fixed_rate, fixed_rate_ninput_to_output + and fixed_rate_noutput_to_input. + + * src/python/gnuradio/gr/flow_graph.py (flow_graph._connect_inputs): + account for initial history when attaching buffer reader. + * src/lib/runtime/gr_buffer.{h,cc,i} (gr_buffer_add_reader): modified to + provide zeros for initial history. + + * src/python/gnuradio/gr/qa_fft_filter.py, + src/python/gnuradio/gr/qa_filter_delay_fc.py, + src/python/gnuradio/gr/qa_hilbert.py, + src/python/gnuradio/gr/qa_interp_fir_filter.py, + src/python/gnuradio/gr/qa_rational_resampler.py: tweaked QA code + to work with new history behavior. + + +2005-11-17 Eric Blossom + + * src/lib/filter/gr_interp_fir_filter_XXX.cc.t, + gr_rational_resampler_base_XXX.cc.t: ensure that history is set in + constructor. + + * src/lib/runtime/gr_msg_queue.i: more evil hackery to release + Python global interpreter lock around blocking msg_queue methods. + + * src/python/gnuradio/packet_utils.py (make_packet): conditionally + add padding such that final packet is a multiple of 512 bytes on the USB. + +2005-11-16 Eric Blossom + + * src/lib/io/gr_message_source.h (class gr_message_source): added + msgq limit to constructor args. + + * src/lib/general/gr_packet_sink.{h,cc,i}: added access code + detection threshold to ctor args. + + * src/lib/filter/gri_mmse_fir_interpolator.{h,cc}: declared interpolate const. + + * src/lib/general/gr_clock_recovery_mm_ff.cc: limit excursions of + omega using omega_relative_limit. Added conditional diagnostic logging. + + * src/lib/runtime/gr_msg_queue.{h,cc}: block when inserting into a + full msg queue. + + * src/lib/filter/gr_fractional_interpolator.cc (general_work): + 1.0 - d_mu -> d_mu to match revised filter defs. + +2005-11-15 Eric Blossom + + * src/lib/io/gr_oscope_guts.{h,cc}, + src/lib/io/gr_oscope_sink_f.{h,cc,i}: Refactored to use messages + and message queues to communicate to Python. This code will never + block waiting for the gui. + * src/lib/io/gr_message_sink.{h,cc,i}: new. A sink that packages up its + input and puts it in a message queue. + +2005-11-14 Eric Blossom + + * doc/Doxyfile.in: updated to latest version. Turned off serveral + options to reduce documentation generation time. + +2005-11-13 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk2.py, + src/python/gnuradio/blksimpl/gmsk2_pkt.py: new GMSK mod/demod. + * src/python/gnuradio/gruimpl/mathmisc.py: new: gcd, lcm. + * src/python/gnuradio/blksimpl/rational_resampler.py: If neither + taps nor fractional_bw is supplied, provide a reasonable default. + +2005-11-11 Eric Blossom + + * src/lib/filter/qa_gri_mmse_fir_interpolator.cc (t1): revised sign. + + * src/lib/filter/gr_fir_filter_XXX.cc.t (work): if taps updated, return 0. + * src/lib/filter/gr_interp_fir_filter_XXX.cc.t (work): if taps updated, return 0. + +2005-11-09 Matt Ettus + + * src/lib/general/gr_packet_sink.cc (gr_make_packet_sink): new. + slices, correlates for packet access code, checks header and + assembles packets. + +2005-11-09 Eric Blossom + + * src/lib/io/gr_message_source.h: new class. Messages sent to + this class are streamed to its single output. + + * src/lib/runtime/gr_message.{h,cc,i}: removed unused methods; new + constructor from string; get contents as string. + + * src/lib/filter/gri_mmse_fir_interpolator.{h,cc}: renamed from gr_mmse_fir_interpolator. + * src/lib/filter/gr_fractional_interpolator.{h,cc,i}: new. + +2005-11-08 Eric Blossom + + * src/lib/general/gr_crc32.{h,cc,i}: new. ISO 3309 CRC-32 generator. + +2005-11-08 Matt Ettus + + * src/lib/general/gr_threshold_ff.{h,cc,i}: new. + * src/python/gnuradio/blksimpl/standard_squelch.py: new + * src/python/gnuradio/blksimpl/nbfm_rx.py: removed squelch from + block. + +2005-11-07 Eric Blossom + + * src/python/gnuradio/blksimpl/rational_resampler.py + (design_filter): added code to automatically design filter. + + * src/lib/general/gr_firdes.cc (window): fixed Kaiser window. + +2005-10-28 Eric Blossom + + * src/lib/io/gr_oscope_sink_f.cc (gr_oscope_sink_f): fixed del of + unowned variable that was causing double-free. + +2005-10-23 Eric Blossom + + * src/lib/general/gr_nco.h (gr_nco): removed unused local var. + +2005-10-17 Eric Blossom + + * src/lib/general/gr_fxpt_vco.h: use floats instead of double. + Gives 30% speedup on Opteron under gcc 3.3.5 + +2005-10-17 Stephane Fillod + + * src/lib/general/gr_fxpt_nco.h, src/lib/general/gr_nco.h, + src/lib/general/gr_sig_source_X.cc.t: set primitives in shape + for an eventual simd speedup. fix bug in sincos() of gr_nco.h. + + * src/lib/general/Makefile.am, src/lib/general/gr_vco.h, + src/lib/general/gr_vco_f.cc, src/lib/general/gr_vco_f.h, + src/lib/general/qa_gr_fxpt_vco.h, src/lib/general/qa_gr_fxpt_vco.cc, + src/lib/general/qa_general.cc, src/tests/benchmark_vco.cc, + src/lib/general/gr_fxpt_vco.h: make use of fixed point cosine for VCO, + with appropriate QA code, set primitives in shape for an eventual + simd speedup. + * src/lib/general/qa_gr_fxpt_vco.cc, src/lib/general/gr_vco.h, + src/lib/general/qa_gr_fxpt_vco.h, src/lib/general/gr_fxpt_vco.h: new + + * README: reference gr-audio-jack, gr-audio-windows and gr-comedi + +2005-10-12 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.{h,cc}: resurrected + rev 1.1 then added check for contiguous mapping. + * src/lib/runtime/gr_vmcircbuf.cc: enable gr_vmcircbuf_mmap_tmpfile. + +2005-10-11 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc + (gr_vmcircbuf_mmap_shm_open): corrected error message. + +2005-10-10 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.{h,cc}: removed. + +2005-10-10 Stephane Fillod + + * src/lib/general/gr_check_counting_s.cc, + src/lib/general/gr_check_lfsr_32k_s.cc, + src/lib/general/gr_vector_source_X.cc.t, + src/lib/runtime/gr_vmcircbuf_createfilemapping.cc, + src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc: compiler warning + silencing. + + * src/lib/general/gr_sig_source_X.cc.t, + src/lib/general/gr_fxpt_nco.h, + src/lib/general/gr_nco.h: added sincos block primitive. + * src/lib/general/qa_gr_fxpt_nco.cc: qa code for new sincos + block primitive. cleanup. + * src/tests/benchmark_nco.cc: benchmark the new sincos block + + * src/tests/Makefile.am: added benchmark_vco + src/tests/benchmark_vco.cc: new + +2005-10-05 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py (hier_block_base.__init__): + reenabled weakref to break circular graph. + * src/python/gnuradio/gr/basic_flow_graph.py (basic_flow_graph), + src/python/gnuradio/gr/flow_graph.py (flow_graph): + removed __slots__ class attribute so we can create weakrefs to + flow graphs. + + * src/python/gnuradio/gr/gr_threading.py: New. Load appropriate bug fix. + * src/python/gnuradio/gr/gr_threading_23.py (Thread.join): bug fixed + version of python 2.3 threading.py. + * src/python/gnuradio/gr/gr_threading_24.py (Thread.join): bug fixed + version of python 2.4 threading.py. + + * src/lib/general/gr_vco_f.{h,cc,i}: new VCO block. + +2005-10-03 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py (hier_block_base.__init__): + backed out use of weakref. + * src/python/gnuradio/gr/scheduler.py (scheduler.wait): backed out + "Control-C fix". + +2005-10-02 Eric Blossom + + * src/python/gnuradio/blksimpl/wfm_tx.py: New. Wide band FM tx block. + +2005-09-29 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py (hier_block_base.__init__): + store weakref to flow_graph to break circular graph so that flow + graph can be reclaimed right away. + + * src/python/gnuradio/gr/flow_graph.py (flow_graph.__del__): call + self.stop() to ensure that i/o devices get shutdown gracefully. + + * src/python/gnuradio/gr/scheduler.py (scheduler.wait): calling + thread.join was keeping us from seeing SIGINT. Replaced with + alternate implementation. + +2005-09-27 Eric Blossom + + * src/python/gnuradio/eng_option.py (check_subdev): removed the + (0, None) and (1, None) results. + +2005-09-21 Eric Blossom + + * src/python/gnuradio/eng_option.py (check_subdev): added new + command line parser type, "subdev", for selecting usrp daughterboards. + +2005-09-17 Krzysztof Kamieniecki + + * src/lib/filter/qa_gr_fir_ccf.cc: alignment fix for gcc 4.x + +2005-08-28 Stephane Fillod + + * config/gr_set_md_cpu.m4, src/lib/filter/Makefile.am: add simd + support for x86_64 platform. + + * src/lib/filter/ccomplex_dotprod_3dnow64.S, + src/lib/filter/ccomplex_dotprod_3dnowext64.S, + src/lib/filter/ccomplex_dotprod_sse64.S, + src/lib/filter/complex_dotprod_3dnow64.S, + src/lib/filter/complex_dotprod_3dnowext64.S, + src/lib/filter/complex_dotprod_sse64.S, + src/lib/filter/fcomplex_dotprod_3dnow64.S, + src/lib/filter/fcomplex_dotprod_sse64.S, + src/lib/filter/float_dotprod_3dnow64.S, + src/lib/filter/float_dotprod_sse64.S, + src/lib/filter/short_dotprod_mmx64.S, + src/lib/filter/cpuid_x86_64.S: new + + * src/lib/filter/ccomplex_dotprod_3dnow.S, + src/lib/filter/ccomplex_dotprod_3dnowext.S, + src/lib/filter/ccomplex_dotprod_sse.S, + src/lib/filter/complex_dotprod_3dnow.S, + src/lib/filter/complex_dotprod_3dnowext.S, + src/lib/filter/complex_dotprod_sse.S, + src/lib/filter/fcomplex_dotprod_3dnow.S, + src/lib/filter/fcomplex_dotprod_sse.S, + src/lib/filter/float_dotprod_3dnow.S, + src/lib/filter/float_dotprod_sse.S, + src/lib/filter/short_dotprod_mmx.S + src/lib/filter/cpuid_x86.S: filename debug info fix, + removed useless emms instruction in pure SSE. + * src/lib/filter/qa_gr_fir_ccc.cc: comment fix + +2005-08-28 Eric Blossom + + * src/lib/general/malloc16.c: fixed 64-bit pointer to int cast problem. + +2005-08-26 Eric Blossom + + * src/python/gnuradio/gr/qa_rational_resampler.py + (test_rational_resampler.test_002_interp): reduced random test + from 10k cases to 1000 cases. The 10k case turns up a single + failure. FIXME figure out why! + + * src/python/gnuradio/gr/qa_fsk_stuff.py + (test_bytes_to_syms.test_simple_framer): fixed test case to + reflect 0x55 trailing tail. + + * src/lib/filter/qa_gr_fir_ccc.cc (test_random_io): Ensure 16-byte + input alignment to meet contract with SIMD ccc kernel. + +2005-08-25 Eric Blossom + + * src/lib/general/gr_simple_correlator.cc: average the samples in + the sync field and use this to set the slicing level for the + payload. This helps account for frequency offsets between the Tx + and Rx sides. + +2005-08-24 Eric Blossom + + * src/lib/general/gr_simple_framer_sync.h: include GRSF_TAIL_PAD + in GRSF_OVERHEAD. + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): now + only invoke sources if we are not making progress. This avoids + blocking (in most cases) unless we've got nothing better to do. + + * src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t + (build_composite_fir): reversed taps to fix problem introduced + when we "rationalized" the tap ordering a while ago. [We are + missing a unit test for this...] + +2005-08-22 Matt Ettus + + * src/python/gnuradio/blksimpl/gmsk.py: + made several changes to the filters on both TX and RX. + The demod filter (integrate_taps) should not average + over multiple samples. In reality, a few samples should + work, so I'm not sure why it doesn't here. + +2005-08-22 Eric Blossom + + * src/lib/general/gr_simple_correlator.cc (general_work): removed + incorrect magic number and replaced with constant expression. + [Almost as embarrassing as a buffer overflow] + +2005-08-21 Eric Blossom + + * src/lib/general/gr_simple_framer_sync.h: added one byte tail + padding to ensure that correlator has a chance to get synced in + case it was later on the previous packet. + + * src/lib/general/gr_simple_correlator.cc (general_work): + corrected to use count_bits64. + +2005-08-19 Eric Blossom + + * doc/Makefile.am: clean-local now uses $(RM) -fr + +2005-08-18 Eric Blossom + + * src/lib/general/gr_count_bits.{h,cc}: new gr_count_bits64. + + * src/lib/general/gr_simple_correlator.{h,cc}, + src/lib/general/gr_simple_framer.{h,cc}, + src/lib/general/gr_simple_framer_sync.h, + src/python/gnuradio/gr/qa_fsk_stuff.py: changed length of SYNC + code from 32 to 64 bits. + +2005-08-16 Andrew Thomas Beck + + * src/lib/runtime/gr_vmcircbuf_createfilemapping.cc (gr_vmcircbuf_createfilemapping): fixes. + +2005-08-15 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.i, + src/lib/runtime/gr_block_detail.i, src/lib/runtime/gr_buffer.i: + fixes for SWIG 1.3.25. Thanks to Job de Haas for a big clue! + +2005-08-08 Martin Dudok van Heel + + Addded a new block to convert from float to unsigned char. Needed for new tv-reception example. + + * src/lib/general/gr_float_to_uchar.{cc,h,i}: new + * src/lib/general/gri_float_to_uchar.{cc,h}: new + * src/lib/general/Makefile.am: changed. Added gr_float_to_uchar and gri_float_to_uchar. (Also added gr_float_to_char.h which was + forgotten in previous patch to add gr_float_to_char) + * src/lib/general/general.i: changed. Added gr_float_to_uchar and gri_float_to_uchar. + +2005-07-28 Eric Blossom + + * src/lib/general/qa_gr_circular_file.cc (t1): conditionalized + base on HAVE_MMAP. + +2005-07-24 Stephane Fillod + + * src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc: get correct + granularity under Cygwin. + + * src/lib/filter/Makefile.am: renamed .s files to .S in order + to enable preprocessor support in assembly source + * src/lib/general/README: misc status update + * src/lib/filter/assembly.h: new + * src/lib/filter/3dnow_float_dotprod_really_simple.S, + src/lib/filter/3dnow_float_dotprod_simple.S, + src/lib/filter/ccomplex_dotprod_3dnow.S, + src/lib/filter/ccomplex_dotprod_3dnowext.S, + src/lib/filter/ccomplex_dotprod_sse.S, + src/lib/filter/complex_dotprod_3dnow.S, + src/lib/filter/complex_dotprod_3dnowext.S, + src/lib/filter/complex_dotprod_sse.S, + src/lib/filter/fcomplex_dotprod_3dnow.S, + src/lib/filter/fcomplex_dotprod_sse.S, + src/lib/filter/float_dotprod_3dnow.S, + src/lib/filter/float_dotprod_sse.S, + src/lib/filter/short_dotprod_mmx.S, + src/lib/filter/cpuid_x86.S: new, moved from .s files with + added preprocessor macros to handle both ELF and Windows + x86 assembly. + * src/lib/filter/3dnow_float_dotprod_really_simple.s, + src/lib/filter/3dnow_float_dotprod_simple.s, + src/lib/filter/ccomplex_dotprod_3dnow.s, + src/lib/filter/ccomplex_dotprod_3dnowext.s, + src/lib/filter/ccomplex_dotprod_sse.s, + src/lib/filter/complex_dotprod_3dnow.s, + src/lib/filter/complex_dotprod_3dnowext.s, + src/lib/filter/complex_dotprod_sse.s, + src/lib/filter/fcomplex_dotprod_3dnow.s, + src/lib/filter/fcomplex_dotprod_sse.s, + src/lib/filter/float_dotprod_3dnow.s, + src/lib/filter/float_dotprod_sse.s, + src/lib/filter/short_dotprod_mmx.s, + src/lib/filter/cpuid_x86.s: removed (renamed) + + +2005-07-21 Eric Blossom + + * src/lib/filter/gr_fft_filter_fff.cc (compute_sizes): turned off + debugging output. + +2005-07-20 Eric Blossom + + * src/python/gnuradio/blksimpl/filterbank.py: documented channel + number to frequency mapping. Fixed a couple of problems related + to reversing filter tap order. + +2005-07-20 Martin Dvh + + * src/lib/runtime/gr_vmcircbuf_createfilemapping.{h,cc}: new. + Native implementation for Windows NT/W2K/XP. + * config/gr_python.m4: MinGW mods. + +2005-07-19 Eric Blossom + + * src/lib/filter/gr_fft_filter_fff.{h,cc,i}: new. Work in + progress. Not yet ready for prime time. + + * src/lib/runtime/gr_single_threaded_scheduler.cc: fixed spinning when + sink's upstream was done, but there was a non-zero but too small + amount of data left in the sink's input buffer. + +2005-07-18 Stephane Fillod + + * config/gr_libgnuradio_core_extra_ldflags.m4, + config/gr_no_undefined.m4, config/gr_python.m4: mods for MinGW. + +2005-07-17 Eric Blossom + + * src/lib/filter/gr_rational_resampler_base_XXX.{h,cc,i}: new. + + * src/python/gnuradio/blksimpl/rational_resampler.py + (rational_resampler_ccc.__init__): new. High-level wrapper for + gr.rational_resampler_base_??? + +2005-07-15 Eric Blossom + + * src/lib/filter/gr_fft_filter_ccc.cc, src/lib/filter/gr_fir_XXX.h.t, + src/lib/filter/gr_fir_ccc_simd.cc, src/lib/filter/gr_fir_ccc_simd.h, + src/lib/filter/gr_fir_ccf_simd.cc, src/lib/filter/gr_fir_ccf_simd.h, + src/lib/filter/gr_fir_fcc_simd.cc, src/lib/filter/gr_fir_fcc_simd.h, + src/lib/filter/gr_fir_fff_simd.cc, src/lib/filter/gr_fir_fsf_simd.cc, + src/lib/filter/gr_fir_scc_simd.cc, src/lib/filter/gr_fir_scc_simd.h, + src/lib/filter/gr_hilbert_fc.cc, src/lib/filter/gr_interp_fir_filter_XXX.cc.t, + src/lib/filter/gr_mmse_fir_interpolator.cc, src/lib/filter/qa_ccomplex_dotprod_x86.cc, + src/lib/filter/qa_gr_fir_ccc.cc, src/lib/filter/qa_gr_fir_ccf.cc, + src/lib/filter/qa_gr_fir_fcc.cc, src/lib/filter/qa_gr_fir_fff.cc, + src/lib/filter/qa_gr_fir_scc.cc, src/lib/general/Makefile.am, + src/lib/general/gr_firdes.cc, src/lib/general/gr_firdes.h, + src/lib/general/gr_firdes.i, src/python/gnuradio/gr/qa_filter_delay_fc.py, + src/python/gnuradio/gr/qa_interp_fir_filter.py: reversed order of + "taps" arguments constructors and set_taps, fixed taps() so it + returns the right order. We now require the "right" order for + taps, instead of the reversed order ("dot product order") we used to + require. + +2005-07-13 Martin Dvh + + * config/gr_check_createfilemapping.m4, + config/gr_libgnuradio_core_extra_ldflags.m4: new files + * configure.ac, config/Makefile.am, src/lib/Makefile.am: added + support for extra ld flags and future createfilemapping + factory. + * src/lib/io/gr_file_source.cc, src/lib/io/gr_file_sink.cc: + binary mode support under Windows. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/lib/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + + * src/python/gnuradio/gr/qa_complex_to_xxx.py: loosened up passing + threshold so that we pass on x86_64. + +2005-06-23 Eric Blossom + + * src/lib/runtime/gr_error_handler.cc: added #include + +2005-06-19 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + added diagnostic logging. Fixed problem where data was dribbling + through pipeline. + + * src/lib/general/gr_fxpt.cc: gcc 4.x fix. + +2005-06-16 Eric Blossom + + * src/lib/general/gr_nco.h: increase precision: float->double. + * src/lib/general/qa_gr_fxpt_nco.h: changed initial test frequency + +2005-06-16 Stephane Fillod + + * gnuradio-core.pc.in, src/lib/Makefile.am, src/lib/atsc/Makefile.am, + src/lib/filter/Makefile.am, src/lib/general/Makefile.am, + src/lib/runtime/Makefile.am, src/tests/Makefile.am: put qa code + in separate library. + +2005-06-12 Eric Blossom + + * src/python/gnuradio/blksimpl/filterbank.py: new. DFT filterbank. + * src/lib/general/gr_vector_to_streams.{h,cc,i}: new. + * src/lib/general/gr_streams_to_vector.{h,cc,i}: new. + * src/lib/general/gr_streams_to_stream.{h,cc,i}: new. Convert + streams of 1 item into a stream of N items. + * src/lib/general/gr_stream_to_streams.{h,cc,i}: new. Convert + a stream of N items into N streams of 1 items. + +2005-06-11 Eric Blossom + + * src/lib/general/gr_nlog10_ff.{h,cc,i}: added addition constructor arg, + k, that is added to the return value. Handy for normalizing FFTs. + + * src/lib/filter/gr_fft_filter_ccc.{h,cc,i}: new. FFT based FIR filtering. + +2005-06-10 Eric Blossom + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate), + src/python/gnuradio/gr/basic_flow_graph.py (downstream_verticies_port): + modified to take into account downstream block decimation ratio. + This allows us to compute big FFTs, FIRs with lots of taps, etc. + +2005-05-18 Eric Blossom + + * src/lib/runtime/gr_block.{h,cc,i}: new start/stop methods. These are + useful for minimizing latency due to startup overhead. + * src/lib/runtime/gr_single_threaded_scheduler.cc: call new methods. + +2005-05-18 John Gilmore + + * src/python/gnuradio/gruimpl/hexint.py: new. Convert hex + constants to negative ints for long ints >= 2**31. + +2005-05-11 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_sysv_shm.cc + (gr_vmcircbuf_sysv_shm): add read-only guard page on either side + of buffer. + + * src/lib/general/gr_throttle.{h,cc,i}: new block to rate-limit + samples. Mostly useful where there's nothing stopping us from + sucking down all CPU. E.g., reading from files, gr.sig_source, etc. + +2005-05-09 Stephane Fillod + + * src/lib/filter/fcomplex_dotprod_{3dnow,sse}.s, + src/lib/filter/fcomplex_dotprod_x86.h, + src/lib/filter/gr_fir_ccf_simd.{cc,h}, + src/lib/filter/gr_fir_ccf_x86.{cc,h}, + src/lib/filter/gr_fir_fcc_simd.{cc,h}, + src/lib/filter/gr_fir_fcc_x86.{cc,h}, + src/tests/benchmark_dotprod_ccf.cc, + src/tests/benchmark_dotprod_fsf.cc: new files + * src/lib/filter/Makefile.am, src/tests/Makefile.am, + src/lib/filter/gr_fir_sysconfig_x86.{cc,h}: support for FCC and + CCF filter speedup + * src/tests/benchmark_dotprod_{ccc,fcc,scc}.cc: copy/paste fixes + which should not change benchmark results + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + * src/lib/runtime/gr_error_handler.cc, src/lib/runtime/gr_local_sighandler.{h,cc}, + src/lib/runtime/gr_vmcircbuf.cc, src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc: + modifications for Cygin, MinGW + +2005-04-27 Eric Blossom + + * src/lib/general/gr_fake_channel_coder_pp.{h,cc,i}: new classes + the pretend to do channel encoding and decoding, but really only + add and strip padding... + + * src/lib/runtime/gr_buffer.cc (allocate_buffer): cleaned up formatting + on allocation warning message. + + * src/python/gnuradio/blksimpl/digital_voice.py: GSM vocoder + GMSK. + +2005-04-03 Eric Blossom + + * src/lib/io/gr_oscope_guts.cc (found_trigger): fixed trigger + problem where value was exactly equal to trigger value. + +2005-03-29 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk.py: new GMSK mod and demod + from Joshua Lackey + +2005-03-29 Ramakrishnan Muthukrishnan + + * src/lib/filter/gr_filter_delay_fc.{h,cc,i}, + src/python/gnuradio/gr/qa_filter_delay_fc.py: New block that + pairs a filter with a delay. + +2005-03-26 Eric Blossom + + * src/lib/runtime/gr_dispatcher.{h,cc,i}, + src/lib/runtime/gr_select_handler.{h,cc,i}: new. Framework for + callbacks based on select(2). + + * src/lib/runtime/gr_error_handler.{h,cc,i}: new. + +2005-03-14 Eric Blossom + + * src/lib/general/gr_complex_to_xxx.{h,cc,i}: now support + vector length argument, vlen. + * src/lib/general/gr_nlog10_ff.{h,cc,i}: new. + * src/lib/general/gr_parallel_to_serial.{h,cc,i}: new. + * src/lib/filter/gr_single_pole_iir_filter_ff.{h,cc,i}: new + * src/python/gnuradio/gr/qa_single_pole_iir.py: new + * src/python/gnuradio/gr/qa_nlog10.py: new + +2005-03-08 Eric Blossom + + * src/python/gnuradio/gr/qa_fsk_stuff.py: enabled simple_framer qa code. + * src/lib/general/gr_simple_framer.{h,cc}: added forecast method. + +2005-03-07 Eric Blossom + + * configure.ac: test for trunc and work around if missing. + +2005-03-02 Eric Blossom + + * src/python/gnuradio/blks/__init__.py, src/python/gnuradio/blksimpl/__init__.py, + src/python/gnuradio/gru/__init__.py, + src/python/gnuradio/gruimpl/__init__.py: refactored organization + so that hierarchical blocks are physically contained in the + blkimpl directory, but that for convenience in naming, all blocks + appear in the gnuradio.blks package. Same story for gruimpl vs gru. + + Rearranged a bunch of stuff under src/python. CVS sucks! + +2005-02-28 Eric Blossom + + * src/lib/general/gr_frequency_modulator_fc.cc (work): fixed + floating point loss of precision. + * src/lib/general/gr_simple_correlator.cc (general_work): fixed + bug that had it processing only a single sample at a time. + +2005-02-25 Matt Ettus + + * lib/general/Makefile.am, lib/general/general.i, + lib/general/gr_rms_[ff,cf].[cc,h,i]: new rms measuring block + +2005-02-25 Eric Blossom + + * python/gnuradio/gr/qa_mute.py, lib/general/gr_mute_XX.cc.t, + lib/general/gr_mute_XX.h.t, lib/general/gr_mute_XX.i.t: new block. + * lib/general/Makefile.am, lib/general/Makefile.gen, + lib/general/general_generated.i, lib/general/generate_common.py: + mods to generate new block. + +2005-02-23 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py: new. support for + hierarchical signal processing blocks. + * src/python/gnuradio/gr/basic_flow_graph.py, + src/python/gnuradio/gr/qa_basic_flow_graph.py: modified to support + hierarchical signal processing blocks. + +2005-02-22 Eric Blossom + + * src/lib/general/gr_simple_squelch_cc.{h,cc,i}: new. + + * src/lib/runtime/gr_message.{h,cc,i}, + src/lib/runtime/gr_msg_handler.{h,cc,i}, + src/lib/runtime/gr_msg_queue.{h,cc,i}, + src/lib/runtime/gr_timer.h: new. work-in-progress. + +2005-02-09 Eric Blossom + + * src/lib/io/gr_file_descriptor_source.{h,cc}(work): reworked to + return as soon as any data is available. This make it much more + friendly for reading sockets, named pipes, etc. + +2005-02-07 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py (coerce_endpoint): + fix exception message. + +2005-02-06 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py + (basic_flow_graph.connect): connect now takes >= 2 args, per + Thomas Traber's suggestion. + * src/python/gnuradio/gr/qa_flow_graph.py, + src/python/gnuradio/gr/qa_basic_flow_grapy.py: additional test code. + +2005-02-05 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py + (basic_flow_graph.connect): removed unnecessary None + +2005-02-02 Chuck Swiger + + * src/lib/io/gr_file_source.{h,cc,i}: added seek method. + +2005-01-29 Eric Blossom + + * src/lib/runtime/gr_io_signature.i: mods for SWIG 1.3.24 + +2005-01-24 Eric Blossom + + * src/python/gnuradio/freqz.py (freqz): New. Compute frequency + response of filter. + * src/python/gnuradio/gnuplot_freqz.py: New. Plot output of freqz. + +2005-01-17 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + Make better initial estimate of noutput_items when current block + is a decimator. Removed old diagnostic code. + + * src/lib/general/gr_vector_source_X.cc.t (work): reorganized the + repeat case so that we always return the number of items requested. + This fixes the excessive latency we were seeing in + spectrum_inversion.py + + * src/python/gnuradio/gr/flow_graph.py: Set noutputs correctly. + * src/python/gnuradio/gr/qa_flow_graph.py: Test value of noutputs. + +2005-01-16 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + check for situation where block is requesting more input data than + we will ever provide. + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate): + set minimum buffersize to 2 * output_multiple() + + * src/lib/runtime/gr_buffer.cc (space_available): fixed degenerate + case to be consistent with normal case. + +2005-01-01 Eric Blossom + + * src/lib/io/sdr_1000.i (class sdr_1000_base): removed default arg + to work around SWIG 1.3.23 bug. + +2004-12-22 Eric Blossom + + * src/lib/general/qa_gr_fxpt.cc (t0): disabled float_to_fixed test + to avoid spurious failures. + +2004-12-21 Eric Blossom + + * src/lib/general/gr_fxpt.h (class gr_fxpt): added explicit float cast. + * src/lib/general/Makefile.am (grinclude_HEADERS): added gr_fxpt_nco.h + +2004-12-18 Eric Blossom + + * src/lib/general/gr_fxpt.{h,cc},src/lib/general/gr_fxpt_nco.{h,cc}, + src/lib/general/qa_gr_fxpt.{h,cc},src/lib/general/qa_gr_fxpt_nco.{h,cc}, + src/tests/benchmark_nco.cc: new. Faster sine and cosine + calculation. Uses table lookup with linear interpolation. This + is about 3x faster than the original code. + +2004-12-17 Eric Blossom + + * src/lib/general/Makefile.am (swiginclude_HEADERS): fixed typo. + * src/lib/general/gr_deinterleave.{h,cc,i}: new. + +2004-12-11 Eric Blossom + + * src/lib/general/gr_interleave.{h,cc,i}: new. + +2004-12-10 Eric Blossom + + * src/python/gnuradio/eng_option.py (check_intx): now parses hex + numbers too. + +2004-12-09 Eric Blossom + + * src/lib/filter/Makefile.am: fixed problem with gr_hilbert_fc on + OS/X (it was in the wrong place in the makefile). Now builds and + checks on OS/X. + +2004-12-06 Ramakrishnan Muthukrishnan + + * src/lib/filter/Makefile.am, src/lib/general/Makefile.am, + src/python/gnuradio/Makefile.am, + src/python/gnuradio/gr/Makefile.am: added *.pyc to CLEANFILES + +2004-11-30 Eric Blossom + + * src/python/gnuradio/gr/Makefile.am, configure.ac: modified to + no longer require run_test_trampoline. Now uses AC_CONFIG_COMMANDS to + set execute bit on run_tests. + * src/python/gnuradio/gr/run_test_trampoline: removed. + + * src/lib/filter/Makefile.am (swiginclude_HEADERS): fix typo in gr_hilbert_fc.i + +2004-11-27 Eric Blossom + + * src/python/gnuradio/gr/qa_hilbert.py: new + * src/lib/general/gr_firdes.i: moved from filter to general. + * src/lib/general/gr_firdes.{h,cc}: new method: reverse. + * src/lib/filter/gr_hilbert_fc.i: new. + * src/lib/filter/gr_hilbert_fc.cc: ensure ntaps is odd. + +2004-11-08 Stephane Fillod + + * src/lib/filter/Makefile.am, src/tests/Makefile.am, + src/lib/filter/complex_dotprod_generic.cc, + src/lib/filter/gr_fir_sysconfig_x86.{cc,h}, + src/lib/filter/qa_dotprod_x86.cc, src/lib/filter/qa_filter.cc: + added support for x86 SIMD CCC dotproduct. + * src/lib/filter/ccomplex_dotprod_3dnow.s, + src/lib/filter/ccomplex_dotprod_3dnowext.s, + src/lib/filter/ccomplex_dotprod_generic.{cc,h}, + src/lib/filter/ccomplex_dotprod_sse.s, + src/lib/filter/ccomplex_dotprod_x86.h, + src/lib/filter/gr_fir_ccc_simd.{cc,h}, + src/lib/filter/gr_fir_ccc_x86.{cc,h}, + src/lib/filter/qa_ccomplex_dotprod_x86.{cc,h}, + src/lib/filter/qa_gr_fir_ccc.{cc,h}, + src/tests/benchmark_dotprod.cc, + src/tests/benchmark_dotprod_{ccc,fcc,scc}.cc: new + +2004-11-08 Eric Blossom + + * src/lib/runtime/gr_block.h: new methods: set_input_signature and + set_output_signature. + +2004-11-04 Eric Blossom + + * configure.ac: upped version to 2.3cvs + + * configure.ac: set version to 2.3. Made release. + * src/python/gnuradio/audio.py (__init__): raise error if no audio + module found. + +2004-11-02 Eric Blossom + + * src/lib/runtime/gr_local_sighandler.cc (name): conditionalized + based on signal names. + +2004-10-30 Eric Blossom + + * src/lib/runtime/gr_local_sighandler.{h,cc}: new. get and set + signal handlers. + * src/lib/runtime/gr_vmcircbuf.cc (test_factory): install handlers + for SIGBUS and SIGSEGV while running tests. + +2004-10-18 Stephane Fillod + + * config/gr_pwin32.m4, src/lib/runtime/gr_preferences.cc: proper + detect Sleep() support, check for mkdir that takes only one arg + under win32. + * src/lib/runtime/gr_io_signature.cc, + src/lib/runtime/gr_io_signature.h, + src/lib/runtime/gr_io_signature.i, + src/lib/runtime/qa_gr_io_signature.cc: resolve a clash with + INFINITE already defined. + * src/lib/runtime/gr_pagesize.cc: declare missing prototype of + getpagesize() under win32. + +2004-10-18 Eric Blossom + + * src/python/gnuradio/gr/run_tests.in: allow VPATH building. + +2004-10-18 Stephane Fillod + + * configure.ac, src/lib/filter/Makefile.am, + src/lib/general/Makefile.am: allow VPATH building. + +2004-10-17 Eric Blossom + + * doc/Makefile.am (install-data-local): install html documentation. + * src/lib/filter/gr_iir_filter_ffd.cc (gr_iir_filter_ffd): removed + debug message. + * src/python/gnuradio/gr/run_tests.in: changed == to = for POSIX + compatibility. + * src/python/gnuradio/gr/qa_basic_flow_graph.py: use /usr/bin/env + to find python. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 2.2cvs + +2004-10-11 Eric Blossom + + * configure.ac: bumped rev to 2.2, make release + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-10-07 Eric Blossom + + * src/python/gnuradio/lmx2306.py: now works! + +2004-09-29 Eric Blossom + + * src/lib/filter/gri_iir.h: renamed from gr_iir.h. Also, changed + the sign back. We're consistent with Oppenheim and Schafer, + "Discrete-Time Signal Processing." Documented exactly what we + compute. Faster delay line implementation. + * src/lib/filter/gr_iir_filter_ffd.{h,cc,i}: new direct form IIR block. + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-09-22 Eric Blossom + + * src/lib/io/gr_file_descriptor_sink.cc: added missing #include + * src/lib/io/gr_file_descriptor_source.cc: added missing #include + +2004-09-21 Matthew Hall + + * src/gnu/lib/gr/gr_iir.h: rewrote ctor docs. Fixed sign error + in filter method. Now gr_iir uses Direct Form I of IIR. + +2004-09-19 Eric Blossom + + * src/lib/general/gr_complex_to_xxx.{h,cc,i}: new blocks. + * src/python/gnuradio/gr/qa_complex_xxx.py: new qa code. + + * src/lib/general/gr_simple_correlator.{h,cc,i}: payload size is + now in bytes, not bits. + * src/lib/general/gr_simple_framer.{h,cc,i}: payload size is + now in bytes, not bits. + + * src/lib/swig/Makefile.am: now tracks swig .i file dependencies. + * src/lib/swig/gnuradio.i: simplification and cleanup. + +2004-09-18 Eric Blossom + + These modifications happened sometime between 2004-09-08 and 2004-09-18. + The details are lost in the swirl around preparing the TAPR DCC. + + * src/lib/filter/gr_interp_fir_filter_XXX.{h,cc,i}.t: new + * src/lib/filter/generate_gr_interp_fir_filter_XXX.py: new + * src/lib/filter/generate_all.py: modified for to generate interpolating fir filter + * src/lib/general/gr_bytes_to_syms.{h,cc,i}: new + * src/lib/general/gr_frequency_modulator_fc.{h,cc,i}: new + * src/lib/general/gr_simple_framer.{h,cc,i}: new + * src/lib/general/gr_simple_framer_sync.h: new + * src/lib/general/gr_simple_correlator.{h,cc,i}: new + * src/lib/io/gr_oscope_guts.{h,cc}: new + * src/lib/io/gr_oscope_sink_{f,x}.{h,cc}: new + * src/lib/io/gr_trigger_mode.h: new + * src/lib/io/ppio.i: new + + The following changes are related to moving from SWIG 1.3.21 to 1.3.22 + + * src/lib/runtime/gr_block_detail.i: removed unneccesary global decl of friend. + * src/lib/runtime/gr_buffer.i: removed unneccesary global decl of friend. + * src/lib/runtime/gr_io_signature.i: removed unneccesary global decl of friend. + * src/lib/runtime/gr_single_threaded_scheduler.i: removed unneccesary global decl of friend. + * src/lib/swig/gnuradio.i: mods for improved STL support + + * src/lib/runtime/gr_types.h: new typedefs + * src/lib/swig/gen-swig-bug-fix: new. generate gnuradio_swig_bug_workaround.h + + * src/python/gnuradio/eng_notation.py: new + * src/python/gnuradio/grutil.py: new + * src/python/gnuradio/gr_unittest.py: new subclass of unittest + * src/python/gnuradio/lmx2306.py: new. Control National PLL synthesizer + * src/python/gnuradio/microtune.py: new. Command line interface + to microtune boards. + * src/python/gnuradio/gr/qa_frequency_modulator.py: new + * src/python/gnuradio/gr/qa_fsk_stuff.py: new + * src/python/gnuradio/gr/qa_head.py: new + * src/python/gnuradio/gr/qa_interp_fir_filter.py: new + * src/python/gnuradio/gr/qa_sig_source.py: new + +2004-09-08 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py + (basic_flow_graph.validate): now calls check_topology. + * src/lib/runtime/gr_block.{h,cc,i} (check_topology): new method. + + * src/lib/general/gr_short_to_float.{h,cc,i}: new + * src/lib/general/gr_float_to_short.{h,cc,i}: new + +2004-08-26 Eric Blossom + + * src/lib/general/gr_fft_vfc.{h,cc,i}: new + * src/lib/general/gr_fft_vcc.{h,cc,i}: new + * src/lib/general/gri_fft.{h,cc}: renamed from gr_fft.{h,cc} + * src/lib/general/gr_serial_to_parallel.{h,cc,i}: new + * src/lib/general/gr_keep_one_in_n.{h,cc,i}: new + +2004-08-25 Eric Blossom + + * src/lib/io/gr_file_descriptor_source.{h,cc,i}: new + * src/lib/io/gr_file_descriptor_sink.{h,cc,i}: new + +2004-08-19 Eric Blossom + + * src/lib/general/gr_sig_source_X.cc.t (work): performance tweak + for constant case. + + * src/python/gnuradio/eng_option.py (check_eng_float): support + engineering notation in option parsing. E.g., 32k, 106.5M + +2004-08-18 Eric Blossom + + * src/python/gnuradio/gr/scheduler.py, + src/python/gnuradio/gr/basic_flow_graph.py, + src/python/gnuradio/gr/flow_graph.py, + src/python/gnuradio/gr/qa_flowgraph.py: modified to partition + graphs and assign separate threads to each disjoint set of + verticies. + + +2004-08-05 Eric Blossom + + * src/lib/general/gr_lfsr_32k_source_s.{h,cc,i}: new. + + * src/lib/general/gr_check_counting_s.{h,cc,i}: renamed from gr_counting_sink. + * src/lib/general/gri_lfsr_15_1_0.h: new LFSR generator with + period 32K-1 bits. + * src/lib/general/gri_lfsr_32k.h: new LFSR generator with period + 32K bits. + * src/lib/general/gr_counting_sink_s.{h,cc,i}: new. checks that + it's input is a counting sequence. + * src/lib/filter/Makefile.am: added missing .t files + +2004-07-31 Eric Blossom + + * src/lib/general/gr_vector_source_X.{h,cc,i}.t: added repeat + argument to constructor. + +2004-07-30 Eric Blossom + + * src/lib/general/gr_sig_source_X.cc.t (work): now use gr_sincos + to compute both at same time. + + * src/lib/general/gr_nco.h (gr_nco): renamed method cossin -> sincos + and use gr_sincos to compute value. + + * configure.ac: upped rev to 2.1cvs. + +2004-07-21 Eric Blossom + + * configure.ac: upped rev to 2.1. Made release. + +2004-07-20 Eric Blossom + + * src/python/gnuradio/optfir.py: new. High level routines for optimal FIR design. + * src/lib/general/gr_remez.{h,cc}: new. Parks-McClellan method + for optimal FIR design. + +2004-07-19 Eric Blossom + + * src/lib/general/gri_add_const_ss_generic.cc: new. + * src/lib/general/gri_add_const_ss.h: new. + +2004-07-17 Eric Blossom + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate): + take into account output_multiple when computing buffer size. + + * src/lib/runtime/gr_block.i: added output_multiple and + relative_rate to swig interface. + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 2.0cvs + + * src/python/gnuradio/sdr_1000.py: added back in. + * src/lib/io/sdr_1000.{h,cc}: added back in. + +2004-07-11 Eric Blossom + + * config/gr_boost.m4 (GR_REQUIRE_BOOST_INCLUDES): new m4 macro. + +2004-07-09 Eric Blossom + + * src/lib/audio-oss: removed all files and moved to gr-audio-oss package. + +2004-07-04 Eric Blossom + + * src/lib/general/gr_{add,sub,multiply,divide}_XX.{h,i,cc}.t: new + * src/lib/general/gr_multiply_const_XX.{h,i,cc}.t: new + * src/lib/runtime/gr_block.{h,cc} (class gr_block): renamed + basic_work method to general_work + * src/lib/general/gr_sync_block.{h,cc} (class gr_sync_block): + renamed sync_work method to work. + +2004-07-03 Eric Blossom + + * src/python/gnuradio/gr/scheduler.py: new. Now run graph in + separate thread. + * src/lib/runtime/gr_single_threaded_scheduler.{h,i,cc}: added + stop method. + * src/lib/general/gr_noise_source_X.{h,i,cc}.t: new random noise source. + * config/gr_swig.m4: fail, not warn, if the right version isn't found. + * src/lib/general/gr_random.{h,cc}: moved implementation specific + defines out of header and into implementation. Also moved statics + into class and cleaned up a couple of other annoyances. + +2004-07-01 Eric Blossom + + * src/python/gnuradio/gr/run_tests.in: new. Sets PYTHONPATH + for sucessful testing in build tree; runs all tests. + * src/lib/runtime/{gr_block.i,gr_swig_block_magic.i}: revised to + use lambda expression for repr printing instead of referencing global. + * src/lib/swig/Makefile.am: now generate standalone swig runtime + library that all other swig modules link against. + +2004-06-21 Eric Blossom + + Cleaned up interface to microtune modules and eval boards. + Now uses boost::shared_ptr's. Refactored all uses 4937 and 4702, + and corresponding eval board classes. + + * src/lib/io/i2c.{h,cc}: split into i2c.{h,cc} and i2c_bitbang.{h,cc} + * src/lib/io/eval_board_4702_defs.h: deleted. + * src/lib/io/i2cio.{h,cc}: renamed to i2c_bbio.{h,cc} + * src/lib/io/i2cio_pp.{h,cc}: renamed to i2c_bbio_pp.{h,cc} + +2004-06-13 Eric Blossom + + * src/lib/general/gr_quadrature_demod_cf.{i,h,cc}: new. + + * src/lib/audio-oss/gr_audio_sink_oss.{i,h,cc}: new. + FIXME: should be moved into a different build tree to decouple oss + dependency. + + * src/lib/io/gr_file_{sink,source}.{i,h,cc} io.i: new. + +2004-06-12 Eric Blossom + + * src/lib/general/gr_sig_source_X.{h,cc,i}.t: new + * src/lib/general/gr_sig_source_waveform.h: new + * src/lib/general/gr_head.{h,cc,i}: new + + * src/lib/runtime/gr_block_detail.cc (set_done), gr_buffer.h: + propagate "done" upstream + + +2004-XX-XX Eric Blossom + + Months of changes... This was whatever it took to get + the beginning of the new code base working... + +2004-03-11 Eric Blossom + + * src/lib/runtime/io_signature.{h,cc}, + * src/lib/runtime/qa_io_signature.{h,cc}: new. + +2004-03-08 Eric Blossom + + Removed cppunit from our build tree and updated qa code to work + with cppunit-1.9.12 + + * Makefile.am + * bootstrap + * configure.ac + * config/Makefile.am + * config/cppunit.m4 + * src/lib/Makefile.am + * src/lib/atsc/convolutional_interleaver.h + * src/lib/atsc/qa_atsc_basic_trellis_encoder.cc + * src/lib/atsc/qa_atsc_data_interleaver.cc + * src/lib/atsc/qa_atsc_equalizer_nop.cc + * src/lib/atsc/qa_atsc_fake_single_viterbi.cc + * src/lib/atsc/qa_atsc_fs_correlator.cc + * src/lib/atsc/qa_atsc_randomizer.cc + * src/lib/atsc/qa_atsc_reed_solomon.cc + * src/lib/atsc/qa_atsc_single_viterbi.cc + * src/lib/atsc/qa_atsc_trellis_encoder.cc + * src/lib/atsc/qa_atsc_viterbi_decoder.cc + * src/lib/atsc/qa_convolutional_interleaver.cc + * src/lib/atsc/qa_interleaver_fifo.cc + * src/lib/filter/qa_complex_dotprod_x86.cc + * src/lib/filter/qa_float_dotprod_x86.cc + * src/lib/filter/qa_gr_fir_CCF.cc + * src/lib/filter/qa_gr_fir_FCC.cc + * src/lib/filter/qa_gr_fir_FFF.cc + * src/lib/filter/qa_gr_fir_SCC.cc + * src/lib/filter/qa_gr_mmse_fir_interpolator.cc + * src/lib/filter/qa_sse_float_dotprod.cc + * src/lib/general/qa_gr_circular_file.cc + * src/lib/general/qa_gr_firdes.cc + * src/lib/general/old/qa_gr_fir_SSS.cc + * src/lib/general/old/qa_gr_fir_sse.cc + * src/lib/runtime/qa_gr_vmcircbuf.cc + * src/lib/vrx/VrComplex.h + * src/tests/GrTestSink.cc + * src/tests/GrTestSkippingSink.cc + * src/tests/GrTestSource.cc + + + +This code was derived from gnuradio-0.9 with a massive amount of hacking. + +# +# Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gnuradio-core/Makefile.am b/gnuradio-core/Makefile.am new file mode 100644 index 00000000..b4b619b8 --- /dev/null +++ b/gnuradio-core/Makefile.am @@ -0,0 +1,36 @@ +# +# Copyright 2001,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + gnuradio-core.conf \ + gnuradio-core.pc.in \ + README.hacking \ + README-win32-mingw-short.txt + +SUBDIRS = src doc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gnuradio-core.pc + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gnuradio-core.conf diff --git a/gnuradio-core/NEWS b/gnuradio-core/NEWS new file mode 100644 index 00000000..bd9ab537 --- /dev/null +++ b/gnuradio-core/NEWS @@ -0,0 +1,35 @@ +GNU Radio -- History of visible changes. + +Copyright (C) 2001, Free Software Foundation, Inc. +See the end for copying conditions. + +Please send GNU Radio bug reports to bug-gnuradio@fsf.org + +Version 0.2 + +* This the first "real release" + + +Version 0.1 + +* We're working toward the first alpha distribution + +* The build strategy is in the processes of being converted to use + automake. It is mostly complete, but there are still some untested directories + which still contain Makefile.in's + +------------------------------------------------------- +Copying information: + +Copyright (C) 2001, Free Software Foundation, Inc. + + Permission is granted to anyone to make or distribute verbatim copies + of this document as received, in any medium, provided that the + copyright notice and this permission notice are preserved, + thus giving the recipient permission to redistribute in turn. + + Permission is granted to distribute modified versions + of this document, or of portions of it, + under the above conditions, provided also that they + carry prominent notices stating who last changed them. + diff --git a/gnuradio-core/README b/gnuradio-core/README new file mode 100644 index 00000000..dfc0ac8d --- /dev/null +++ b/gnuradio-core/README @@ -0,0 +1,190 @@ +# +# Copyright 2001,2002,2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +------------------------------------------------------------------------------- + + IMPORTANT + +------------------------------------------------------------------------------- + +GNU Radio is now broken up into several packages. You're looking at +the gnuradio-core. You'll probably want some or all of these too. +Build and install them in the order listed here: + + gnuradio-core # main library + gnuradio-examples # examples + gr-audio-alsa # support for sounds cards using ALSA (prefered under GNU/Linux) + gr-audio-oss # support for sounds cards using OSS + gr-audio-jack # support for JACK Audio Connection Kit + gr-audio-windows # support for sounds cards using Windows Wave + gr-comedi # support for DAQ cards using COMEDI + gr-wxgui # GUI framework built on wxPython + usrp # non-GNU Radio specific portion of usrp + gr-usrp # glues usrp into GNU Radio + mc4020 # GNU/Linux driver for Measurement Computing PCI-DAS4020/12 A/D board + gr-mc4020 # the glue that ties the mc4020 driver into GNU Radio + + +------------------------------------------------------------------------------- + + KNOWN INCOMPATIBILITIES + + + GNU Radio triggers bugs in g++ 3.3 for X86. DO NOT USE GCC 3.3. + gcc 3.2 and 3.4 are known to work well. + +------------------------------------------------------------------------------- + +Prerequisites (you may already have these): + +(1) 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. + + +(2) 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. + + +(3) Python 2.3 or later http://www.python.org + +Python 2.3 or later is now required. If your distribution splits +python into a bunch of separate RPMS including python-devel or +libpython you'll most likely need those too. + + +(4) Numeric python library http://numeric.scipy.org + +Provides a high performance array type for Python. + + +(5) The Boost C++ Libraries http://www.boost.org + +We use the Smart Pointer library. Fedore Core 2 has a package for +this, boost-devel-1.31.0-7. Otherwise download the source and follow +the build instructions. They're a bit different from the normal +./configure && make + + +(6) cppunit 1.9.14 or later. http://cppunit.sourceforge.net + +Unit testing framework for C++. + + +(7) Simple Wrapper Interface Generator. http://www.swig.org + +These versions are known to work: + 1.3.23, 1.3.24, 1.3.25, 1.3.27, 1.3.28, 1.3.29 + +---------------------------------------------------------------- + +For the impatient, just do the following: + + $ ./configure + $ make + $ make check + $ make install + +If it doesn't work, fix it and send us a patch... + + +See http://www.gnu.org/software/gnuradio/ for an overview. +The project is hosted at http://savannah.gnu.org/projects/gnuradio/ + + +If you've got doxygen installed and provide the --enable-doxygen +configure option, the build process creates documentation for the +class hierarchy etc. Point your browser at +gnuradio-core/doc/html/index.html + + +To run the examples you'll need to set PYTHONPATH. +Note that the python version number in the path needs to match your +installed version of python. + + $ export PYTHONPATH=/usr/local/lib/python2.3/site-packages + +You may want to add this to your ~/.bash_profile + + + +---------------------------------------------------------------- + + Notes on building GNU Radio from the CVS repository + +---------------------------------------------------------------- + +If you're building from the CVS repository YOU MUST BE PLAYING BY THE +RULES THAT THE OTHER DEVELOPERS ARE USING. This is especially true +with regard to the versions of the tools below... + +Ensure that you've got THESE VERSIONS of the following tools: + + autoconf 2.57 or later + automake 1.7.4 or later + libtool 1.5 or later + swig 1.3.{23,24,25,27,28,29} + +If you're using earlier versions than these, don't expect the system +to build. Get these versions or something later. They're available +at any of the GNU mirrors. + +Then, check out a copy of GNU Radio. + +See http://www.gnu.org/software/gnuradio for directions on anonymous +access to the CVS repository. + +Then in the top level directory, execute + + $ ./bootstrap + +This builds configure from configure.ac and also builds all the +Makefile.in's from the Makefile.am's. + +Then carry on as usual: + + $ ./configure + $ make + $ make check + $ make install + + +For the easiest way to build from CVS, see +http://comsec.com/wiki?HowtoBuildFromCVS + + + +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: + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/local/lib + $ make CPPFLAGS="-I$HOME/local/include" + diff --git a/gnuradio-core/README-win32-mingw-short.txt b/gnuradio-core/README-win32-mingw-short.txt new file mode 100644 index 00000000..88338e3b --- /dev/null +++ b/gnuradio-core/README-win32-mingw-short.txt @@ -0,0 +1,92 @@ +Building and using gnuradio on windows (win32) using mingw + +Required tools and libraries + +MingW and Msys +Download the latest stable version from the mingw site oand follow their installation instructions) + +Python for windows version 2.4 (or higher) +You do not need to build this yourself. +You can just install the windows executable which you can find on the python site. +I am not sure if it will work if you have speces in your python pathname. +I recommend installing it in C:\Python24 or D:\Python24 + +Libtool +If you are building from cvs you need a recent libtool +msys comes with libtool, but the version distributed with current mingw doesn't work with gnuradio. +download, build and install a recent libtool + +cppunit +Build and install cppunit + +boost +build and install boost (maybe you can get away with only unpacking the source, we only use the boost header files) +If you build boost, you first have to download jam (boost jam) for win32. (Do not use build and use the cygwin version) + +build environment: +You need to have the following files on your PATH: +python.exe python24.dll libcppunit-1-10-2.dll libfftw3f-3.dll fftwf-wisdom.exe cppunit-config +If you have cygwin installed Make sure that NO cygwin executables are on your path. + +needed on PATH: +/usr/local/bin +/mingw/bin +/bin +/c/Python24/ python.exe +/c/Python24/libs python24.dll +/c/Python24/DLLs +/usr/local/bin or /mingw/bin or /my/special/installed/lib/folder/bin + libcppunit-1-10-2.dll + libfftw3f-3.dll + fftw-wisdom-to-conf + fftwf-wisdom.exe + cppunit-config +/c/WINNT/system32 +/c/WINNT + + +I made a little script set_clean_path.sh to set my path for building gnuradio where I just discard the original PATH (to get rid of the cygwin executables on my default path) and just include what is needed: + +#!/bin/sh +export PATH=".:/usr/local/bin:/mingw/bin:/bin:/c/Python24:/c/Python24/DLLs:/c/Python24/libs:/my/special/installed/lib/folder/bin:/c/WINNT/system32:/c/WINNT:/c/WINNT/System32/Wbem:. + +You need to source this script to set the PATH. +. ./set_clean_path.sh +(notice the extra dot and space in the beginning of the line, this means source this file. Sourcing means execute it and remember all environment variables set in this script) + +If you are building from cvs it is recommended that you edit bootstrap to your needs and use it +If you built a recent libtool and didn't overwrite the original libtool +(because you installed the new version in /usr/local) then you have to tell aclocal to use the more recent libtool m4 macros. +You can do this by appending -I /usr/local/share/aclocal to the aclocal commandline +I also changed the aclocal and automake invocations to use the most recent version in my bootstrap script +Here follows the bootstrap script I use + +#!/bin/sh +rm -fr config.cache autom4te*.cache + +aclocal-1.8 -I config -I /usr/local/share/aclocal +autoconf +autoheader +libtoolize --automake +automake-1.8 --add-missing + +If you run this script it will convert a clean cvs checkout to a version which you can configure, build and install + +So now you can configure gnuradio. +On win32 /mingw you need to give it a few parameters +You need to tell it where cppunit is installed +where boost include files are to be found +where the pkg-config of libfftw is to be found +to use a generic cpu (no 3Dnow,SSE,MMX) (This option will not be needed anymore soon) +If you have boost installed in C:\boost_1_32_0 and cppunit and fftw in /usr/local then you would need the following configur commandline +$ ./configure --with-md-cpu=generic --with-cppunit-prefix=/usr/local --with-boost-include-dir=/c/boost_1_32_0/include/boost-1_32 PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + +If everything went well you cannow do +make +make install + +Now you have a working gnuradio-core +Now you can go on building and installing gr-audio-windows and windows usrp and wxgui +remember that all gnuradio and python dlls need to be on your path to use gnuradio +The gnuradio dlls are installed at +/c/Python24/Lib/site-packages:/c/Python24/Lib/site-packages/gnuradio:/c/Python24/Lib/site-packages/gnuradio/gr diff --git a/gnuradio-core/README.hacking b/gnuradio-core/README.hacking new file mode 100644 index 00000000..7e211e0b --- /dev/null +++ b/gnuradio-core/README.hacking @@ -0,0 +1,178 @@ +# -*- Outline -*- +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +Random notes on coding conventions, some explanations about why things +aren't done differently, etc, etc, + + +* C++ and Python + +GNU Radio is now a hybrid system. Some parts of the system are built +in C++ and some of it in Python. In general, prefer Python to C++. +Signal processing primitives are still built in C++ for performance. + +It is no longer possible to build user applications entirely in C++. +Essential parts of the runtime system have been moved into Python. + + +* C++ namespaces + +In the cleanup process, I considered putting everything in the +gnuradio namespace and dropping the Gr|gr prefix. In fact, I think +it's probably the right idea, but when I tested it out, I ran into +problems with SWIG's handling of namespaces. Bottom line, SWIG +(1.3.21) got confused and generated bad code when I started playing +around with namespaces in a not particularly convoluted way. I saw +problems using the boost::shared_ptr template in combination with +classes defined in the gnuradio namespace. It wasn't pretty... + + +* Naming conventions + +Death to CamelCaseNames! We've returned to a kinder, gentler era. +We're now using the "STL style" naming convention with a couple of +modifications since we're not using namespaces. + +With the exception of macros and other constant values, all +identifiers shall be lower case with words_separated_like_this. + +Macros and constant values (e.g., enumerated values, +static const int FOO = 23) shall be in UPPER_CASE. + + +** Global names + +All globally visible names (types, functions, variables, consts, etc) +shall begin with a "package prefix", followed by an '_'. The bulk of +the code in GNU Radio logically belongs to the "gr" package, hence +names look like gr_open_file (...). + +Large coherent bodies of code may use other package prefixes, but +let's try to keep them to a well thought out list. See the list +below. + +*** Package prefixes + +These are the current package prefixes: + + gr_ Almost everything + + gri_ Implementation primitives. Sometimes we + have both a gr_ and a gri_. In that case, + gr_ would be derived from gr_block and gri_ + would be the low level guts of the function. + + atsc_ Code related to the Advanced Television + Standards Committee HDTV implementation + + usrp_ Universal Software Radio Peripheral + + qa_ Quality Assurance. Test code. + + +** Class data members (instance variables) + +All class data members shall begin with d_. + +The big win is when you're staring at a block of code it's obvious +which of the things being assigned to persist outside of the block. +This also keeps you from having to be creative with parameter names +for methods and constructors. You just use the same name as the +instance variable, without the d_. + +class gr_wonderfulness { + std::string d_name; + double d_wonderfulness_factor; + +public: + gr_wonderfulness (std::string name, double wonderfulness_factor) + : d_name (name), d_wonderfulness_factor (wonderfulness_factor) + { + ... + } + ... +}; + + +** Class static data members (class variables) + +All class static data members shall begin with s_. + + +** File names + +Each significant class shall be contained in it's own file. The +declaration of class gr_foo shall be in gr_foo.h, the definition in +gr_foo.cc. + + + +* Storage management + +Strongly consider using the boost smart pointer templates, scoped_ptr +and shared_ptr. scoped_ptr should be used for locals that contain +pointers to objects that we need to delete when we exit the current +scope. shared_ptr implements transparent reference counting and is a +major win. You never have to worry about calling delete. The right +thing happens. + +See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + + +* Unit tests + +Build unit tests for everything non-trivial and run them after every +change. Check out Extreme Programming: +http://c2.com/cgi/wiki?ExtremeProgrammingRoadmap + +Unit tests should also be written for all examples. This should kill +off the bit rot we've been plagued with. + +** C++ unit tests + +For C++ we're using the cppunit framework. cppunit has its bad +smells, but it's mostly workable. http://cppunit.sf.net + +Currently each directory contains files qa_.{h,cc} +that bring together all the qa_ test suites in the directory. +We ought to be able to automate this without too much trouble. + +The directory gnuradio-core/src/tests contains programs that run +the tests. test_all runs all of the registered C++ unit tests. + +As far as I can tell, the cppunit TestFactoryRegistry maybe able to be +tricked into doing what we want. As is, I don't think it's enough by +itself, since there's nothing dragging the qa* files out of the +library and into the program. I haven't tested out this idea. + +** Python unit tests + +We use the standard unittest package for unit testing of Python code. + + +* Misc tips + +ccache, a compiler cache, can really speed up your builds. +See http://ccache.samba.org/ + +Be sure to create links for gcc and g++ diff --git a/gnuradio-core/THANKS b/gnuradio-core/THANKS new file mode 100644 index 00000000..00e44886 --- /dev/null +++ b/gnuradio-core/THANKS @@ -0,0 +1,7 @@ +GNU Radio THANKS file + +GNU Radio has originally been written by Free Software Foundation, Inc. +Many people have further contributed to GNU Radio by reporting problems, +suggesting various improvements, or submitting actual code. Here is +a list of these people. Help me keep it complete and exempt of errors. + diff --git a/gnuradio-core/TODO b/gnuradio-core/TODO new file mode 100644 index 00000000..f9521c29 --- /dev/null +++ b/gnuradio-core/TODO @@ -0,0 +1,14 @@ +Have configure check for correct version of SWIG. +gr_swig checks, but doesn't set any variable that can be checked +afterwards. + +Failure to find SWIG should disable build of scripting directory + + +Have configure search for FFTW includes and libraries (use pkg-config +to find them) + +Come up with a consistent naming strategy and implement it! + +make o'scope display fast enough + diff --git a/gnuradio-core/doc/Doxyfile.in b/gnuradio-core/doc/Doxyfile.in new file mode 100644 index 00000000..7283a7b2 --- /dev/null +++ b/gnuradio-core/doc/Doxyfile.in @@ -0,0 +1,1224 @@ +# Doxyfile 1.4.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "GNU Radio 2.x" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. + +# -eb +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/src/lib \ + @top_srcdir@/src/tests \ + @top_srcdir@/doc/other + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h \ + *.cc \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = CVS \ + @top_srcdir@/src/lib/swig/gnuradio_swig_python.cc \ + @top_srcdir@/src/lib/atsc \ + @top_srcdir@/src/lib/io-orig \ + @top_srcdir@/src/lib/vrx + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = moc_*.cc + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +# -eb +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +# -eb +XML_PROGRAMLISTING = NO + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = @HAVE_DOT@ + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +# -eb +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/gnuradio-core/doc/Makefile.am b/gnuradio-core/doc/Makefile.am new file mode 100644 index 00000000..562b3665 --- /dev/null +++ b/gnuradio-core/doc/Makefile.am @@ -0,0 +1,71 @@ +# +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = other xml + +man3dir = $(mandir)/man3 +docdir = $(prefix)/share/doc/@PACKAGE@-@VERSION@ + +EXTRA_DIST = + +all-local: prep @generate_docs@ +doc: docs # alias + +docs: prep html/index.html +html/index.html: + @DOXYGEN@ + +prep: + mkdir -p html + +#install-data-local: +# $(mkinstalldirs) $(DESTDIR)$(man3dir) +# @for i in ./man/man3/*.3; do \ +# inst=`basename $$i | sed 's/_/:/g'`; \ +# echo "$(INSTALL_DATA) $$i $(DESTDIR)$(man3dir)/$$inst"; \ +# $(INSTALL_DATA) $$i $(DESTDIR)$(man3dir)/$$inst; \ +# done +# $(mkinstalldirs) $(DESTDIR)$(docdir) +## @for i in ../README ../ChangeLog @PACKAGE@.ps @PACKAGE@.pdf; do \ +## echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)"; \ +## $(INSTALL_DATA) $$i $(DESTDIR)$(docdir); \ +## done +# cp -r html $(docdir) + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(docdir) + @for i in $(top_srcdir)/README $(top_srcdir)/README.hacking $(top_srcdir)/ChangeLog; do \ + echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(docdir); \ + done + cp -r html $(DESTDIR)$(docdir) + +uninstall-local: + @for i in README README.hacking ChangeLog; do \ + echo "$(RM) $(DESTDIR)$(docdir)/$$i;"; \ + $(RM) $(DESTDIR)$(docdir)/$$i; \ + done + $(RM) -fr $(DESTDIR)$(docdir)/html + +clean-local: + $(RM) -fr latex html man diff --git a/gnuradio-core/doc/other/Makefile.am b/gnuradio-core/doc/other/Makefile.am new file mode 100644 index 00000000..25685eda --- /dev/null +++ b/gnuradio-core/doc/other/Makefile.am @@ -0,0 +1,31 @@ +# +# Copyright 2001,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + tv-channel-frequencies \ + vector_docstub.h \ + shared_ptr_docstub.h \ + omnithread.html \ + omnithread.pdf \ + omnithread.ps \ + group_defs.dox diff --git a/gnuradio-core/doc/other/group_defs.dox b/gnuradio-core/doc/other/group_defs.dox new file mode 100644 index 00000000..47cce21c --- /dev/null +++ b/gnuradio-core/doc/other/group_defs.dox @@ -0,0 +1,31 @@ +/*! + * \defgroup block Signal Processing Blocks + * These are the signal processing blocks, blah, blah blah... + * @{ + */ + +/*! + * \defgroup source Signal Sources + * signal sources docs... + */ + +/*! + * \defgroup sink Signal Sinks + * docs for sinks... + */ + +/*! + * \defgroup filter Filters + */ + +/*! + * \defgroup converter Type Conversions + */ + +/*! @} */ + +/*! \defgroup filter_design Filter Design */ +/*! \defgroup filter_primitive Filter Primitives */ +/*! \defgroup internal Implementation Details */ +/*! \defgroup qa Quality Assurance */ + diff --git a/gnuradio-core/doc/other/main_page.dox b/gnuradio-core/doc/other/main_page.dox new file mode 100644 index 00000000..5c37905f --- /dev/null +++ b/gnuradio-core/doc/other/main_page.dox @@ -0,0 +1,5 @@ +/*! \mainpage + +Welcome to GNU Radio! + +*/ diff --git a/gnuradio-core/doc/other/omnithread.html b/gnuradio-core/doc/other/omnithread.html new file mode 100644 index 00000000..5682d1d0 --- /dev/null +++ b/gnuradio-core/doc/other/omnithread.html @@ -0,0 +1,411 @@ + + +The OMNI Thread Abstraction + + + + + + + + + + + + +

The OMNI Thread Abstraction

+ +

Tristan Richardson
+AT&T Laboratories Cambridge
+

+ +

Revised November 2001

+ + +

1  Introduction

+ +The OMNI thread abstraction is designed to provide a common set of +thread operations for use in programs written in C++. Programs +written using the abstraction should be much easier to port between +different architectures with different underlying threads primitives.
+
+The programming interface is designed to be similar to the C language +interface to POSIX threads (IEEE draft standard 1003.1c --- previously +1003.4a, often known as ``pthreads'' [POSIX94]).
+
+Much of the abstraction consists of simple C++ object wrappers around +pthread calls. However for some features such as thread-specific +data, a better interface can be offered because of the use of C++.
+
+Some of the more complex features of pthreads are not supported +because of the difficulty of ensuring the same features can be offered +on top of other thread systems. Such features include thread +cancellation and complex scheduling control (though simple thread +priorities are supported).
+
+The abstraction layer is currently implemented for the following +architectures / thread systems: +
  • Solaris 2.x using pthreads draft 10 +
  • Solaris 2.x using solaris threads (but pthreads version is now standard) +
  • Alpha OSF1 using pthreads draft 4 +
  • Windows NT using NT threads +
  • Linux 2.x using Linuxthread 0.5 (which is based on pthreads draft 10) +
  • Linux 2.x using MIT pthreads (which is based on draft 8) +
  • ATMos using pthreads draft 6 (but not Virata ATMos)
+See the omnithread.h header file for full details of the API. +The descriptions below assume you have some previous knowledge of +threads, mutexes, condition variables and semaphores. Also refer to +other documentation ([Birrell89], [POSIX94]) for further +explanation of these ideas (particularly condition variables, the use +of which may not be particularly intuitive when first encountered).
+
+ + +

2  Synchronisation objects

+ +Synchronisation objects are used to synchronise threads within the +same process. There is no inter-process synchronisation provided. +The synchronisation objects provided are mutexes, condition variables +and counting semaphores.
+
+ + +

2.1  Mutex

+ +An object of type omni_mutex is used for mutual exclusion. +It provides two operations, lock() and unlock(). +The alternative names acquire() and release() can be +used if preferred. Behaviour is undefined when a thread attempts to +lock the same mutex again or when a mutex is locked by one thread and +unlocked by a different thread.
+
+ + +

2.2  Condition Variable

+ +A condition variable is represented by an omni_condition and +is used for signalling between threads. A call to wait() +causes a thread to wait on the condition variable. A call to +signal() wakes up at least one thread if any are waiting. A +call to broadcast() wakes up all threads waiting on the +condition variable.
+
+When constructed, a pointer to an omni_mutex must be given. +A condition variable wait() has an implicit mutex +unlock() and lock() around it. The link between +condition variable and mutex lasts for the lifetime of the condition +variable (unlike pthreads where the link is only for the duration of +the wait). The same mutex may be used with several condition +variables.
+
+A wait with a timeout can be achieved by calling +timed_wait(). This is given an absolute time to wait until. +The routine omni_thread::get_time() can be used to turn a +relative time into an absolute time. timed_wait() returns +true if the condition was signalled, false if the +time expired before the condition variable was signalled.
+
+ + +

2.3  Counting semaphores

+ +An omni_semaphore is a counting semaphore. When created it +is given an initial unsigned integer value. When wait() is +called, the value is decremented if non-zero. If the value is zero +then the thread blocks instead. When post() is called, if +any threads are blocked in wait(), exactly one thread is +woken. If no threads were blocked then the value of the semaphore is +incremented.
+
+If a thread calls try_wait(), then the thread won't block if +the semaphore's value is 0, returning false instead.
+
+There is no way of querying the value of the semaphore.
+
+ + +

3  Thread object

+ +A thread is represented by an omni_thread object. There are +broadly two different ways in which it can be used.
+
+The first way is simply to create an omni_thread object, +giving a particular function which the thread should execute. This is +like the POSIX (or any other) C language interface.
+
+The second method of use is to create a new class which inherits from +omni_thread. In this case the thread will execute the +run() member function of the new class. One advantage of +this scheme is that thread-specific data can be implemented simply by +having data members of the new class.
+
+When constructed a thread is in the "new" state and has not actually +started. A call to start() causes the thread to begin +executing. A static member function create() is provided to +construct and start a thread in a single call. A thread exits by +calling exit() or by returning from the thread function.
+
+Threads can be either detached or undetached. Detached threads are +threads for which all state will be lost upon exit. Other threads +cannot determine when a detached thread will disappear, and therefore +should not attempt to access the thread object unless some explicit +synchronisation with the detached thread guarantees that it still +exists.
+
+Undetached threads are threads for which storage is not reclaimed +until another thread waits for its termination by calling +join(). An exit value can be passed from an undetached +thread to the thread which joins it.
+
+Detached / undetached threads are distinguished on creation by the +type of function they execute. Undetached threads execute a function +which has a void* return type, whereas detached threads +execute a function which has a void return type. +Unfortunately C++ member functions are not allowed to be distinguished +simply by their return type. Thus in the case of a derived class of +omni_thread which needs an undetached thread, the member +function executed by the thread is called run_undetached() +rather than run(), and it is started by calling +start_undetached() instead of start().
+
+The abstraction currently supports three priorities of thread, but no +guarantee is made of how this will affect underlying thread +scheduling. The three priorities are PRIORITY_LOW, +PRIORITY_NORMAL and PRIORITY_HIGH. By default all +threads run at PRIORITY_NORMAL. A different priority can be +specified on thread creation, or while the thread is running using +set_priority(). A thread's current priority is returned by +priority().
+
+Other functions provided are self() which returns the calling +thread's omni_thread object, yield() which +requests that other threads be allowed to run, id() which +returns an integer id for the thread for use in debugging, +state(), sleep() and get_time().
+
+ + +

4  Per-thread data

+ +omnithread supports per-thread data, via member functions of the +omni_thread object.
+
+First, you must allocate a key for with the +omni_thread::allocate_key() function. Then, any object +whose class is derived from omni_thread::value_t can be +stored using the set_value() function. Values are retrieved +or removed with get_value() and remove_value() +respectively.
+
+When the thread exits, all per-thread data is deleted (hence the base +class with virtual destructor).
+
+Note that the per-thread data functions are not thread safe, +so although you can access one thread's storage from another thread, +there is no concurrency control. Unless you really know what you are +doing, it is best to only access per-thread data from the thread it is +attached to.
+
+ + +

5  Using OMNI threads in your program

+ +Obviously you need to include the omnithread.h header file in +your source code, and link in the omnithread library with your +executable. Because there is a single omnithread.h for all +platforms, certain preprocessor defines must be given as compiler +options. The easiest way to do this is to study the makefiles given +in the examples provided with this distribution. If you are to +include OMNI threads in your own development environment, these are +the necessary preprocessor defines:
+ + + + + + + + + + + + + + + + + + + + + + + + +
PlatformPreprocessor Defines
Sun Solaris 2.x-D__sunos__ -D__sparc__ -D__OSVERSION__=5
 -DSVR4 -DUsePthread -D_REENTRANT
x86 Linux 2.0-D__linux__ -D__i86__ -D__OSVERSION__=2
with linuxthreads 0.5-D_REENTRANT
Digital Unix 3.2-D__osf1__ -D__alpha__ -D__OSVERSION__=3
 -D_REENTRANT
Windows NT-D__NT__ -MD

+ + +

6  Threaded I/O shutdown for Unix

+ +or, how one thread should tell another thread to shut down when it +might be doing a blocking call on a socket.
+
+If you are using omniORB, you don't need to worry about all +this, since omniORB does it for you. This section is only relevant +if you are using omnithread in your own socket-based programming. It +is also seriously out of date.
+
+Unfortunately there doesn't seem to be a standard way of doing this +which works across all Unix systems. I have investigated the +behaviour of Solaris 2.5 and Digital Unix 3.2. On Digital Unix +everything is fine, as the obvious method using shutdown() seems to +work OK. Unfortunately on Solaris shutdown can only be used on a +connected socket, so we need devious means to get around this +limitation. The details are summarised below:
+
+ + +

6.1  read()

+ +Thread A is in a loop, doing read(sock), processing the data, +then going back into the read.
+
+Thread B comes along and wants to shut it down --- it can't cancel +thread A since (i) working out how to clean up according to where A is +in its loop is a nightmare, and (ii) this isn't available in +omnithread anyway.
+
+On Solaris 2.5 and Digital Unix 3.2 the following strategy works:
+
+Thread B does shutdown(sock,2).
+
+At this point thread A is either blocked inside read(sock), or +is elsewhere in the loop. If the former then read will return 0, +indicating that the socket is closed. If the latter then eventually +thread A will call read(sock) and then this will return 0. +Thread A should close(sock), do any other tidying up, and exit.
+
+If there is another point in the loop that thread A can block then +obviously thread B needs to be aware of this and be able to wake it up +in the appropriate way from that point.
+
+ + +

6.2  accept()

+ +Again thread A is in a loop, this time doing an accept on listenSock, +dealing with a new connection and going back into accept. Thread B +wants to cancel it.
+
+On Digital Unix 3.2 the strategy is identical to that for read:
+
+Thread B does shutdown(listenSock,2). Wherever thread A is in +the loop, eventually it will return ECONNABORTED from the +accept call. It should close(listenSock), tidy up as necessary +and exit.
+
+On Solaris 2.5 thread B can't do shutdown(listenSock,2) --- +this returns ENOTCONN. Instead the following strategy can be +used:
+
+First thread B sets some sort of "shutdown flag" associated with +listenSock. Then it does getsockaddr(listenSock) to find out +which port listenSock is on (or knows already), sets up a socket +dummySock, does connect(dummySock, this host, port) and +finally does close(dummySock).
+
+Wherever thread A is in the loop, eventually it will call +accept(listenSock). This will return successfully with a new +socket, say connSock. Thread A then checks to see if the "shutdown +flag" is set. If not, then it's a normal connection. If it is set, +then thread A closes listenSock and connSock, tidies up and exits.
+
+ + +

6.3  write()

+ +Thread A may be blocked in write, or about to go in to a +potentially-blocking write. Thread B wants to shut it down.
+
+On Solaris 2.5:
+
+Thread B does shutdown(sock,2).
+
+If thread A is already in write(sock) then it will return with +ENXIO. If thread A calls write after thread B calls shutdown +this will return EIO.
+
+On Digital Unix 3.2:
+
+Thread B does shutdown(sock,2).
+
+If thread A is already in write(sock) then it will return the +number of bytes written before it became blocked. A subsequent call +to write will then generate SIGPIPE (or EPIPE will be +returned if SIGPIPE is ignored by the thread).
+
+ + +

6.4  connect()

+ +Thread A may be blocked in connect, or about to go in to a +potentially-blocking connect. Thread B wants to shut it down.
+
+On Digital Unix 3.2:
+
+Thread B does shutdown(sock,2).
+
+If thread A is already in connect(sock) then it will return a +successful connection. Subsequent reading or writing will show that +the socket has been shut down (i.e. read returns 0, write generates +SIGPIPE or returns EPIPE). If thread A calls connect +after thread B calls shutdown this will return EINVAL.
+
+On Solaris 2.5:
+
+There is no way to wake up a thread which is blocked in connect. +Instead Solaris forces us through a ridiculous procedure whichever way +we try it. One way is this:
+
+First thread A creates a pipe in addition to the socket. Instead of +shutting down the socket, thread B simply writes a byte to the pipe.
+
+Thread A meanwhile sets the socket to non-blocking mode using +fcntl(sock, F_SETFL, O_NONBLOCK). Then it calls connect +on the socket --- this will return EINPROGRESS. Then it must +call select(), waiting for either sock to become writable or +for the pipe to become readable. If select returns that just sock is +writable then the connection has succeeded. It then needs to set the +socket back to blocking mode using fcntl(sock, F_SETFL, 0). If +instead select returns that the pipe is readable, thread A closes the +socket, tidies up and exits.
+
+An alternative method is similar but to use polling instead of the +pipe. Thread B justs sets a flag and thread A calls select with a +timeout, periodically waking up to see if the flag has been set.
+
+ + +

References

+
[POSIX94]
+Portable Operating System Interface (POSIX) Threads Extension, +P1003.1c Draft 10, +IEEE, +September 1994.
+
+
[Birrell89]
+An Introduction to Programming with Threads, +Research Report 35, +DEC Systems Research Center, +Palo Alto, CA, +January 1989.
+ + + +
+
This document was translated from LATEX by +HEVEA. +
+ + diff --git a/gnuradio-core/doc/other/omnithread.pdf b/gnuradio-core/doc/other/omnithread.pdf new file mode 100644 index 00000000..b5421874 Binary files /dev/null and b/gnuradio-core/doc/other/omnithread.pdf differ diff --git a/gnuradio-core/doc/other/omnithread.ps b/gnuradio-core/doc/other/omnithread.ps new file mode 100644 index 00000000..9e858f0b --- /dev/null +++ b/gnuradio-core/doc/other/omnithread.ps @@ -0,0 +1,730 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.86 p1.5d Copyright 1996-2001 ASCII Corp.(www-ptex@ascii.co.jp) +%%based on dvipsk 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com) +%%Title: omnithread.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentFonts: Palatino-Roman Palatino-Italic Palatino-Bold Courier +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips omnithread +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2002.08.15:1756 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/dir 0 def/dyy{/dir 0 def}B/dyt{/dir 1 def}B/dty{/dir 2 def}B/dtt{/dir 3 +def}B/p{dir 2 eq{-90 rotate show 90 rotate}{dir 3 eq{-90 rotate show 90 +rotate}{show}ifelse}ifelse}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 +N/Ry 0 N/V{}B/RV/v{/Ry X/Rx X V}B statusdict begin/product where{pop +false[(Display)(NeXT)(LaserWriter 16/600)]{A length product length le{A +length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse} +forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{ +BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat +{BDot}imagemask grestore}}ifelse B/QV{gsave newpath transform round exch +round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 +rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B +/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M} +B/g{0 M}B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p +-3 w}B/n{p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{ +0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "1 July 1998", +% filename = "8r.enc", +% email = "tex-fonts@@tug.org", +% docstring = "Encoding for TrueType or Type 1 fonts +% to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both +% ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin 0 1 255{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}for Metrics/Metrics currentdict end def[2 index currentdict end +definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup +sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll +mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ +exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} +forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def +end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (omnithread.dvi) +@start /Fa 134[ 45 45 66 1[ 51 30 35 35 1[ 45 40 51 71 +25 2[ 25 45 45 25 35 45 37 42 40 8[ 66 3[ 56 51 2[ 56 +71 5[ 30 3[ 56 3[ 66 23[ 30 30 40[{ TeXBase1Encoding ReEncodeFont} 31 +90.9091 /Palatino-Italic rf /Fb 134[ 51 1[ 76 1[ 56 30 +40 35 2[ 51 56 81 30 2[ 30 56 51 35 45 56 40 56 45 14[ 66 +2[ 76 5[ 35 6[ 61 19[ 23 30 23 4[ 25 39[{ TeXBase1Encoding ReEncodeFont} +27 90.9091 /Palatino-Bold rf /Fc 135[ 50 83 1[ 61 33 +44 39 1[ 61 55 61 89 33 2[ 33 61 55 1[ 50 61 44 61 50 +10[ 78 8[ 100 9[ 72 12[ 50 1[ 50 50 50 50 2[ 25 4[ 33 +33 40[{ TeXBase1Encoding ReEncodeFont} 30 99.6264 /Palatino-Bold +rf /Fd 134[ 55 55 55 55 55 55 55 55 55 55 55 55 55 55 +55 55 55 55 55 55 55 55 55 55 55 1[ 55 5[ 55 55 55 55 +55 55 55 55 1[ 55 55 55 55 55 55 1[ 55 55 55 55 55 55 +55 55 55 3[ 55 2[ 55 1[ 55 1[ 55 55 55 55 55 55 55 1[ 55 +55 55 1[ 55 55 55 40[{ TeXBase1Encoding ReEncodeFont} 65 +90.9091 /Courier rf /Fe 141[ 36 12[ 44 56 2[ 45 7[ 61 +61 91 1[ 71 56 48 61 2[ 71 76 3[ 30 31 76 1[ 51 56 70 +64 56 71 10[ 45 3[ 45 45 1[ 55 23 4[ 30 30 40[{ +.167 SlantFont TeXBase1Encoding ReEncodeFont} 29 90.9091 +/Palatino-Roman rf +%DVIPSBitmapFont: Ff cmsy10 10.95 1 +/Ff 1 16 df 15 +D E +%EndDVIPSBitmapFont +/Fg 104[ 91 2[ 45 45 24[ 45 51 47 76 51 55 30 39 36 51 +55 50 53 80 26 51 21 26 53 51 30 44 56 40 50 45 3[ 30 +1[ 30 2[ 61 91 66 71 56 48 61 1[ 55 71 76 86 56 66 30 +31 76 1[ 51 56 70 64 56 71 6[ 23 45 45 45 45 45 45 45 +45 45 45 55 23 30 23 55 1[ 30 30 25 4[ 34 30[ 55 55 2[{ +TeXBase1Encoding ReEncodeFont} 75 90.9091 /Palatino-Roman +rf /Fh 134[ 66 60 100 1[ 73 40 53 47 1[ 73 66 73 106 +2[ 40 40 73 66 47 60 73 53 73 60 11[ 93 80 73 86 1[ 73 +100 100 120 3[ 47 18[ 60 60 60 60 60 60 1[ 35 1[ 40 45[{ +TeXBase1Encoding ReEncodeFont} 38 119.552 /Palatino-Bold +rf /Fi 137[ 50 2[ 39 9[ 28 3[ 39 50 17[ 66 82[{ +TeXBase1Encoding ReEncodeFont} 6 99.6264 /Palatino-Italic +rf /Fj 137[ 56 1[ 32 42 39 2[ 54 58 88 3[ 29 58 55 1[ 48 +61 44 55 50 12[ 61 1[ 67 3[ 83 1[ 61 8[ 71 1[ 78 14[ 50 +50 50 9[ 78 38[{ TeXBase1Encoding ReEncodeFont} 25 99.6264 +/Palatino-Roman rf /Fk 139[ 47 61 57 2[ 78 83 4[ 42 83 +2[ 69 88 64 79 72 12[ 88 4[ 113 119 136 3[ 48 7[ 112 +65[{ TeXBase1Encoding ReEncodeFont} 18 143.462 /Palatino-Roman +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: A4 + +%%EndSetup +%%Page: 1 1 +1 0 bop Fk 728 918 a(The) 36 b(OMNI) g(Thr) m(ead) f(Abstracti) n(on) p +Fj 1293 1176 a(T) -9 b(ristan) 26 b(Richar) n(dson) 1022 +1293 y(A) -7 b(T&T) 24 b(Laboratories) i(Cambridge) p +Fi 1192 1504 a(Revised) p Fj 24 w(November) f(2001) p +Fh 63 1961 a(1) 119 b(Introduction) p Fg 63 2183 a(The) 20 +b(OMNI) h(thr) n(ead) g(abstraction) g(is) h(des) n(igned) f(to) f(pr) n +(ovide) h(a) h(common) f(set) f(of) h(thr) n(ead) g(oper) n(-) 63 +2296 y(ations) h(for) g(use) g(in) h(pr) n(ograms) f(written) f(in) i +(C++.) 29 b(Pr) n(ograms) 22 b(written) g(using) f(the) h(abstraction) +63 2409 y(should) 30 b(be) g(much) i(easier) e(to) g(port) g(betwee) n +(n) h(dif) n(fer) n(ent) g(ar) n(chi) r(tectur) l(es) g(with) g(dif) n +(fer) n(ent) f(un-) 63 2522 y(derlying) 21 b(thr) n(eads) h +(primitives.) 204 2640 y(The) 17 b(pr) n(ogramming) h(interface) g(is) f +(designed) f(to) h(be) h(similar) h(to) e(the) g(C) i(language) e +(interface) 63 2753 y(to) k(POSIX) h(thr) n(eads) f(\(IEEE) g(draft) h +(standar) n(d) f(100) r(3.1c) i(\227) f(pr) n(eviously) g(1003) r(.4a,) +g(often) g(known) 63 2866 y(as) g(\223pthr) n(eads\224) h([POSIX94]\).) +204 2985 y(Much) 18 b(of) f(the) g(abstraction) i(consists) d(of) i +(simple) g(C++) g(object) g(wrappers) e(ar) n(ound) h(pthr) n(ead) 63 +3098 y(calls.) 28 b(Howe) n(ver) 20 b(for) f(some) f(featur) n(es) g +(such) h(as) h(thr) n(ead-spe) n(ci\002c) h(data,) f(a) f(better) f +(interface) i(can) 63 3211 y(be) i(of) n(fer) n(ed) g(because) h(of) f +(the) g(use) g(of) g(C++.) 204 3329 y(Some) 28 b(of) h(the) f(mor) n(e) +h(complex) f(featur) n(es) g(of) h(pthr) n(eads) f(ar) n(e) h(not) f +(suppo) n(rted) g(because) h(of) 63 3442 y(the) e(dif) n(\002culty) i +(of) f(ensuring) g(the) f(same) h(featur) n(es) g(can) h(be) f(of) n +(fer) n(ed) g(on) g(top) g(of) g(other) f(thr) n(ead) 63 +3555 y(sys) n(tems.) f(Such) 17 b(featur) n(es) g(include) h(thr) n +(ead) f(cancell) r(ation) g(and) h(complex) g(schedu) n(ling) h(contr) n +(ol) 63 3668 y(\(thoug) n(h) k(simple) g(thr) n(ead) f(priorities) g +(ar) n(e) h(supp) n(orted\).) 204 3787 y(The) i(abstraction) h(layer) h +(is) f(curr) n(ently) f(implemented) g(for) h(the) f(following) i(ar) n +(chitectur) n(es) 63 3900 y(/) 22 b(thr) n(ead) h(sys) n(tems:) p +Ff 199 4141 a(\017) p Fg 46 w(Solaris) g(2.x) g(using) f(pthr) n(eads) f +(draft) h(10) p Ff 199 4351 a(\017) p Fg 46 w(Solaris) h(2.x) g(using) f +(solaris) g(thr) n(eads) g(\(but) h(pthr) n(eads) e(version) h(is) h +(now) f(standar) n(d\)) p Ff 199 4561 a(\017) p Fg 46 +w(Alpha) h(OSF1) g(using) f(pthr) n(eads) f(draft) i(4) p +Ff 199 4772 a(\017) p Fg 46 w(W) -5 b(indows) 21 b(NT) h(using) g(NT) g +(thr) n(eads) p Ff 199 4982 a(\017) p Fg 46 w(Linux) g(2.x) h(using) f +(Linuxthr) n(ead) g(0.5) h(\(which) h(is) e(based) g(on) h(pthr) n +(eads) e(draft) i(10\)) p Ff 199 5193 a(\017) p Fg 46 +w(Linux) f(2.x) h(using) f(MIT) g(pthr) n(eads) f(\(which) j(is) f +(based) f(on) g(draft) h(8\)) p Ff 199 5403 a(\017) p +Fg 46 w(A) -7 b(TMos) 22 b(using) g(pthr) n(eads) f(draft) h(6) i +(\(but) e(not) g(V) -5 b(irata) 23 b(A) -7 b(TMos\)) 1684 +5652 y(1) p 90 rotate dyy eop +%%Page: 2 2 +2 1 bop Fg 221 249 a(2) p Fe 1797 w(2) 91 b(SYNCHRONI) n(SA) -7 +b(TION) 22 b(OBJECTS) p Fg 362 548 a(See) h(the) p Fd +22 w(omni) n(thre) n(ad.h) p Fg 22 w(header) f(\002le) i(for) f(full) i +(det) n(ail) r(s) e(of) g(the) g(API.) f(The) h(des) n(criptions) 221 +661 y(below) 35 b(assume) g(you) g(have) h(some) e(pr) n(evious) h +(knowled) n(ge) g(of) h(thr) n(eads) n(,) j(mutexes) n(,) g(condi-) 221 +774 y(tion) f(varia) r(bles) g(and) g(semaphor) n(es) n(.) 75 +b(Also) 38 b(r) n(efer) f(to) h(other) f(document) n(ation) i(\([Birr) n +(ell89) r(],) 221 887 y([POSIX94) q(]\)) 22 b(for) g(further) f +(explanation) i(of) f(thes) n(e) g(ideas) g(\(particularly) h +(condition) f(variab) r(les,) 221 1000 y(the) g(use) g(of) g(which) h +(may) g(not) f(be) h(particularly) h(intuitive) f(when) f(\002rst) f +(encounter) n(ed) n(\).) p Fh 221 1299 a(2) 119 b(Synchronisation) 31 +b(objects) p Fg 221 1510 a(Synchr) n(onisation) 26 b(objects) h(ar) n +(e) g(used) e(to) h(synchr) n(onise) g(thr) n(eads) g(within) h(the) f +(same) h(pr) n(ocess) n(.) 221 1623 y(Ther) n(e) j(is) i(no) f(inter) n +(-pr) n(ocess) f(synchr) n(onisation) g(pr) n(ovided.) 53 +b(The) 30 b(synchr) n(onisation) h(objects) 221 1735 +y(pr) n(ovided) 22 b(ar) n(e) h(mutexes) n(,) g(condition) f(variab) r +(les) g(and) h(counting) f(semaphor) n(e) n(s.) p Fc +221 1991 a(2.1) 99 b(Mutex) p Fg 221 2168 a(An) 26 b(object) g(of) h +(typ) n(e) p Fd 26 w(omni) n(_mute) n(x) p Fg 26 w(is) g(use) n(d) f +(for) h(mutual) f(exclusion.) 39 b(It) 26 b(pr) n(ovides) f(two) g(op-) +221 2281 y(erations,) p Fd 37 w(lock\() n(\)) p Fg 35 +w(and) p Fd 35 w(unloc) n(k\(\)) p Fg(.) 64 b(The) 35 +b(alternative) h(names) p Fd 35 w(acq) n(uire\() n(\)) p +Fg 35 w(and) p Fd 35 w(re-) 221 2393 y(leas) n(e\(\)) p +Fg 19 w(can) 21 b(be) f(used) f(if) i(pr) n(eferr) n(ed) n(.) 27 +b(Behaviour) 20 b(is) g(unde\002ne) n(d) g(when) f(a) i(thr) n(ead) f +(attempt) n(s) 221 2506 y(to) 30 b(lock) h(the) e(same) i(mutex) f +(again) h(or) f(when) g(a) h(mutex) f(is) h(locked) e(by) i(one) e(thr) +n(ead) h(and) h(un-) 221 2619 y(locked) 22 b(by) h(a) g(dif) n(fer) n +(ent) f(thr) n(ead.) p Fc 221 2874 a(2.2) 99 b(Condition) 26 +b(V) -11 b(ariable) p Fg 221 3051 a(A) 28 b(condition) f(varia) r(ble) h +(is) g(r) n(epr) n(ese) n(nted) f(by) h(an) p Fd 28 w(omn) n(i_con) n +(diti) n(on) p Fg 27 w(and) g(is) g(used) e(for) i(sig-) 221 +3164 y(nalli) r(ng) 20 b(betwee) n(n) g(thr) n(eads.) 26 +b(A) 21 b(call) h(to) p Fd 19 w(wait\() n(\)) p Fg 20 +w(causes) e(a) h(thr) n(ead) e(to) h(wait) h(on) f(the) f(condition) 221 +3277 y(varia) r(ble.) 45 b(A) 28 b(call) i(to) p Fd 27 +w(sign) n(al\(\)) p Fg 27 w(wakes) d(up) h(at) g(least) g(one) f(thr) n +(ead) h(if) h(any) f(ar) n(e) g(waiting.) 45 b(A) 221 +3390 y(call) 25 b(to) p Fd 22 w(bro) n(adca) n(st\(\)) p +Fg 21 w(wakes) d(up) g(all) i(thr) n(eads) e(waiting) h(on) f(the) g +(condition) g(varia) r(ble.) 362 3503 y(When) 30 b(constr) o(ucte) n +(d,) i(a) e(pointer) f(to) h(an) p Fd 30 w(omni) n(_mute) n(x) p +Fg 30 w(must) f(be) h(given.) 50 b(A) 30 b(condition) 221 +3616 y(varia) r(ble) p Fd 33 w(wait\() n(\)) p Fg 33 +w(has) j(an) h(implic) r(it) f(mutex) p Fd 33 w(unlo) n(ck\(\)) p +Fg 32 w(and) p Fd 33 w(lock) n(\(\)) p Fg 33 w(ar) n(ound) g(it.) 60 +b(The) 221 3729 y(link) 30 b(between) f(condition) g(varia) r(ble) h +(and) g(mutex) f(lasts) g(for) h(the) f(lifetime) i(of) e(the) g +(condition) 221 3842 y(varia) r(ble) c(\(unlike) h(pthr) n(eads) e +(wher) n(e) g(the) h(link) h(is) f(only) g(for) g(the) g(duration) f +(of) i(the) e(wait\).) 37 b(The) 221 3955 y(same) 23 +b(mutex) f(may) h(be) f(used) f(with) i(several) f(condition) h(variab) +r(les.) 362 4068 y(A) c(wait) g(with) g(a) g(timeout) f(can) i(be) e +(achieved) h(by) g(call) r(ing) p Fd 19 w(tim) n(ed_w) n(ait\(\)) p +Fg -2 w(.) 27 b(This) 18 b(is) h(given) 221 4181 y(an) 27 +b(absolute) e(time) h(to) f(wait) h(until.) 38 b(The) 26 +b(r) n(outine) p Fd 25 w(omn) n(i_thr) n(ead:) n(:get_) n(time) n(\(\)) +p Fg 25 w(can) h(be) 221 4293 y(used) 21 b(to) h(turn) g(a) h(r) n +(elativ) r(e) f(time) g(into) h(an) g(absolute) f(time.) p +Fd 28 w(tim) n(ed_wa) n(it\(\)) p Fg 21 w(r) n(eturns) p +Fd 21 w(true) p Fg 21 w(if) 221 4406 y(the) 27 b(condition) h(was) g +(signalled,) p Fd 29 w(false) p Fg 26 w(if) h(the) f(time) g(expir) n +(ed) f(befor) n(e) g(the) h(condition) f(vari) r(-) 221 +4519 y(able) d(was) e(signalled.) p Fc 221 4774 a(2.3) 99 +b(Counting) 26 b(semaphores) p Fg 221 4951 a(An) p Fd +21 w(omn) n(i_sem) n(apho) n(re) p Fg 20 w(is) 21 b(a) h(counting) e +(semaphor) n(e) n(.) 28 b(When) 20 b(cr) n(eated) g(it) h(is) g(given) g +(an) g(initial) 221 5064 y(unsigned) j(intege) n(r) i(value.) 36 +b(When) p Fd 25 w(wai) n(t\(\)) p Fg 24 w(is) 26 b(called,) g(the) f +(value) h(is) f(decr) n(emente) n(d) g(if) h(non-) 221 +5177 y(zer) n(o.) 43 b(If) 27 b(the) g(value) h(is) f(zer) n(o) h(then) +f(the) f(thr) n(ead) h(blocks) h(instead.) 41 b(When) p +Fd 27 w(post) n(\(\)) p Fg 27 w(is) 27 b(cal) r(led,) 221 +5290 y(if) h(any) g(thr) n(eads) e(ar) n(e) i(blocked) f(in) p +Fd 27 w(wait\() n(\)) p Fg(,) h(exactly) f(one) g(thr) n(ead) g(is) g +(woken.) 41 b(If) 27 b(no) g(thr) n(eads) 221 5403 y(wer) n(e) 22 +b(blocked) g(then) g(the) g(value) h(of) g(the) e(semaphor) n(e) h(is) h +(incr) n(emented.) p 90 rotate dyy eop +%%Page: 3 3 +3 2 bop Fg 3306 249 a(3) 204 548 y(If) 27 b(a) h(thr) n(ead) e(cal) r +(ls) p Fd 27 w(try) n(_wait) n(\(\)) p Fg(,) h(then) g(the) f(thr) n +(ead) g(won't) h(block) h(if) f(the) g(semaphor) n(e's) 63 +661 y(value) c(is) g(0,) g(r) n(eturning) p Fd 21 w(false) p +Fg 21 w(instead.) 204 777 y(Ther) n(e) f(is) g(no) h(way) f(of) h +(query) n(ing) g(the) f(value) h(of) g(the) f(semaphor) n(e) n(.) p +Fh 63 1095 a(3) 119 b(Thread) 29 b(object) p Fg 63 1313 +a(A) 23 b(thr) n(ead) g(is) h(r) n(epr) n(ese) n(nted) e(by) i(an) p +Fd 24 w(omni) n(_thr) n(ead) p Fg 23 w(object.) 30 b(Ther) n(e) 23 +b(ar) n(e) h(br) n(oadly) g(two) e(dif) n(fer) n(-) 63 +1426 y(ent) f(ways) i(in) g(which) g(it) g(can) g(be) g(used) n(.) 204 +1542 y(The) 28 b(\002rst) g(way) h(is) h(simply) f(to) f(cr) n(eate) h +(an) p Fd 30 w(omn) n(i_thr) n(ead) p Fg 28 w(object,) h(giving) g(a) f +(particula) r(r) 63 1655 y(function) c(which) h(the) e(thr) n(ead) h +(should) f(execute) n(.) 36 b(This) 25 b(is) g(like) g(the) g(POSIX) f +(\(or) i(any) f(other) n(\)) h(C) 63 1768 y(language) c(interface.) 204 +1884 y(The) k(second) f(method) h(of) h(use) e(is) i(to) f(cr) n(eate) h +(a) g(new) g(class) g(which) g(inherits) f(fr) n(om) p +Fd 28 w(omn) n(i_) 63 1997 y(thr) n(ead) p Fg(.) 50 b(In) 31 +b(this) f(case) g(the) g(thr) n(ead) g(will) i(execute) d(the) p +Fd 29 w(run\(\)) p Fg 29 w(member) h(function) h(of) f(the) 63 +2109 y(new) 22 b(class.) 29 b(One) 23 b(advantage) g(of) g(this) g +(scheme) f(is) h(that) g(thr) n(ead-speci\002c) g(data) g(can) h(be) f +(imple-) 63 2222 y(mented) e(simply) h(by) h(having) g(data) g(members) +f(of) h(the) f(new) g(class.) 204 2339 y(When) f(constr) o(ucted) g(a) i +(thr) n(ead) f(is) g(in) h(the) e("new") h(state) f(and) h(has) g(not) g +(actuall) r(y) g(starte) n(d.) 28 b(A) 63 2451 y(call) j(to) p +Fd 29 w(sta) n(rt\(\)) p Fg 28 w(causes) e(the) g(thr) n(ead) g(to) g +(begin) g(executing.) 47 b(A) 29 b(static) h(member) f(function) p +Fd 63 2564 a(cre) n(ate\() n(\)) p Fg 32 w(is) j(pr) n(ovided) f(to) g +(constr) o(uct) g(and) g(start) g(a) i(thr) n(ead) e(in) h(a) g(single) +g(call.) 57 b(A) 31 b(thr) n(ead) 63 2677 y(exits) 21 +b(by) i(call) r(ing) p Fd 22 w(exit\() n(\)) p Fg 22 +w(or) g(by) f(r) n(eturning) g(fr) n(om) h(the) f(thr) n(ead) g +(function.) 204 2793 y(Thr) n(eads) 27 b(can) j(be) e(either) g +(detached) f(or) h(undetached) n(.) 46 b(Detached) 28 +b(thr) n(eads) g(ar) n(e) h(thr) n(eads) 63 2906 y(for) h(which) i(all) +g(state) e(will) i(be) f(lost) f(upon) g(exit.) 52 b(Other) 30 +b(thr) n(eads) g(cannot) h(dete) n(rmine) g(when) 63 +3019 y(a) e(detached) f(thr) n(ead) h(will) h(disappear) -7 +b(,) 31 b(and) e(ther) n(efor) n(e) f(should) g(not) h(attempt) f(to) g +(access) h(the) 63 3132 y(thr) n(ead) 23 b(object) g(unless) f(some) h +(explicit) h(synchr) n(onisation) f(with) g(the) g(detached) f(thr) n +(ead) h(guar) n(-) 63 3245 y(antees) e(that) h(it) h(still) g(exists.) +204 3361 y(Undet) n(ached) 33 b(thr) n(eads) f(ar) n(e) i(thr) n(eads) e +(for) h(which) g(storage) f(is) h(not) f(r) n(eclai) r(med) g(until) i +(an-) 63 3474 y(othe) n(r) g(thr) n(ead) g(waits) g(for) g(its) g +(termination) g(by) g(call) r(ing) p Fd 34 w(joi) n(n\(\)) p +Fg(.) 61 b(An) 34 b(exit) g(value) h(can) g(be) 63 3587 +y(passe) n(d) 23 b(fr) n(om) g(an) g(undet) n(ached) g(thr) n(ead) f +(to) g(the) g(thr) n(ead) g(which) h(joins) g(it.) 204 +3703 y(Detached) 31 b(/) h(undetached) e(thr) n(eads) h(ar) n(e) i +(distinguish) n(ed) f(on) f(cr) n(eation) h(by) g(the) f(type) g(of) 63 +3816 y(function) 24 b(they) e(execute.) 30 b(Undetached) 22 +b(thr) n(eads) h(execute) g(a) h(function) g(which) g(has) g(a) p +Fd 25 w(voi) n(d*) p Fg 63 3929 a(r) n(eturn) c(typ) n(e,) h(wher) n +(eas) f(detached) f(thr) n(eads) h(execute) f(a) j(function) f(which) g +(has) g(a) p Fd 21 w(void) p Fg 19 w(r) n(eturn) 63 4042 +y(typ) n(e.) 52 b(Unfortunate) n(ly) 31 b(C++) g(member) g(functions) f +(ar) n(e) h(not) f(allowed) g(to) g(be) h(distingu) n(ished) 63 +4155 y(simply) 26 b(by) h(their) f(r) n(eturn) g(type) n(.) 40 +b(Thus) 26 b(in) h(the) f(case) h(of) g(a) g(derived) f(class) h(of) p +Fd 26 w(omni_) n(thre) n(ad) p Fg 63 4268 a(which) 20 +b(needs) e(an) j(undet) n(ached) f(thr) n(ead,) g(the) f(member) h +(function) g(execute) n(d) g(by) g(the) f(thr) n(ead) g(is) 63 +4380 y(called) p Fd 19 w(run_u) n(ndet) n(ache) n(d\(\)) p +Fg 18 w(rather) f(than) p Fd 19 w(run\() n(\)) p Fg(,) h(and) g(it) g +(is) g(started) e(by) i(calli) r(ng) p Fd 18 w(star) n(t_) 63 +4493 y(und) n(etac) n(hed\(\)) p Fg 21 w(instead) j(of) p +Fd 22 w(start) n(\(\)) p Fg(.) 204 4610 y(The) i(abstraction) i(curr) n +(ently) e(suppo) n(rts) h(thr) n(ee) f(priorities) g(of) h(thr) n(ead,) +g(but) g(no) g(guarantee) 63 4722 y(is) 33 b(made) g(of) h(how) f(this) +g(will) h(af) n(f) r(ect) f(underlying) f(thr) n(ead) h(scheduling.) 59 +b(The) 33 b(thr) n(ee) f(priori-) 63 4835 y(ties) 18 +b(ar) n(e) p Fd 20 w(PRIO) n(RITY) n(_LOW) p Fg(,) p +Fd 18 w(PRIO) n(RITY) n(_NOR) n(MAL) p Fg 19 w(and) p +Fd 19 w(PRIO) n(RITY) n(_HIG) n(H) p Fg(.) h(By) g(default) g(all) 63 +4948 y(thr) n(eads) i(r) o(un) i(at) p Fd 23 w(PRIO) n(RITY) n(_NORM) n +(AL) p Fg(.) f(A) g(dif) n(fer) n(ent) h(priority) f(can) i(be) e +(speci\002ed) g(on) g(thr) n(ead) 63 5061 y(cr) n(eation,) h(or) f +(while) h(the) f(thr) n(ead) g(is) h(r) o(unning) g(using) p +Fd 22 w(set_) n(prio) n(rity\() n(\).) p Fg 28 w(A) g(thr) n(ead's) f +(cur) n(-) 63 5174 y(r) n(ent) g(priority) g(is) g(r) n(eturned) f(by) p +Fd 23 w(pri) n(ority) n(\(\)) p Fg(.) 204 5290 y(Other) d(functions) g +(pr) n(ovided) g(ar) n(e) p Fd 19 w(sel) n(f\(\)) p Fg +18 w(which) h(r) n(eturns) e(the) h(calli) r(ng) g(thr) n(ead's) p +Fd 18 w(omn) n(i_) 63 5403 y(thr) n(ead) p Fg 36 w(object,) p +Fd 40 w(yie) n(ld\(\)) p Fg 35 w(which) 38 b(r) n(eques) n(ts) e(that) h +(other) e(thr) n(eads) h(be) h(allowed) g(to) f(r) o(un,) p +90 rotate dyy eop +%%Page: 4 4 +4 3 bop Fg 221 249 a(4) p Fe 1367 w(6) 91 b(THRE) n(ADED) 23 +b(I/O) g(SHUTDOWN) f(FOR) g(UNIX) p Fd 221 548 a(id\(\)) p +Fg 27 w(which) 29 b(r) n(eturns) e(an) i(intege) n(r) g(id) f(for) h +(the) e(thr) n(ead) h(for) g(use) g(in) h(debug) n(ging,) p +Fd 29 w(state) n(\(\)) p Fg(,) p Fd 221 661 a(slee) n(p\(\)) p +Fg 22 w(and) p Fd 22 w(get_t) n(ime\() n(\)) p Fg(.) p +Fh 221 953 a(4) 119 b(Per) n(-threa) n(d) 30 b(data) p +Fg 221 1164 a(omnithr) n(ead) 22 b(suppo) n(rts) g(per) n(-thr) n(ead) f +(data,) h(via) i(member) e(functions) f(of) i(the) p +Fd 21 w(omni) n(_thr) n(ead) p Fg 221 1277 a(object.) 362 +1390 y(First,) d(you) g(must) h(allocate) h(a) f(key) f(for) g(with) h +(the) p Fd 20 w(omni) n(_thre) n(ad::) n(allo) n(cate_) n(key\() n(\)) p +Fg 221 1502 a(function.) 28 b(Then,) 21 b(any) h(object) g(whose) f +(class) h(is) g(derived) f(fr) n(om) p Fd 23 w(omni) n(_thr) n(ead::) n +(valu) n(e_t) p Fg 221 1615 a(can) 27 b(be) f(stor) n(e) n(d) g(using) f +(the) p Fd 26 w(set) n(_val) n(ue\(\)) p Fg 25 w(function.) 38 +b(V) -8 b(alues) 25 b(ar) n(e) h(r) n(etrieved) f(or) h(r) n(emoved) 221 +1728 y(with) p Fd 23 w(get) n(_valu) n(e\(\)) p Fg 21 +w(and) p Fd 23 w(remo) n(ve_v) n(alue\() n(\)) p Fg 22 +w(r) n(espectively) -10 b(.) 362 1841 y(When) 23 b(the) g(thr) n(ead) g +(exits,) g(all) i(per) n(-thr) n(ead) e(data) h(is) g(delet) n(ed) f +(\(hence) h(the) e(base) i(class) g(with) 221 1954 y(virtual) g(dest) n +(r) o(uctor\).) 362 2067 y(Note) 17 b(that) i(the) f(per) n(-thr) n +(ead) f(data) i(functions) f(ar) n(e) p Fb 19 w(not) p +Fg 18 w(thr) n(ead) g(safe,) i(so) d(although) i(you) e(can) 221 +2180 y(access) 29 b(one) e(thr) n(ead's) h(storage) f(fr) n(om) i +(another) f(thr) n(ead,) h(ther) n(e) e(is) i(no) f(concurr) n(ency) g +(contr) n(ol.) 221 2293 y(Unless) j(you) g(r) n(eall) r(y) h(know) f +(what) h(you) f(ar) n(e) i(doing,) g(it) g(is) f(best) f(to) h(only) g +(access) g(per) n(-thr) n(ead) 221 2406 y(data) 23 b(fr) n(om) g(the) f +(thr) n(ead) g(it) h(is) g(attached) f(to.) p Fh 221 +2698 a(5) 119 b(Using) 31 b(OMNI) d(threads) h(in) h(your) g(program) p +Fg 221 2909 a(Obvi) r(ously) 16 b(you) h(need) g(to) g(include) h(the) p +Fd 16 w(omnit) n(hrea) n(d.h) p Fg 17 w(header) e(\002le) i(in) g(your) +f(sour) n(ce) g(code,) 221 3021 y(and) 25 b(link) g(in) h(the) e +(omnithr) n(ead) g(libra) r(ry) g(with) h(your) f(execut) n(abl) r(e.) +34 b(Because) 23 b(ther) n(e) h(is) h(a) g(single) p +Fd 221 3134 a(omni) n(threa) n(d.h) p Fg 30 w(for) 32 +b(all) h(platforms,) h(certain) e(pr) n(epr) n(oces) n(sor) f +(de\002nes) f(must) h(be) g(given) h(as) 221 3247 y(compiler) 25 +b(options) n(.) 33 b(The) 23 b(easiest) g(way) h(to) g(do) f(this) h +(is) g(to) g(stud) n(y) g(the) g(make\002les) f(given) h(in) h(the) 221 +3360 y(examples) i(pr) n(ovided) g(with) g(this) g(distribution.) 42 +b(If) 27 b(you) g(ar) n(e) g(to) g(include) h(OMNI) f(thr) n(eads) g +(in) 221 3473 y(your) 18 b(own) g(development) g(envir) n(onment,) h +(thes) n(e) g(ar) n(e) g(the) f(necessary) g(pr) n(epr) n(oce) n(ssor) g +(de\002nes) n(:) p 362 3567 3287 4 v 360 3680 4 113 v +412 3646 a(Platform) p 1312 3680 V 599 w(Pr) n(epr) n(ocess) n(or) 23 +b(De\002nes) p 3648 3680 V 362 3683 3287 4 v 362 3700 +V 360 3813 4 113 v 412 3779 a(Sun) f(Solaris) h(2.x) p +1312 3813 V Fd 365 w(-D__) n(suno) n(s__) 54 b(-D_) n(_spa) n(rc__) f +(-D__) n(OSVER) n(SION) n(__=5) p 3648 3813 V 360 3926 +V 1312 3926 V 1363 3892 a(-DSV) n(R4) h(-DUs) n(ePth) n(read) f(-D_R) n +(EENT) n(RANT) p 3648 3926 V 362 3929 3287 4 v 360 4042 +4 113 v Fg 412 4008 a(x86) 24 b(Linux) e(2.0) p 1312 +4042 V Fd 418 w(-D__) n(linu) n(x__) 54 b(-D_) n(_i86) n(__) g(-D__) n +(OSVE) n(RSION) n(__=2) p 3648 4042 V 360 4155 V Fg 412 +4121 a(with) 23 b(linuxthr) n(eads) f(0.5) p 1312 4155 +V Fd 100 w(-D_R) n(EENT) n(RANT) p 3648 4155 V 362 4158 +3287 4 v 360 4271 4 113 v Fg 412 4237 a(Digital) i(Unix) f(3.2) p +1312 4271 V Fd 320 w(-D__) n(osf1) n(__) 54 b(-D__) n(alph) n(a__) g +(-D_) n(_OSV) n(ERSIO) n(N__=) n(3) p 3648 4271 V 360 +4384 V 1312 4384 V 1363 4350 a(-D_R) n(EENT) n(RANT) p +3648 4384 V 362 4387 3287 4 v 360 4500 4 113 v Fg 412 +4466 a(W) -5 b(indows) 22 b(NT) p 1312 4500 V Fd 411 +w(-D__) n(NT__) 53 b(-MD) p 3648 4500 V 362 4503 3287 +4 v Fh 221 4740 a(6) 119 b(Threaded) 29 b(I/O) g(shutdown) h(for) g +(Unix) p Fg 221 4951 a(or) -7 b(,) 20 b(how) e(one) g(thr) n(ead) h +(shou) n(ld) h(tell) f(another) f(thr) n(ead) g(to) h(shut) f(down) g +(when) g(it) h(might) g(be) g(doing) 221 5064 y(a) k(blocking) g(cal) r +(l) g(on) f(a) h(socket) n(.) p Fb 362 5177 a(If) h(you) e(are) i +(using) e(omniOR) n(B,) h(you) e(don') n(t) i(need) g(to) g(worry) f +(about) g(all) i(this,) f(since) h(om-) 221 5290 y(niORB) i(does) h(it) +h(for) f(you) n(.) p Fg 41 w(This) g(section) f(is) h(only) g(r) n +(elevant) g(if) h(you) e(ar) n(e) h(using) f(omnithr) n(ead) 221 +5403 y(in) d(your) f(own) g(socket) n(-based) h(pr) n(ogramming.) k(It) +22 b(is) h(also) g(serious) n(ly) g(out) f(of) h(date.) p +90 rotate dyy eop +%%Page: 5 5 +5 4 bop Fe 63 249 a(6.1) 91 b(r) n(ead\(\)) p Fg 2800 +w(5) 204 548 y(Unfortunate) n(ly) 35 b(ther) n(e) e(doe) n(sn't) h +(seem) f(to) h(be) g(a) h(standar) n(d) e(way) i(of) f(doing) f(this) h +(which) 63 661 y(works) 19 b(acr) n(oss) i(all) i(Unix) e(syst) n(ems.) +27 b(I) 21 b(have) g(investigated) f(the) h(behaviour) g(of) g(Solaris) +h(2.5) g(and) 63 774 y(Digital) k(Unix) g(3.2.) 36 b(On) 26 +b(Digital) h(Unix) e(everyth) n(ing) h(is) f(\002ne,) g(as) h(the) e +(obvious) h(method) f(using) 63 887 y(shutd) n(own\(\)) 32 +b(seems) f(to) h(work) f(OK.) h(Unfortunately) f(on) h(Solaris) h(shut) +n(down) f(can) h(only) f(be) 63 1000 y(used) 25 b(on) h(a) h(connected) +e(socke) n(t,) i(so) f(we) g(need) f(devious) h(means) g(to) g(get) f +(ar) n(ound) h(this) g(lim) r(ita-) 63 1112 y(tion.) h(The) 22 +b(details) g(ar) n(e) h(summarised) g(below:) p Fc 63 +1429 a(6.1) 99 b(read\(\)) p Fg 63 1627 a(Thr) n(ead) 28 +b(A) h(is) g(in) h(a) g(loop,) g(doing) p Fd 28 w(rea) n(d\(soc) n(k\)) +p Fg(,) g(pr) n(ocess) n(ing) f(the) g(data,) h(then) f(going) f(back) +63 1739 y(into) 22 b(the) g(r) n(ead.) 204 1862 y(Thr) n(ead) 30 +b(B) h(comes) f(along) h(and) g(wants) f(to) g(shut) g(it) h(down) f +(\227) h(it) g(can't) g(cancel) h(thr) n(ead) f(A) 63 +1975 y(since) 21 b(\(i\)) h(working) e(out) g(how) g(to) h(clean) h(up) +e(accor) n(ding) i(to) e(wher) n(e) g(A) h(is) g(in) h(its) f(loop) f +(is) h(a) h(night-) 63 2088 y(mar) n(e,) h(and) f(\(ii\)) i(this) f +(isn't) f(ava) r(ilabl) r(e) g(in) h(omnithr) n(ead) f(anyway) -10 +b(.) 204 2211 y(On) 23 b(Solaris) g(2.5) g(and) g(Digital) h(Unix) f +(3.2) g(the) f(following) h(strate) n(gy) f(works:) 204 +2334 y(Thr) n(ead) g(B) g(does) p Fd 21 w(shut) n(down\() n(sock) n +(,2\)) p Fg(.) 204 2457 y(At) g(this) g(point) h(thr) n(ead) f(A) g(is) +h(either) f(blocked) g(inside) p Fd 23 w(rea) n(d\(so) n(ck\)) p +Fg(,) g(or) g(is) h(elsewhe) n(r) n(e) g(in) 63 2570 +y(the) 18 b(loop.) 26 b(If) 18 b(the) g(former) h(then) f(r) n(ead) h +(will) h(r) n(eturn) e(0,) i(indicating) f(that) g(the) f(socke) n(t) h +(is) g(closed.) 26 b(If) 63 2683 y(the) 21 b(latter) h(then) f +(eventually) h(thr) n(ead) g(A) g(will) i(call) p Fd +24 w(rea) n(d\(so) n(ck\)) p Fg 21 w(and) f(then) e(this) h(will) h(r) n +(eturn) 63 2796 y(0.) 28 b(Thr) n(ead) 22 b(A) h(should) p +Fd 21 w(clos) n(e\(soc) n(k\)) p Fg(,) f(do) g(any) g(other) g(tidying) +f(up,) h(and) h(exit.) 204 2919 y(If) 34 b(ther) n(e) g(is) h(another) f +(point) g(in) h(the) e(loop) i(that) f(thr) n(ead) g(A) h(can) g(block) +g(then) f(obviously) 63 3032 y(thr) n(ead) 19 b(B) h(needs) f(to) h(be) +g(awar) n(e) h(of) f(this) g(and) g(be) h(able) g(to) e(wake) h(it) h +(up) f(in) g(the) g(appr) n(opriate) g(way) 63 3145 y(fr) n(om) j(that) +f(point.) p Fc 63 3462 a(6.2) 99 b(accept\(\)) p Fg 63 +3659 a(Again) 25 b(thr) n(ead) g(A) h(is) f(in) h(a) g(loop,) g(this) f +(time) h(doing) e(an) i(acc) r(ept) e(on) h(listenSock,) g(dealing) h +(with) 63 3772 y(a) d(new) f(connection) g(and) h(going) e(back) j +(into) e(accept.) 28 b(Thr) n(ead) 22 b(B) g(wants) h(to) f(cancel) h +(it.) 204 3895 y(On) g(Digital) h(Unix) f(3.2) g(the) f(strateg) n(y) g +(is) h(identical) h(to) e(that) g(for) h(r) n(ead:) 204 +4018 y(Thr) n(ead) 39 b(B) g(does) p Fd 38 w(shut) n(down) n(\(list) n +(enSo) n(ck,2) n(\)) p Fg(.) 79 b(Wher) n(ever) 38 b(thr) n(ead) h(A) h +(is) f(in) h(the) 63 4131 y(loop,) i(eventually) c(it) h(will) h(r) n +(eturn) p Fd 38 w(ECONN) n(ABOR) n(TED) p Fg 38 w(fr) n(om) f(the) f +(accept) h(call) r(.) 76 b(It) 39 b(shou) n(ld) p Fd +63 4244 a(clo) n(se\(l) n(isten) n(Sock) n(\)) p Fg(,) 22 +b(tidy) g(up) g(as) h(necessary) e(and) i(exit.) 204 +4367 y(On) 30 b(Solaris) f(2.5) i(thr) n(ead) e(B) g(can't) h(do) p +Fd 29 w(shu) n(tdow) n(n\(lis) n(tenS) n(ock,2) n(\)) p +Fg 29 w(\227) g(this) f(r) n(eturns) p Fd 63 4480 a(ENO) n(TCON) n(N) p +Fg(.) 22 b(Instead) f(the) h(following) h(strateg) n(y) g(can) g(be) g +(used) n(:) 204 4603 y(First) 35 b(thr) n(ead) h(B) g(set) n(s) g(some) +f(sort) g(of) h("shutdo) n(wn) g(\003ag") g(associated) g(with) g +(listenSock.) 63 4716 y(Then) 31 b(it) h(does) p Fd 30 +w(gets) n(ocka) n(ddr\(l) n(iste) n(nSock) n(\)) p Fg +32 w(to) f(\002nd) g(out) g(which) i(port) e(listenSock) f(is) 63 +4828 y(on) 18 b(\(or) h(knows) e(alr) n(eady\),) j(sets) d(up) h(a) h +(socket) e(dummySock,) i(doe) n(s) p Fd 19 w(con) n(nect) n(\(dumm) n +(ySoc) n(k,) 63 4941 y(thi) n(s) 54 b(host,) f(por) n(t\)) p +Fg 22 w(and) 23 b(\002nally) g(does) p Fd 21 w(clos) n(e\(dum) n(mySo) n +(ck\)) p Fg(.) 204 5064 y(Wher) n(ever) 16 b(thr) n(ead) h(A) g(is) g +(in) h(the) e(loop,) h(eventually) g(it) h(will) g(call) p +Fd 19 w(acce) n(pt\(li) n(sten) n(Sock) n(\)) p Fg(.) 63 +5177 y(This) 35 b(will) j(r) n(eturn) d(successfully) g(with) h(a) h +(new) e(socket,) j(say) e(connSock.) 67 b(Thr) n(ead) 36 +b(A) f(then) 63 5290 y(checks) 20 b(to) h(see) f(if) i(the) f("shutd) n +(own) g(\003ag") h(is) f(set.) 26 b(If) c(not,) e(then) h(it's) g(a) h +(normal) g(connection.) 27 b(If) 21 b(it) 63 5403 y(is) h(set,) g(then) +f(thr) n(ead) h(A) h(closes) f(listenSock) f(and) i(connSock,) e +(tidies) h(up) g(and) h(exits.) p 90 rotate dyy eop +%%Page: 6 6 +6 5 bop Fg 221 249 a(6) p Fe 1367 w(6) 91 b(THRE) n(ADED) 23 +b(I/O) g(SHUTDOWN) f(FOR) g(UNIX) p Fc 221 548 a(6.3) 99 +b(write\(\)) p Fg 221 768 a(Thr) n(ead) 19 b(A) f(may) h(be) g(blocked) +f(in) i(write,) f(or) f(about) h(to) f(go) g(in) h(to) g(a) g(poten) n +(tiall) r(y-blocking) g(write.) 221 881 y(Thr) n(ead) j(B) h(wants) f +(to) g(shut) f(it) i(down.) 362 1016 y(On) g(Solaris) g(2.5:) 362 +1150 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 w(shu) n(tdown) n(\(soc) n +(k,2\)) p Fg -2 w(.) 362 1285 y(If) c(thr) n(ead) f(A) h(is) g(alr) n +(eady) g(in) p Fd 20 w(wri) n(te\(s) n(ock\)) p Fg 17 +w(then) f(it) h(will) i(r) n(eturn) d(with) p Fd 18 w(ENXIO) p +Fg -2 w(.) h(If) g(thr) n(ead) 221 1398 y(A) k(calls) h(write) e(after) +g(thr) n(ead) g(B) h(calls) h(shut) n(down) e(this) g(will) i(r) n +(eturn) p Fd 22 w(EIO) p Fg(.) 362 1532 y(On) f(Digital) h(Unix) f +(3.2:) 362 1666 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 +w(shu) n(tdown) n(\(soc) n(k,2\)) p Fg -2 w(.) 362 1801 +y(If) h(thr) n(ead) f(A) g(is) h(alr) n(eady) g(in) p +Fd 24 w(writ) n(e\(so) n(ck\)) p Fg 23 w(then) e(it) i(will) h(r) n +(eturn) e(the) f(number) i(of) f(bytes) 221 1914 y(written) 31 +b(befor) n(e) h(it) g(became) g(blocked.) 55 b(A) 32 +b(subseq) n(uent) f(cal) r(l) h(to) f(write) h(will) h(then) e(gene) n +(rate) p Fd 221 2027 a(SIGP) n(IPE) p Fg 22 w(\(or) p +Fd 22 w(EPIP) n(E) p Fg 23 w(will) 24 b(be) e(r) n(eturned) f(if) p +Fd 24 w(SIG) n(PIPE) p Fg 21 w(is) i(ignor) n(ed) e(by) i(the) f(thr) n +(ead\).) p Fc 221 2413 a(6.4) 99 b(connect\(\)) p Fg +221 2634 a(Thr) n(ead) 30 b(A) f(may) h(be) g(blocked) f(in) i +(connect,) g(or) e(about) h(to) f(go) g(in) i(to) e(a) h(poten) n +(tiall) r(y-blocking) 221 2747 y(connect.) d(Thr) n(ead) c(B) f(wants) g +(to) g(shut) g(it) g(down.) 362 2881 y(On) h(Digital) h(Unix) f(3.2:) +362 3016 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 w(shu) n(tdown) n +(\(soc) n(k,2\)) p Fg -2 w(.) 362 3150 y(If) j(thr) n(ead) f(A) g(is) h +(alr) n(eady) g(in) p Fd 26 w(conn) n(ect\() n(sock) n(\)) p +Fg 26 w(then) e(it) i(will) h(r) n(eturn) e(a) h(successful) f(con-) 221 +3263 y(nection.) 54 b(Subsequ) n(ent) 31 b(r) n(eading) g(or) g +(writing) g(will) i(show) d(that) i(the) e(socket) g(has) h(been) g +(shut) 221 3376 y(down) 22 b(\(i.e.) 28 b(r) n(ead) 23 +b(r) n(eturns) e(0,) i(write) f(generate) n(s) p Fd 23 +w(SIG) n(PIPE) p Fg 21 w(or) g(r) n(eturns) p Fd 22 w(EPI) n(PE) p +Fg(\).) g(If) h(thr) n(ead) f(A) 221 3489 y(call) r(s) g(connect) g +(after) h(thr) n(ead) f(B) g(call) r(s) g(shutdo) n(wn) h(this) f(will) +i(r) n(eturn) p Fd 22 w(EIN) n(VAL) p Fg(.) 362 3623 +y(On) f(Solaris) g(2.5:) 362 3758 y(Ther) n(e) 35 b(is) h(no) f(way) g +(to) g(wake) g(up) g(a) h(thr) n(ead) f(which) h(is) g(blocked) f(in) h +(connect.) 66 b(Inst) n(ead) 221 3871 y(Solaris) 33 b(for) n(ces) g(us) +f(thr) n(ough) g(a) i(ridiculous) f(pr) n(oced) n(ur) n(e) g(whichever) +g(way) g(we) f(try) g(it.) 59 b(One) 221 3984 y(way) 23 +b(is) f(this:) 362 4118 y(First) d(thr) n(ead) h(A) g(cr) n(eates) f(a) +h(pipe) g(in) g(addition) g(to) f(the) g(socket) n(.) 27 +b(Instead) 19 b(of) h(shut) n(ting) g(down) 221 4231 +y(the) i(socket) n(,) h(thr) n(ead) f(B) g(simply) h(writes) e(a) i +(byte) f(to) g(the) g(pipe.) 362 4365 y(Thr) n(ead) 17 +b(A) g(meanwhile) h(set) n(s) f(the) g(socke) n(t) g(to) g +(non-blocking) g(mode) f(using) p Fd 17 w(fcn) n(tl\(s) n(ock,) 221 +4478 y(F_SE) n(TFL,) 53 b(O_NO) n(NBLO) n(CK\)) p Fg(.) 26 +b(Then) h(it) g(cal) r(ls) g(connect) g(on) g(the) f(socket) g(\227) h +(this) g(will) i(r) n(eturn) p Fd 221 4591 a(EINP) n(ROGRE) n(SS) p +Fg(.) k(Then) h(it) h(must) e(cal) r(l) p Fd 35 w(sel) n(ect\() n(\)) p +Fg(,) k(waiting) e(for) f(either) g(sock) g(to) f(become) 221 +4704 y(writable) 39 b(or) f(for) h(the) e(pipe) h(to) g(become) g(r) n +(eadable.) 75 b(If) 39 b(select) e(r) n(eturns) g(that) i(just) e(sock) +h(is) 221 4817 y(writable) 30 b(then) f(the) g(connection) g(has) h +(succeede) n(d.) 49 b(It) 29 b(then) g(need) n(s) h(to) f(set) f(the) h +(socket) f(back) 221 4930 y(to) i(blocking) h(mode) f(using) p +Fd 30 w(fcnt) n(l\(so) n(ck,) 54 b(F_S) n(ETFL) n(,) h(0\)) p +Fg(.) c(If) 31 b(instead) e(select) h(r) n(eturns) 221 +5043 y(that) 23 b(the) e(pipe) h(is) h(r) n(eadable,) g(thr) n(ead) f +(A) h(closes) e(the) h(socket) n(,) h(tidies) f(up) g(and) h(exits.) 362 +5177 y(An) g(alternative) h(method) e(is) i(similar) h(but) e(to) g +(use) f(polling) i(instead) e(of) i(the) e(pipe.) 29 +b(Thr) n(ead) 221 5290 y(B) 24 b(justs) e(sets) g(a) j(\003ag) f(and) g +(thr) n(ead) f(A) h(calls) h(select) e(with) g(a) i(timeout,) e(period) +n(ica) r(lly) h(waking) f(up) 221 5403 y(to) f(see) g(if) h(the) f +(\003ag) h(has) f(been) g(set.) p 90 rotate dyy eop +%%Page: 7 7 +7 6 bop Fe 63 249 a(REF) n(ERENCES) p Fg 2660 w(7) p +Fh 63 548 a(Refere) n(nces) p Fg 63 759 a([POSIX94]) p +Fa 46 w(Portable) 29 b(Operat) r(ing) f(System) g(Interface) h +(\(POSIX\)) e(Thr) n(ea) r(ds) h(Extension) p Fg(,) h(P1003) r(.1c) 245 +872 y(Draft) 23 b(10,) g(IEEE,) e(Septe) n(mber) i(1994) r(.) 63 +1059 y([Birr) n(ell89]) p Fa 47 w(An) 28 b(Intr) n(od) r(uction) g(to) h +(Pr) n(ogr) r(amming) g(with) g(Thr) n(ead) r(s) p Fg(,) h(Rese) n(ar) n +(ch) g(Repo) n(rt) e(35,) j(DEC) 245 1172 y(Syst) n(ems) 22 +b(Resear) n(ch) g(Center) -7 b(,) 22 b(Palo) h(Alto,) f(CA,) h(January) +g(1989) r(.) p 90 rotate dyy eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/gnuradio-core/doc/other/shared_ptr_docstub.h b/gnuradio-core/doc/other/shared_ptr_docstub.h new file mode 100755 index 00000000..428dd03f --- /dev/null +++ b/gnuradio-core/doc/other/shared_ptr_docstub.h @@ -0,0 +1,24 @@ +namespace boost +{ + /*! + * \brief shared_ptr documentation stub + * + * \warning + * This isn't the real shared_ptr template. It's just enough to get doxygen + * to draw pretty collaboration diagrams. + * + * An enhanced relative of scoped_ptr with reference counted copy semantics. + * The object pointed to is deleted when the last shared_ptr pointing to it + * is destroyed or reset. + */ + +template class shared_ptr +{ +public: + + T * px; // contained pointer + +}; // shared_ptr + + +} // namespace boost diff --git a/gnuradio-core/doc/other/tv-channel-frequencies b/gnuradio-core/doc/other/tv-channel-frequencies new file mode 100644 index 00000000..e2780eca --- /dev/null +++ b/gnuradio-core/doc/other/tv-channel-frequencies @@ -0,0 +1,79 @@ +# These are the center frequencies in MHz for North American broadcast +# TV channels. Each channel is 6 MHz wide, hence the bottom edge of the +# channel is 3 MHz below the value in this table. +# +# For NTSC (Analog) TV, the picture carrier is 1.25 MHz up from the +# bottom edge. NTSC has the FM audio at bottom + 5.75 and the spike is easily +# visible. +# +# For ATSC, the pilot tone is 0.31 MHz up from the bottom. +# +# + 2 57.00 + 3 63.00 + 4 69.00 + 5 79.00 + 6 85.00 + 7 177.00 + 8 183.00 + 9 189.00 + 10 195.00 + 11 201.00 + 12 207.00 + 13 213.00 + 14 473.00 + 15 479.00 + 16 485.00 + 17 491.00 + 18 497.00 + 19 503.00 + 20 509.00 + 21 515.00 + 22 521.00 + 23 527.00 + 24 533.00 + 25 539.00 + 26 545.00 + 27 551.00 + 28 557.00 + 29 563.00 + 30 569.00 + 31 575.00 + 32 581.00 + 33 587.00 + 34 593.00 + 35 599.00 + 36 605.00 + 37 611.00 + 38 617.00 + 39 623.00 + 40 629.00 + 41 635.00 + 42 641.00 + 43 647.00 + 44 653.00 + 45 659.00 + 46 665.00 + 47 671.00 + 48 677.00 + 49 683.00 + 50 689.00 + 51 695.00 + 52 701.00 + 53 707.00 + 54 713.00 + 55 719.00 + 56 725.00 + 57 731.00 + 58 737.00 + 59 743.00 + 60 749.00 + 61 755.00 + 62 761.00 + 63 767.00 + 64 773.00 + 65 779.00 + 66 785.00 + 67 791.00 + 68 797.00 + 69 803.00 diff --git a/gnuradio-core/doc/other/vector_docstub.h b/gnuradio-core/doc/other/vector_docstub.h new file mode 100644 index 00000000..139ce651 --- /dev/null +++ b/gnuradio-core/doc/other/vector_docstub.h @@ -0,0 +1,16 @@ +namespace std +{ + /*! + * \brief vector documentation stub + * + * \warning + * This isn't the real vector template. It's just enough to get doxygen + * to draw pretty collaboration diagrams. + */ + template class vector + { + public: + T *p; + }; + +} // namespace std diff --git a/gnuradio-core/doc/xml/Makefile.am b/gnuradio-core/doc/xml/Makefile.am new file mode 100644 index 00000000..848a4685 --- /dev/null +++ b/gnuradio-core/doc/xml/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = README doxy2swig.py swig.xsl + +CLEANFILES = *.xml combine.xslt compound.xsd index.xsd + diff --git a/gnuradio-core/doc/xml/README b/gnuradio-core/doc/xml/README new file mode 100644 index 00000000..317dbb4e --- /dev/null +++ b/gnuradio-core/doc/xml/README @@ -0,0 +1,129 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# +# Generating Python docstrings from C++ code using doxygen +# + +There are at least two strategies for this: + - use xsltproc as described below + - use doxy2swig.py (included in this directory) + +FIXME: get one of these working (probably doxy2swig since it doesn't +add any additional dependencies). + +---------------------------------------------------------------- + +Note: Robin's patch is in SWIG >= 1.3.23 + +-------------------------------------------------------------------------------- +From: http://mailman.cs.uchicago.edu/pipermail/swig/2004-October/010604.html + +> I applied the docstring patch. '%feature("autodoc",1");' is working as +> expected ... + +[problem solved. ...] + +> I can not agree more with the doxygen idea. I am using doxygen for +> documentation and I have been trying to put doxygen output to the +> python interface. Automatic generation of %feature("docstring") lines +> from doxygen output is the closest solution I can think of but the +> workload is still pretty big. How I wish this feature can be +> implemented in the near future. + +I have successfully extracted function/class description from doxygen +generated xml files, using an xslt script. To add doxygen generated +description to each class/function, you will need to (tested under +linux, note that this works only for Python, using Robin's docstring +patch) + +1. download swig source, apply Robin's docstring patch from + https://sourceforge.net/tracker/index.php?func=detail&aid=1023309&group_id=1645&atid=301645 + compile and install + +2. generate doxygen document with option "GENERATE_XML = YES" + +3. copy the attached script (save as swig.xsl) to the doc/xml directory + and run + + > xsltproc swig.xsl index.xml > temp_doc.i + > cat temp_doc.i | sed 's/"/\\"/g' | sed 's/__QuOtE__/"/g' > swig_doc.i + + you will get an interface file with lines like + %feature("docstring") class "class description"; + %feature("docstring") class::function "member function + description"; + + the second step is necessary since there might be " in descriptions + and I need to backquote them before I replace __QuOtE__ by real + quotes. (xslt experts may know how to post-process and + make the script easier to use.) + +4. in your interface file, add + %include "siwg_doc.i" + %feature("autodoc","1") ; + +Hope this helps. + +swig.xsl: +========================================================= + + + + + + + + + + + + + + %feature(__QuOtE__docstring__QuOtE__) + + __QuOtE__ + + + + see also: + + __QuOtE__; + + + + %feature(__QuOtE__docstring__QuOtE__) :: + __QuOtE__ + + + + + __QuOtE__; + + + + + +-- +Bo Peng \ No newline at end of file diff --git a/gnuradio-core/doc/xml/doxy2swig.py b/gnuradio-core/doc/xml/doxy2swig.py new file mode 100644 index 00000000..1e379d94 --- /dev/null +++ b/gnuradio-core/doc/xml/doxy2swig.py @@ -0,0 +1,371 @@ +#!/usr/bin/env python +"""Doxygen XML to SWIG docstring converter. + +Converts Doxygen generated XML files into a file containing docstrings +that can be used by SWIG-1.3.x. Note that you need to get SWIG +version > 1.3.23 or use Robin Dunn's docstring patch to be able to use +the resulting output. + +Usage: + + doxy2swig.py input.xml output.i + +input.xml is your doxygen generated XML file and output.i is where the +output will be written (the file will be clobbered). + +""" + +# This code is implemented using Mark Pilgrim's code as a guideline: +# http://www.faqs.org/docs/diveintopython/kgp_divein.html +# +# Author: Prabhu Ramachandran +# License: BSD style + + +from xml.dom import minidom +import re +import textwrap +import sys +import types +import os.path + + +def my_open_read(source): + if hasattr(source, "read"): + return source + else: + return open(source) + +def my_open_write(dest): + if hasattr(dest, "write"): + return dest + else: + return open(dest, 'w') + + +class Doxy2SWIG: + """Converts Doxygen generated XML files into a file containing + docstrings that can be used by SWIG-1.3.x that have support for + feature("docstring"). Once the data is parsed it is stored in + self.pieces. + + """ + + def __init__(self, src): + """Initialize the instance given a source object (file or + filename). + + """ + f = my_open_read(src) + self.my_dir = os.path.dirname(f.name) + self.xmldoc = minidom.parse(f).documentElement + f.close() + + self.pieces = [] + self.pieces.append('\n// File: %s\n'%\ + os.path.basename(f.name)) + + self.space_re = re.compile(r'\s+') + self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)') + self.multi = 0 + self.ignores = ('inheritancegraph', 'param', 'listofallmembers', + 'innerclass', 'name', 'declname', 'incdepgraph', + 'invincdepgraph', 'programlisting', 'type', + 'references', 'referencedby', 'location', + 'collaborationgraph', 'reimplements', + 'reimplementedby', 'derivedcompoundref', + 'basecompoundref') + #self.generics = [] + + def generate(self): + """Parses the file set in the initialization. The resulting + data is stored in `self.pieces`. + + """ + self.parse(self.xmldoc) + + def parse(self, node): + """Parse a given node. This function in turn calls the + `parse_` functions which handle the respective + nodes. + + """ + pm = getattr(self, "parse_%s"%node.__class__.__name__) + pm(node) + + def parse_Document(self, node): + self.parse(node.documentElement) + + def parse_Text(self, node): + txt = node.data + txt = txt.replace('\\', r'\\\\') + txt = txt.replace('"', r'\"') + # ignore pure whitespace + m = self.space_re.match(txt) + if m and len(m.group()) == len(txt): + pass + else: + self.add_text(textwrap.fill(txt)) + + def parse_Element(self, node): + """Parse an `ELEMENT_NODE`. This calls specific + `do_` handers for different elements. If no handler + is available the `generic_parse` method is called. All + tagNames specified in `self.ignores` are simply ignored. + + """ + name = node.tagName + ignores = self.ignores + if name in ignores: + return + attr = "do_%s" % name + if hasattr(self, attr): + handlerMethod = getattr(self, attr) + handlerMethod(node) + else: + self.generic_parse(node) + #if name not in self.generics: self.generics.append(name) + + def add_text(self, value): + """Adds text corresponding to `value` into `self.pieces`.""" + if type(value) in (types.ListType, types.TupleType): + self.pieces.extend(value) + else: + self.pieces.append(value) + + def get_specific_nodes(self, node, names): + """Given a node and a sequence of strings in `names`, return a + dictionary containing the names as keys and child + `ELEMENT_NODEs`, that have a `tagName` equal to the name. + + """ + nodes = [(x.tagName, x) for x in node.childNodes \ + if x.nodeType == x.ELEMENT_NODE and \ + x.tagName in names] + return dict(nodes) + + def generic_parse(self, node, pad=0): + """A Generic parser for arbitrary tags in a node. + + Parameters: + + - node: A node in the DOM. + - pad: `int` (default: 0) + + If 0 the node data is not padded with newlines. If 1 it + appends a newline after parsing the childNodes. If 2 it + pads before and after the nodes are processed. Defaults to + 0. + + """ + npiece = 0 + if pad: + npiece = len(self.pieces) + if pad == 2: + self.add_text('\n') + for n in node.childNodes: + self.parse(n) + if pad: + if len(self.pieces) > npiece: + self.add_text('\n') + + def space_parse(self, node): + self.add_text(' ') + self.generic_parse(node) + + do_ref = space_parse + do_emphasis = space_parse + do_bold = space_parse + do_computeroutput = space_parse + do_formula = space_parse + + def do_compoundname(self, node): + self.add_text('\n\n') + data = node.firstChild.data + self.add_text('%%feature("docstring") %s "\n'%data) + + def do_compounddef(self, node): + kind = node.attributes['kind'].value + if kind in ('class', 'struct'): + prot = node.attributes['prot'].value + if prot <> 'public': + return + names = ('compoundname', 'briefdescription', + 'detaileddescription', 'includes') + first = self.get_specific_nodes(node, names) + for n in names: + if first.has_key(n): + self.parse(first[n]) + self.add_text(['";','\n']) + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + elif kind in ('file', 'namespace'): + nodes = node.getElementsByTagName('sectiondef') + for n in nodes: + self.parse(n) + + def do_includes(self, node): + self.add_text('C++ includes: ') + self.generic_parse(node, pad=1) + + def do_parameterlist(self, node): + self.add_text(['\n', '\n', 'Parameters:', '\n']) + self.generic_parse(node, pad=1) + + def do_para(self, node): + self.add_text('\n') + self.generic_parse(node, pad=1) + + def do_parametername(self, node): + self.add_text('\n') + self.add_text("%s: "%node.firstChild.data) + + def do_parameterdefinition(self, node): + self.generic_parse(node, pad=1) + + def do_detaileddescription(self, node): + self.generic_parse(node, pad=1) + + def do_briefdescription(self, node): + self.generic_parse(node, pad=1) + + def do_memberdef(self, node): + prot = node.attributes['prot'].value + id = node.attributes['id'].value + kind = node.attributes['kind'].value + tmp = node.parentNode.parentNode.parentNode + compdef = tmp.getElementsByTagName('compounddef')[0] + cdef_kind = compdef.attributes['kind'].value + + if prot == 'public': + first = self.get_specific_nodes(node, ('definition', 'name')) + name = first['name'].firstChild.data + if name[:8] == 'operator': # Don't handle operators yet. + return + + defn = first['definition'].firstChild.data + self.add_text('\n') + self.add_text('%feature("docstring") ') + + anc = node.parentNode.parentNode + if cdef_kind in ('file', 'namespace'): + ns_node = anc.getElementsByTagName('innernamespace') + if not ns_node and cdef_kind == 'namespace': + ns_node = anc.getElementsByTagName('compoundname') + if ns_node: + ns = ns_node[0].firstChild.data + self.add_text(' %s::%s "\n%s'%(ns, name, defn)) + else: + self.add_text(' %s "\n%s'%(name, defn)) + elif cdef_kind in ('class', 'struct'): + # Get the full function name. + anc_node = anc.getElementsByTagName('compoundname') + cname = anc_node[0].firstChild.data + self.add_text(' %s::%s "\n%s'%(cname, name, defn)) + + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + self.add_text(['";', '\n']) + + def do_definition(self, node): + data = node.firstChild.data + self.add_text('%s "\n%s'%(data, data)) + + def do_sectiondef(self, node): + kind = node.attributes['kind'].value + if kind in ('public-func', 'func'): + self.generic_parse(node) + + def do_simplesect(self, node): + kind = node.attributes['kind'].value + if kind in ('date', 'rcs', 'version'): + pass + elif kind == 'warning': + self.add_text(['\n', 'WARNING: ']) + self.generic_parse(node) + elif kind == 'see': + self.add_text('\n') + self.add_text('See: ') + self.generic_parse(node) + else: + self.generic_parse(node) + + def do_argsstring(self, node): + self.generic_parse(node, pad=1) + + def do_member(self, node): + kind = node.attributes['kind'].value + refid = node.attributes['refid'].value + if kind == 'function' and refid[:9] == 'namespace': + self.generic_parse(node) + + def do_doxygenindex(self, node): + self.multi = 1 + comps = node.getElementsByTagName('compound') + for c in comps: + refid = c.attributes['refid'].value + fname = refid + '.xml' + if not os.path.exists(fname): + fname = os.path.join(self.my_dir, fname) + print "parsing file: %s"%fname + p = Doxy2SWIG(fname) + p.generate() + self.pieces.extend(self.clean_pieces(p.pieces)) + + def write(self, fname): + o = my_open_write(fname) + if self.multi: + o.write("".join(self.pieces)) + else: + o.write("".join(self.clean_pieces(self.pieces))) + o.close() + + def clean_pieces(self, pieces): + """Cleans the list of strings given as `pieces`. It replaces + multiple newlines by a maximum of 2 and returns a new list. + It also wraps the paragraphs nicely. + + """ + ret = [] + count = 0 + for i in pieces: + if i == '\n': + count = count + 1 + else: + if i == '";': + if count: + ret.append('\n') + elif count > 2: + ret.append('\n\n') + elif count: + ret.append('\n'*count) + count = 0 + ret.append(i) + + _data = "".join(ret) + ret = [] + for i in _data.split('\n\n'): + if i == 'Parameters:': + ret.extend(['Parameters:\n-----------', '\n\n']) + elif i.find('// File:') > -1: # leave comments alone. + ret.extend([i, '\n']) + else: + _tmp = textwrap.fill(i.strip()) + _tmp = self.lead_spc.sub(r'\1"\2', _tmp) + ret.extend([_tmp, '\n\n']) + return ret + + +def main(input, output): + p = Doxy2SWIG(input) + p.generate() + p.write(output) + + +if __name__ == '__main__': + if len(sys.argv) != 3: + print __doc__ + sys.exit(1) + main(sys.argv[1], sys.argv[2]) diff --git a/gnuradio-core/doc/xml/swig.xsl b/gnuradio-core/doc/xml/swig.xsl new file mode 100644 index 00000000..6163c2d9 --- /dev/null +++ b/gnuradio-core/doc/xml/swig.xsl @@ -0,0 +1,38 @@ + + + + + + + + + + + + + %feature(__QuOtE__docstring__QuOtE__) + + __QuOtE__ + + + + see also: + + __QuOtE__; + + + + %feature(__QuOtE__docstring__QuOtE__) :: + __QuOtE__ + + + + + __QuOtE__; + + + + diff --git a/gnuradio-core/gnuradio-core.conf b/gnuradio-core/gnuradio-core.conf new file mode 100644 index 00000000..d64f5840 --- /dev/null +++ b/gnuradio-core/gnuradio-core.conf @@ -0,0 +1,19 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[DEFAULT] + +verbose = False + + +[audio] + +# specify which audio module to load, or use "auto" to have the system +# select one. Valid choices depend on your OS and which modules +# you've installed, but typically include: auto, audio_alsa, +# audio_oss, audio_portaudio, audio_jack, audio_osx, audio_windows + +audio_module = auto + + diff --git a/gnuradio-core/gnuradio-core.pc.in b/gnuradio-core/gnuradio-core.pc.in new file mode 100644 index 00000000..cc6c03ac --- /dev/null +++ b/gnuradio-core/gnuradio-core.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gnuradio + +Name: gnuradio-core +Description: GNU Software Radio toolkit +Requires: +Version: @VERSION@ +Libs: -L${libdir} -lgnuradio-core @FFTW3F_LIBS@ +Cflags: -I${includedir} @DEFINES@ @PTHREAD_CFLAGS@ diff --git a/gnuradio-core/src/Makefile.am b/gnuradio-core/src/Makefile.am new file mode 100644 index 00000000..8d00ccae --- /dev/null +++ b/gnuradio-core/src/Makefile.am @@ -0,0 +1,26 @@ +# +# Copyright 2001,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = gen_interpolator_taps lib tests python + +DIST_SUBDIRS = gen_interpolator_taps lib tests python utils diff --git a/gnuradio-core/src/gen_interpolator_taps/Makefile.am b/gnuradio-core/src/gen_interpolator_taps/Makefile.am new file mode 100644 index 00000000..fff6372c --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = praxis.txt simpson.h + +if ENABLE_FORTRAN +noinst_PROGRAMS = gen_interpolator_taps +noinst_HEADERS = simpson.h + +gen_interpolator_taps_SOURCES = gen_interpolator_taps.c objective_fct.c simpson.c praxis.f +gen_interpolator_taps_LDADD = $(FLIBS) -lm + +endif diff --git a/gnuradio-core/src/gen_interpolator_taps/README b/gnuradio-core/src/gen_interpolator_taps/README new file mode 100644 index 00000000..cc2f1ac8 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/README @@ -0,0 +1,47 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +This file contains the source for gen_interpolator_taps, a program +which generates optimal interpolator taps for a fractional +interpolator. + +The ideal interpolator requires an infinite tap FIR filter to +realize. We design a separate 8 tap filter for each value of mu, +the fractional delay, that we are interested in. The taps are +selected such that the mean squared error between the ideal frequency +response and the approximation is mininimized over all frequencies of +interest. In this implementation we define ``frequencies of +interest'' as those from -B to +B, where B = 1/(4*Ts), where Ts is the +sampling period. + +For a detailed look at what this is all about, please see Chapter 9 of +"Digital Communication Receivers: Synchronization, Channel Estimation +and Signal Processing" by Meyr, Moeneclaey and Fechtel, ISBN 0-471-50275-8 + +NOTE, if you're running gen_interpolator_taps and it seg faults in +RANDOM, you're probably using g77-2.96. The fix is to use g77 3.0 or later + + cd + rm config.cache + export F77=g77-3.0.4 + ./configure + make diff --git a/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c new file mode 100644 index 00000000..0dd05651 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c @@ -0,0 +1,186 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#define NSTEPS 10 // how many steps of mu are in the generated table +#define MAX_NSTEPS 256 +#define NTAPS 8 // # of taps in the interpolator +#define MAX_NTAPS 128 + +extern void initpt (double x[], int ntaps); +extern double objective (double x[], int *ntaps); +extern double global_mu; +extern double global_B; + +// fortran +extern double prax2_ (double (fct)(double x[], int *ntaps), + double initv[], int *ntaps, double result[]); + +static void +usage (char *name) +{ + fprintf (stderr, "usage: %s [-v] [-n ] [-t ] [-B ]\n", name); + exit (1); +} + +static void +printline (double x[], int ntaps, int imu, int nsteps) +{ + int i; + + printf (" { "); + for (i = 0; i < ntaps; i++){ + printf ("%12.5e", x[i]); + if (i != ntaps - 1) + printf (", "); + else + printf (" }, // %3d/%d\n", imu, nsteps); + } +} + +int +main (int argc, char **argv) +{ + double xx[MAX_NSTEPS+1][MAX_NTAPS]; + int ntaps = NTAPS; + int nsteps = NSTEPS; + int i, j; + double result; + double step_size; + int c; + int verbose = 0; + + global_B = 0.25; + + while ((c = getopt (argc, argv, "n:t:B:v")) != EOF){ + switch (c){ + case 'n': + nsteps = strtol (optarg, 0, 0); + break; + + case 't': + ntaps = strtol (optarg, 0, 0); + break; + + case 'B': + global_B = strtod (optarg, 0); + break; + + case 'v': + verbose = 1; + break; + + default: + usage (argv[0]); + break; + } + } + + if ((nsteps & 1) != 0){ + fprintf (stderr, "%s: nsteps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NSTEPS){ + fprintf (stderr, "%s: nsteps must be < %d\n", argv[0], MAX_NSTEPS); + exit (1); + } + + if ((ntaps & 1) != 0){ + fprintf (stderr, "%s: ntaps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NTAPS){ + fprintf (stderr, "%s: ntaps must be < %d\n", argv[0], MAX_NTAPS); + exit (1); + } + + if (global_B < 0 || global_B > 0.5){ + fprintf (stderr, "%s: bandwidth must be in the range (0, 0.5)\n", argv[0]); + exit (1); + } + + step_size = 1.0/nsteps; + + // the optimizer chokes on the two easy cases (0/N and N/N). We do them by hand... + + for (i = 0; i < ntaps; i++) + xx[0][i] = 0.0; + xx[0][ntaps/2] = 1.0; + + + // compute optimal values for mu <= 0.5 + + for (j = 1; j <= nsteps/2; j++){ + + global_mu = j * step_size; // this determines the MU for which we're computing the taps + + // initialize X to a reasonable starting value + + initpt (&xx[j][0], ntaps); + + // find the value of X that minimizes the value of OBJECTIVE + + result = prax2_ (objective, &xx[j][0], &ntaps, &xx[j][0]); + + if (verbose){ + fprintf (stderr, "Mu: %10.8f\t", global_mu); + fprintf (stderr, "Objective: %g\n", result); + } + } + + // now compute remaining values via symmetry + + for (j = 0; j < nsteps/2; j++){ + for (i = 0; i < ntaps; i++){ + xx[nsteps - j][i] = xx[j][ntaps-i-1]; + } + } + + // now print out the table + + printf ("\ +/*\n\ + * This file was machine generated by gen_interpolator_taps.\n\ + * DO NOT EDIT BY HAND.\n\ + */\n\n"); + + + printf ("static const int NTAPS = %4d;\n", ntaps); + printf ("static const int NSTEPS = %4d;\n", nsteps); + printf ("static const double BANDWIDTH = %g;\n\n", global_B); + + printf ("static const float taps[NSTEPS+1][NTAPS] = {\n"); + printf (" // -4 -3 -2 -1 0 1 2 3 mu\n"); + + + for (i = 0; i <= nsteps; i++) + printline (xx[i], ntaps, i, nsteps); + + printf ("};\n\n"); + + return 0; +} diff --git a/gnuradio-core/src/gen_interpolator_taps/objective_fct.c b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c new file mode 100644 index 00000000..aab0008e --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c @@ -0,0 +1,124 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * generate MMSE FIR interpolation table values + */ + +#include +#include +#include "simpson.h" + +#define MU 0.5 /* the MU for which we're computing coeffs */ + +#define Ts (1.0) /* sampling period */ +#define B (1.0/(4*Ts)) /* one-sided signal bandwidth */ +//#define B (1.0/(8./3*Ts)) /* one-sided signal bandwidth */ + +static unsigned global_n; +static double *global_h; +double global_mu = MU; +double global_B = B; + +/* + * This function computes the difference squared between the ideal + * interpolator frequency response at frequency OMEGA and the + * approximation defined by the FIR coefficients in global_h[] + * + * See eqn (9-7), "Digital Communication Receivers", Meyr, Moeneclaey + * and Fechtel, Wiley, 1998. + */ + +static double +integrand (double omega) +{ + double real_ideal; + double real_approx; + double real_diff; + double imag_ideal; + double imag_approx; + double imag_diff; + + int i, n; + int I1; + double *h; + + real_ideal = cos (omega * Ts * global_mu); + imag_ideal = sin (omega * Ts * global_mu); + + n = global_n; + h = global_h; + I1 = -(n / 2); + + real_approx = 0; + imag_approx = 0; + + for (i = 0; i < n; i++){ + real_approx += h[i] * cos (-omega * Ts * (i + I1)); + imag_approx += h[i] * sin (-omega * Ts * (i + I1)); + } + + real_diff = real_ideal - real_approx; + imag_diff = imag_ideal - imag_approx; + + return real_diff * real_diff + imag_diff * imag_diff; +} + +/* + * Integrate the difference squared over all frequencies of interest. + */ +double +c_fcn (double *x, int n) +{ + assert ((n & 1) == 0); /* assert n is even */ + global_n = n; + global_h = x; + return qsimp (integrand, -2 * M_PI * global_B, 2 * M_PI * global_B); +} + +/* this is the interface expected by the calling fortran code */ + +double +objective (double x[], int *ndim) +{ + return c_fcn (x, *ndim); +} + +static double +si (double x) +{ + if (fabs (x) < 1e-9) + return 1.0; + + return sin(x) / x; +} + +/* + * starting guess for optimization + */ +void initpt (double x[], int ndim) +{ + int i; + for (i = 0; i < ndim; i++){ + x[i] = si (M_PI * ((double) (i - ndim/2) + global_mu)); + } +} diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.f b/gnuradio-core/src/gen_interpolator_taps/praxis.f new file mode 100644 index 00000000..1b648b9b --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.f @@ -0,0 +1,1705 @@ +C +C Copyright 2002 Free Software Foundation, Inc. +C +C This file is part of GNU Radio +C +C GNU Radio is free software; you can redistribute it and/or modify +C it under the terms of the GNU General Public License as published by +C the Free Software Foundation; either version 2, or (at your option) +C any later version. +C +C GNU Radio is distributed in the hope that it will be useful, +C but WITHOUT ANY WARRANTY; without even the implied warranty of +C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +C GNU General Public License for more details. +C +C You should have received a copy of the GNU General Public License +C along with GNU Radio; see the file COPYING. If not, write to +C the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +C Boston, MA 02111-1307, USA. +C + DOUBLE PRECISION FUNCTION PRAX2(F,INITV,NDIM,OUT) + DOUBLE PRECISION INITV(128),OUT(128), F + INTEGER NDIM + EXTERNAL F +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + +C + N=NDIM + do 10 I=1,N + 10 X(I) = INITV(I) + +C + call praset + +C -1 produces no diagnostic output + jprint = -1 + nfmax = 3000 +C tighter tolerance + T=1.0D-6 +C + call praxis(f) +C + do 30 I=1,N + 30 OUT(I) = X(I) +C + prax2 = fx + return + end + + + SUBROUTINE PRASET +C +C PRASET 1.0 JUNE 1995 +C +C SET INITIAL VALUES FOR SOME QUANTITIES USED IN SUBROUTINE PRAXIS. +C THE USER CAN RESET THESE, IF DESIRED, +C AFTER CALLING PRASET AND BEFORE CALLING PRAXIS. +C +C J. P. CHANDLER, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY +C +C ON MANY MACHINES, SUBROUTINE PRAXIS WILL CAUSE UNDERFLOW AND/OR +C DIVIDE CHECK WHEN COMPUTING EPSMCH**4 AND EPSMCH**(-4). +C IN THAT CASE, SET EPSMCH=1.0D-9 (OR POSSIBLY EPSMCH=1.0D-8) +C AFTER CALLING SUBROUTINE PRASET. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION A,B,XMID,XPLUS,RZERO,UNITR,RTWO +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + RZERO=0.0D0 + UNITR=1.0D0 + RTWO=2.0D0 +C +C NMAX IS THE DIMENSION OF THE ARRAYS V(*,*), X(*), D(*), +C Q0(*), AND Q1(*). +C + NMAX=128 +C +C NFMAX IS THE MAXIMUM NUMBER OF FUNCTION EVALUATIONS PERMITTED. +C + NFMAX=100000 +C +C LP IS THE LOGICAL UNIT NUMBER FOR PRINTED OUTPUT. +C + LP=6 +C +C T IS A CONVERGENCE TOLERANCE USED IN SUBROUTINE PRAXIS. +C + T=1.0D-5 +C +C JPRINT CONTROLS PRINTED OUTPUT IN PRAXIS. +C + JPRINT=4 +C +C H IS AN ESTIMATE OF THE DISTANCE FROM THE INITIAL POINT +C TO THE SOLUTION. +C + H=1.0D0 +C +C USE BISECTION TO COMPUTE THE VALUE OF EPSMCH, "MACHINE EPSILON". +C EPSMCH IS THE SMALLEST FLOATING POINT (REAL OR DOUBLE PRECISION) +C NUMBER WHICH, WHEN ADDED TO ONE, GIVES A RESULT GREATER THAN ONE. +C + A=RZERO + B=UNITR + 10 XMID=A+(B-A)/RTWO + IF(XMID.LE.A .OR. XMID.GE.B) GO TO 20 + XPLUS=UNITR+XMID + IF(XPLUS.GT.UNITR) THEN + B=XMID + ELSE + A=XMID + ENDIF + GO TO 10 +C + 20 EPSMCH=B +C + DO 30 J=1,NMAX + X(J)=RZERO + 30 CONTINUE +C +C JRANCH = 1 TO USE BRENT'S RANDOM, +C JRANCH = 2 TO USE FUNCTION DRANDM. +C + JRANCH=1 +C + CALL RANINI(4.0D0) +C +C DSEED IS AN INITIAL SEED FOR DRANDM, +C A SUBROUTINE THAT GENERATES PSEUDORANDOM NUMBERS +C UNIFORMLY DISTRIBUTED ON (0,1). +C + DSEED=1234567.0D0 +C +C SCBD IS AN UPPER BOUND ON THE SCALE FACTORS IN PRAXIS. +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C + SCBD=1.0D0 +C +C ILLCIN IS THE INITIAL VALUE OF ILLC, +C THE FLAG THAT SIGNALS AN ILL-CONDITIONED PROBLEM. +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLCIN=1, +C OTHERWISE 0. +C + ILLCIN=0 +C +C KTM IS A CONVERGENCE SWITCH USED IN PRAXIS. +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C + KTM=1 +C + RETURN +C +C END PRASET +C + END + SUBROUTINE PRAXIS(F) +C +C PRAXIS 2.0 JUNE 1995 +C +C THE PRAXIS PACKAGE MINIMIZES THE FUNCTION F(X,N) OF N +C VARIABLES X(1),...,X(N), USING THE PRINCIPAL AXIS METHOD. +C F MUST BE A SMOOTH (CONTINUOUSLY DIFFERENTIABLE) FUNCTION. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973 (ISBN 0-13-022335-2), +C PAGES 156-167 +C +C TRANSLATED FROM ALGOL W TO A.N.S.I. 1966 STANDARD BASIC FORTRAN +C BY ROSALEE TAYLOR AND SUE PINSKI, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY (DECEMBER 1973). +C +C UPDATED TO A.N.S.I. STANDARD FORTRAN 77 BY J. P. CHANDLER +C COMPUTER SCIENCE DEPARTMENT, OKLAHOMA STATE UNIVERSITY +C +C +C SUBROUTINE PRAXIS CALLS SUBPROGRAMS +C F, MINX, RANDOM (OR DRANDM), QUAD, MINFIT, SORT. +C +C SUBROUTINE QUAD CALLS MINX. +C +C SUBROUTINE MINX CALLS FLIN. +C +C SUBROUTINE FLIN CALLS F. +C +C +C INPUT QUANTITIES (SET IN THE CALLING PROGRAM)... +C +C F FUNCTION F(X,N) TO BE MINIMIZED +C +C X(*) INITIAL GUESS OF MINIMUM +C +C N DIMENSION OF X (NOTE... N MUST BE .GE. 2) +C +C H MAXIMUM STEP SIZE +C +C T TOLERANCE +C +C EPSMCH MACHINE PRECISION +C +C JPRINT PRINT SWITCH +C +C +C OUTPUT QUANTITIES... +C +C X(*) ESTIMATED POINT OF MINIMUM +C +C FX VALUE OF F AT X +C +C NL NUMBER OF LINEAR SEARCHES +C +C NF NUMBER OF FUNCTION EVALUATIONS +C +C V(*,*) EIGENVECTORS OF A +C NEW DIRECTIONS +C +C D(*) EIGENVALUES OF A +C NEW D +C +C Z(*) SCALE FACTORS +C +C +C ON ENTRY X(*) HOLDS A GUESS. ON RETURN IT HOLDS THE ESTIMATED +C POINT OF MINIMUM, WITH (HOPEFULLY) +C ABS(ERROR) LESS THAN SQRT(EPSMCH)*ABS(X) + T, WHERE +C EPSMCH IS THE MACHINE PRECISION, THE SMALLEST NUMBER SUCH THAT +C (1 + EPSMCH) IS GREATER THAN 1. +C +C T IS A TOLERANCE. +C +C H IS THE MAXIMUM STEP SIZE, SET TO ABOUT THE MAXIMUM EXPECTED +C DISTANCE FROM THE GUESS TO THE MINIMUM. IF H IS SET TOO +C SMALL OR TOO LARGE THEN THE INITIAL RATE OF CONVERGENCE WILL +C BE SLOW. +C +C THE USER SHOULD OBSERVE THE COMMENT ON HEURISTIC NUMBERS +C AT THE BEGINNING OF THE SUBROUTINE. +C +C JPRINT CONTROLS THE PRINTING OF INTERMEDIATE RESULTS. +C IT USES SUBROUTINES FLIN, MINX, QUAD, SORT, AND MINFIT. +C IF JPRINT = 1, F IS PRINTED AFTER EVERY N+1 OR N+2 LINEAR +C MINIMIZATIONS, AND FINAL X IS PRINTED, BUT INTERMEDIATE +C X ONLY IF N IS LESS THAN OR EQUAL TO 4. +C IF JPRINT = 2, EIGENVALUES OF A AND SCALE FACTORS ARE ALSO PRINTED. +C IF JPRINT = 3, F AND X ARE PRINTED AFTER EVERY FEW LINEAR +C MINIMIZATIONS. +C IF JPRINT = 4, EIGENVECTORS ARE ALSO PRINTED. +C IF JPRINT = 5, ADDITIONAL DEBUGGING INFORMATION IS ALSO PRINTED. +C +C RANDOM RETURNS A RANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0, 1). +C +C THIS SUBROUTINE IS MACHINE-INDEPENDENT, APART FROM THE +C SPECIFICATION OF EPSMCH. WE ASSUME THAT EPSMCH**(-4) DOES NOT +C OVERFLOW (IF IT DOES THEN EPSMCH MUST BE INCREASED), AND THAT ON +C FLOATING-POINT UNDERFLOW THE RESULT IS SET TO ZERO. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER ILLC,I,IK,IM,IMU,J,K,KL,KM1,KT,K2 +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, Y,Z,E, DABS,DSQRT,ZABS,ZSQRT,DRANDM, + * HUNDRD,HUNDTH,ONE,PT9,RHALF,TEN,TENTH,TWO,ZERO, + * DF,DLDFAC,DN,F1,XF,XL,T2,RANVAL,ARG, + * VLARGE,VSMALL,XLARGE,XLDS,FXVALU,F1VALU,S,SF,SL +C + EXTERNAL F +C + DIMENSION Y(128),Z(128),E(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C +C INITIALIZATION... +C + RHALF=0.5D0 + ONE=1.0D0 + TENTH=0.1D0 + HUNDTH=0.01D0 + HUNDRD=100.0D0 + ZERO=0.0D0 + PT9=0.9D0 + TEN=10.0D0 + TWO=2.0D0 +C +C MACHINE DEPENDENT NUMBERS... +C +C ON MANY COMPUTERS, VSMALL WILL UNDERFLOW, +C AND COMPUTING XLARGE MAY CAUSE A DIVISION BY ZERO. +C IN THAT CASE, EPSMCH SHOULD BE SET EQUAL TO 1.0D-9 +C (OR POSSIBLY 1.0D-8) BEFORE CALLING PRAXIS. +C + SMALL=EPSMCH*EPSMCH + VSMALL=SMALL*SMALL + XLARGE=ONE/SMALL + VLARGE=ONE/VSMALL + XM2=ZSQRT(EPSMCH) + XM4=ZSQRT(XM2) +C +C HEURISTIC NUMBERS... +C +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLC = 1, +C OTHERWISE 0. +C +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C +C BRENT RECOMMENDED THE FOLLOWING VALUES FOR MOST PROBLEMS... +C +C SCBD=1.0 +C ILLC=0 +C KTM=1 +C +C SCBD, ILLCIN, AND KTM ARE NOW IN COMMON. +C THEY ARE INITIALIZED IN SUBROUTINE PRASET, +C AND CAN BE RESET BY THE USER AFTER CALLING PRASET. +C + ILLC=ILLCIN +C + IF(ILLC.EQ.1) THEN + DLDFAC=TENTH + ELSE + DLDFAC=HUNDTH + ENDIF +C + KT=0 + NL=0 + NF=1 + FX=F(X,N) + QF1=FX + T=SMALL+ZABS(T) + T2=T + DMIN=SMALL + IF(H.LT.HUNDRD*T) H=HUNDRD*T + XLDT=H +C + DO 20 I=1,N + DO 10 J=1,N + V(I,J)=ZERO + 10 CONTINUE + V(I,I)=ONE + 20 CONTINUE +C + QD0=ZERO + D(1)=ZERO +C +C Q0(*) AND Q1(*) ARE PREVIOUS X(*) POINTS, +C INITIALIZED IN PRAXIS, USED IN FLIN, +C AND CHANGED IN QUAD. +C + DO 30 I=1,N + Q1(I)=X(I) +C +C Q0(*) WAS NOT INITIALIZED IN BRENT'S ALGOL PROCEDURE. +C + Q0(I)=X(I) + 30 CONTINUE +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + 40 FORMAT(/' NL =',I10,5X,'NF =',I10/5X,'FX =',1PG15.7) +C + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + 50 FORMAT(/8X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF + ENDIF +C +C MAIN LOOP... +C LABEL L0... +C + 60 SF=D(1) + S=ZERO + D(1)=ZERO +C +C MINIMIZE ALONG THE FIRST DIRECTION. +C + IF(JPRINT.GE.5) WRITE(LP,70)D(1),S,FX + 70 FORMAT(/' CALL NO. 1 TO MINX.'/ + * 5X,'D(1) =',1PG15.7,5X,'S =',G15.7,5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(1,2,D(1),S,FXVALU,0,F) +C + IF(S.LE.ZERO) THEN + DO 80 I=1,N + V(I,1)=-V(I,1) + 80 CONTINUE + ENDIF +C + IF(SF.LE.PT9*D(1) .OR. PT9*SF.GE.D(1)) THEN +C + IF(N.GE.2) THEN + DO 90 I=2,N + D(I)=ZERO + 90 CONTINUE + ENDIF +C + ENDIF +C + IF(N.LT.2) GO TO 320 + DO 310 K=2,N +C + DO 100 I=1,N + Y(I)=X(I) + 100 CONTINUE +C + SF=FX + IF(KT.GT.0) ILLC=1 +C +C LABEL L1... +C + 110 KL=K + DF=ZERO +C + IF(ILLC.EQ.1) THEN +C +C TAKE A RANDOM STEP TO GET OUT OF A RESOLUTION VALLEY. +C +C PRAXIS ASSUMES THAT RANDOM (OR DRANDM) RETURNS +C A PSEUDORANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0,1), +C AND THAT ANY INITIALIZATION OF THE RANDOM NUMBER GENERATOR +C HAS ALREADY BEEN DONE. +C + DO 130 I=1,N +C + IF(JRANCH.EQ.1) THEN + CALL RANDOM(RANVAL) + ELSE + RANVAL=DRANDM(DSEED) + ENDIF +C + S=(TENTH*XLDT+T2*TEN**KT)*(RANVAL-RHALF) + Z(I)=S +C + DO 120 J=1,N + X(J)=X(J)+S*V(J,I) + 120 CONTINUE + 130 CONTINUE +C + FX=F(X,N) + NF=NF+1 +C + IF(JPRINT.GE.1) WRITE(LP,140)NF,SF,FX + 140 FORMAT(/' ***** RANDOM STEP IN PRAXIS. NF =',I11/ + * 5X,'SF =',1PG15.7,5X,'FX =',G15.7) + ENDIF +C + IF(K.GT.N) GO TO 170 + DO 160 K2=K,N + SL=FX + S=ZERO +C +C MINIMIZE ALONG NON-CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,150)K2,D(K2),S,FX + 150 FORMAT(/' CALL NO. 2 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) +C + IF(ILLC.EQ.1) THEN + S=D(K2)*(S+Z(K2))**2 + ELSE + S=SL-FX + ENDIF +C + IF(DF.LT.S) THEN + DF=S + KL=K2 + ENDIF + 160 CONTINUE +C + 170 IF(ILLC.EQ.0 .AND. DF.LT.ZABS(HUNDRD*EPSMCH*FX)) THEN +C +C NO SUCCESS WITH ILLC=0, SO TRY ONCE WITH ILLC=1 . +C + ILLC=1 +C +C GO TO L1. +C + GO TO 110 + ENDIF +C + IF(K.EQ.2 .AND. JPRINT.GT.1) THEN + WRITE(LP,180)(D(I),I=1,N) + 180 FORMAT(/' NEW D'/(1X,1PG15.7,4G15.7)) + ENDIF +C + KM1=K-1 + IF(KM1.LT.1) GO TO 210 + DO 200 K2=1,KM1 +C +C MINIMIZE ALONG CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,190)K2,D(K2),S,FX + 190 FORMAT(/' CALL NO. 3 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + S=ZERO + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) + 200 CONTINUE +C + 210 F1=FX + FX=SF +C + XLDS=ZERO + DO 220 I=1,N + SL=X(I) + X(I)=Y(I) + SL=SL-Y(I) + Y(I)=SL + XLDS=XLDS+SL*SL + 220 CONTINUE +C + XLDS=ZSQRT(XLDS) + IF(XLDS.GT.SMALL) THEN +C +C THROW AWAY THE DIRECTION KL AND MINIMIZE ALONG +C THE NEW CONJUGATE DIRECTION. +C + IK=KL-1 + IF(K.GT.IK) GO TO 250 + DO 240 IM=K,IK + I=IK-IM+K +C + DO 230 J=1,N + V(J,I+1)=V(J,I) + 230 CONTINUE +C + D(I+1)=D(I) + 240 CONTINUE +C + 250 D(K)=ZERO +C + DO 260 I=1,N + V(I,K)=Y(I)/XLDS + 260 CONTINUE +C + IF(JPRINT.GE.5) WRITE(LP,270)K,D(K),XLDS,F1 + 270 FORMAT(/' CALL NO. 4 TO MINX.'/ + * 5X,'K =',I4,5X,'D(K) =',1PG15.7,5X, + * 'XLDS =',G15.7/5X,'F1 =',G15.7) +C + F1VALU=F1 + CALL MINX(K,4,D(K),XLDS,F1VALU,1,F) +C + IF(XLDS.LE.ZERO) THEN + XLDS=-XLDS +C + DO 280 I=1,N + V(I,K)=-V(I,K) + 280 CONTINUE + ENDIF + ENDIF +C + XLDT=DLDFAC*XLDT + IF(XLDT.LT.XLDS) XLDT=XLDS +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + ENDIF + ENDIF +C + T2=ZERO + DO 290 I=1,N + T2=T2+X(I)**2 + 290 CONTINUE + T2=XM2*ZSQRT(T2)+T +C +C SEE IF THE STEP LENGTH EXCEEDS HALF THE TOLERANCE. +C + IF(XLDT.GT.RHALF*T2) THEN + KT=0 + ELSE + KT=KT+1 + ENDIF +C +C IF(...) GO TO L2 +C + IF(KT.GT.KTM) GO TO 550 +C + IF(NF.GE.NFMAX) THEN + WRITE(LP,300)NFMAX + 300 FORMAT(/' IN PRAXIS, NF REACHED THE LIMIT NFMAX =',I11/ + * 5X,'THIS IS AN ABNORMAL TERMINATION.'/ + * 5X,'THE FUNCTION HAS NOT BEEN MINIMIZED AND', + * ' THE RESULTING X(*) VECTOR SHOULD NOT BE USED.') + GO TO 550 + ENDIF +C + 310 CONTINUE +C +C TRY QUADRATIC EXTRAPOLATION IN CASE WE ARE STUCK IN A CURVED VALLEY. +C + 320 CALL QUAD(F) +C + DN=ZERO + DO 330 I=1,N + D(I)=ONE/ZSQRT(D(I)) + IF(DN.LT.D(I)) DN=D(I) + 330 CONTINUE +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,340) + 340 FORMAT(/' NEW DIRECTIONS') +C + DO 360 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 350 FORMAT(1X,I5,4X,1PG15.7,4G15.7/(10X,5G15.7)) + 360 CONTINUE + ENDIF +C + DO 380 J=1,N +C + S=D(J)/DN + DO 370 I=1,N + V(I,J)=S*V(I,J) + 370 CONTINUE + 380 CONTINUE +C + IF(SCBD.GT.ONE) THEN +C +C SCALE THE AXES TO TRY TO REDUCE THE CONDITION NUMBER. +C + S=VLARGE + DO 400 I=1,N +C + SL=ZERO + DO 390 J=1,N + SL=SL+V(I,J)**2 + 390 CONTINUE +C + Z(I)=ZSQRT(SL) + IF(Z(I).LT.XM4) Z(I)=XM4 + IF(S.GT.Z(I)) S=Z(I) + 400 CONTINUE +C + DO 410 I=1,N + SL=S/Z(I) + Z(I)=ONE/SL +C + IF(Z(I).GT.SCBD) THEN + SL=ONE/SCBD + Z(I)=SCBD + ENDIF +C +C IT APPEARS THAT THERE ARE TWO MISSING END; STATEMENTS +C AT THIS POINT IN BRENT'S LISTING. +C + 410 CONTINUE + ENDIF +C +C TRANSPOSE V FOR MINFIT. +C + IF(N.LT.2) GO TO 440 + DO 430 I=2,N +C + IMU=I-1 + DO 420 J=1,IMU + S=V(I,J) + V(I,J)=V(J,I) + V(J,I)=S + 420 CONTINUE + 430 CONTINUE +C +C FIND THE SINGULAR VALUE DECOMPOSITION OF V. +C THIS GIVES THE EIGENVALUES AND PRINCIPAL AXES +C OF THE APPROXIMATING QUADRATIC FORM +C WITHOUT SQUARING THE CONDITION NUMBER. +C + 440 CALL MINFIT(N,EPSMCH,VSMALL,V,D,E,NMAX,LP) +C + IF(SCBD.GT.ONE) THEN +C +C UNSCALING... +C + DO 460 I=1,N +C + S=Z(I) + DO 450 J=1,N + V(I,J)=S*V(I,J) + 450 CONTINUE + 460 CONTINUE +C + DO 490 I=1,N +C + S=ZERO + DO 470 J=1,N + S=S+V(J,I)**2 + 470 CONTINUE + S=ZSQRT(S) +C + D(I)=S*D(I) +C + S=ONE/S + DO 480 J=1,N + V(J,I)=S*V(J,I) + 480 CONTINUE + 490 CONTINUE + ENDIF +C + DO 500 I=1,N +C + IF(DN*D(I).GT.XLARGE) THEN + D(I)=VSMALL + ELSE IF(DN*D(I).LT.SMALL) THEN + D(I)=VLARGE + ELSE + D(I)=ONE/(DN*D(I))**2 + ENDIF + 500 CONTINUE +C +C SORT THE NEW EIGENVALUES AND EIGENVECTORS. +C + CALL SORT +C + DMIN=D(N) + IF(DMIN.LT.SMALL) DMIN=SMALL +C + IF(XM2*D(1).GT.DMIN) THEN + ILLC=1 + ELSE + ILLC=0 + ENDIF +C + IF(JPRINT.GT.1 .AND. SCBD.GT.ONE) THEN + WRITE(LP,510)(Z(I),I=1,N) + 510 FORMAT(/' SCALE FACTORS'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.1) THEN + WRITE(LP,520)(D(I),I=1,N) + 520 FORMAT(/' EIGENVALUES OF A'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,530) + 530 FORMAT(/' EIGENVECTORS OF A') +C + DO 540 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 540 CONTINUE + ENDIF +C +C GO BACK TO THE MAIN LOOP. +C GO TO L0 +C +C HANDLE THE CASE N .EQ. 1 IN AN AD HOC WAY. +C (BRENT DID NOT PROVIDE FOR THIS CASE.) +C + IF(N.GE.2) GO TO 60 +C +C LABEL L2... +C + 550 IF(JPRINT.GT.0) THEN + WRITE(LP,560)(X(I),I=1,N) + 560 FORMAT(//7X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF +C + FX=F(X,N) +C + IF(JPRINT.GE.0) WRITE(LP,570)FX,NL,NF + 570 FORMAT(/' EXIT PRAXIS. FX =',1PG25.17,5X,'NL =',I8, + * 5X,'NF =',I9) +C + RETURN +C +C END PRAXIS +C + END + SUBROUTINE QUAD(F) +C +C THIS SUBROUTINE LOOKS FOR THE MINIMUM ALONG +C A CURVE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGE 161 +C +C SUBROUTINE QUAD IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, DSQRT,ZSQRT,ARG, + * ONE,QA,QB,QC,S,TWO,XL,ZERO,QF1VAL +C + EXTERNAL F +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) +C + ZERO=0.0D0 + ONE=1.0D0 +C + S=FX + FX=QF1 + QF1=S + QD1=ZERO +C + DO 10 I=1,N + S=X(I) + XL=Q1(I) + X(I)=XL + Q1(I)=S + QD1=QD1+(S-XL)**2 + 10 CONTINUE +C + QD1=ZSQRT(QD1) + XL=QD1 + S=ZERO +C + IF(QD0.GT.ZERO .AND. QD1.GT.ZERO .AND. NL.GE.3*N*N) THEN +C + IF(JPRINT.GE.1) WRITE(LP,20)NF,QD0,QD1,FX,QF1 + 20 FORMAT(/' ***** CALL MINX FROM QUAD. NF =',I11/ + * 5X,'QD0 =',1PG15.7,5X,'QD1 =',G15.7/ + * 5X,'FX =',G15.7,5X,'QF1 =',G15.7) +C + QF1VAL=QF1 + CALL MINX(0,2,S,XL,QF1VAL,1,F) + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) + ELSE + FX=QF1 + QA=ZERO + QB=ZERO + QC=ONE + ENDIF +C + QD0=QD1 +C + DO 30 I=1,N + S=Q0(I) + Q0(I)=X(I) + X(I)=QA*S+QB*X(I)+QC*Q1(I) + 30 CONTINUE +C + RETURN +C +C END QUAD +C + END + SUBROUTINE MINX(J,NITS,D2,X1,F1,IFK,F) +C +C SUBROUTINE MINX MINIMIZES F FROM X IN THE DIRECTION V(*,J) +C UNLESS J IS LESS THAN 1, WHEN A QUADRATIC SEARCH IS DONE IN +C THE PLANE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE MINX IS CALLED BY SUBROUTINES PRAXIS AND QUAD. +C +C D2 AND X1 RETURN RESULTS. +C J, NITS, F1 AND IFK ARE VALUE PARAMETERS THAT RETURN NOTHING. +C DO NOT SEND A COMMON VARIABLE TO MINX FOR PARAMETER F1. +C +C +C D2 IS AN APPROXIMATION TO HALF OF +C THE SECOND DERIVATIVE OF F (OR ZERO). +C +C X1 IS AN ESTIMATE OF DISTANCE TO MINIMUM, +C RETURNED AS THE DISTANCE FOUND. +C +C IF IFK = 1 THEN F1 IS FLIN(X1), OTHERWISE X1 AND F1 ARE +C IGNORED ON ENTRY UNLESS FINAL FX IS GREATER THAN F1. +C +C NITS CONTROLS THE NUMBER OF TIMES AN ATTEMPT IS MADE TO +C HALVE THE INTERVAL. +C + EXTERNAL F +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER IFK,J,NITS, I,IDZ,K +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION D2,X1, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * HUNDTH,RHALF,TWO,ZERO, + * DENOM,D1,FM,F0,F1,F2,S,SF1,SX1,T2,XM,X2 +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) + ZABS(ARG)=DABS(ARG) +C + HUNDTH=0.01D0 + ZERO=0.0D0 + TWO=2.0D0 + RHALF=0.5D0 +C + SF1=F1 + SX1=X1 + K=0 + XM=ZERO + FM=FX + F0=FX +C + IF(D2.LT.EPSMCH) THEN + IDZ=1 + ELSE + IDZ=0 + ENDIF +C +C FIND THE STEP SIZE. +C + S=ZERO + DO 10 I=1,N + S=S+X(I)**2 + 10 CONTINUE + S=ZSQRT(S) +C + IF(IDZ.EQ.1) THEN + DENOM=DMIN + ELSE + DENOM=D2 + ENDIF +C + T2=XM4*ZSQRT(ZABS(FX)/DENOM+S*XLDT)+XM2*XLDT + S=XM4*S+T + IF(IDZ.EQ.1 .AND. T2.GT.S) T2=S + IF(T2.LT.SMALL) T2=SMALL + IF(T2.GT.HUNDTH*H) T2=HUNDTH*H +C + IF(IFK.EQ.1 .AND. F1.LE.FM) THEN + XM=X1 + FM=F1 + ENDIF +C + IF(IFK.EQ.0 .OR. ZABS(X1).LT.T2) THEN +C + IF(X1.GE.ZERO) THEN + X1=T2 + ELSE + X1=-T2 + ENDIF +C + CALL FLIN(X1,J,F,F1) + ENDIF +C + IF(F1.LT.FM) THEN + XM=X1 + FM=F1 + ENDIF +C +C LABEL L0... +C + 20 IF(IDZ.EQ.1) THEN +C +C EVALUATE FLIN AT ANOTHER POINT, +C AND ESTIMATE THE SECOND DERIVATIVE. +C + IF(F0.LT.F1) THEN + X2=-X1 + ELSE + X2=TWO*X1 + ENDIF +C + CALL FLIN(X2,J,F,F2) +C + IF(F2.LE.FM) THEN + XM=X2 + FM=F2 + ENDIF +C + D2=(X2*(F1-F0)-X1*(F2-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,30)X1,X2,F0,F1,F2,D2 + 30 FORMAT(/' COMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'F1 =',G15.7,5X,'F2 =',G15.7/ + * 5X,'D2 =',G15.7) + ENDIF +C +C ESTIMATE THE FIRST DERIVATIVE AT 0. +C + D1=(F1-F0)/X1-X1*D2 + IDZ=1 +C +C PREDICT THE MINIMUM. +C + IF(D2.LE.SMALL) THEN +C + IF(D1.LT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF +C + ELSE + X2=-RHALF*D1/D2 + ENDIF +C + IF(ZABS(X2).GT.H) THEN +C + IF(X2.GT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF + ENDIF +C +C EVALUATE F AT THE PREDICTED MINIMUM. +C LABEL L1... +C + 40 CALL FLIN(X2,J,F,F2) +C + IF(K.LT.NITS .AND. F2.GT.F0) THEN +C +C NO SUCCESS, SO TRY AGAIN. +C + K=K+1 +C +C IF(...) GO TO L0 +C + IF(F0.LT.F1 .AND. X1*X2.GT.ZERO) GO TO 20 + X2=X2/TWO +C +C GO TO L1 +C + GO TO 40 +C + ENDIF +C +C INCREMENT THE ONE-DIMENSIONAL SEARCH COUNTER. +C + NL=NL+1 +C + IF(F2.GT.FM) THEN + X2=XM + ELSE + FM=F2 + ENDIF +C +C GET A NEW ESTIMATE OF THE SECOND DERIVATIVE. +C + IF(ZABS(X2*(X2-X1)).GT.SMALL) THEN + D2=(X2*(F1-F0)-X1*(FM-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,50)X1,X2,F0,FM,F1,D2 + 50 FORMAT(/' RECOMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'FM =',G15.7,5X,'F1 =',G15.7/ + * 5X,'D2 =',G15.7) +C + ELSE IF(K.GT.0) THEN + D2=ZERO +C + IF(JPRINT.GE.5) WRITE(LP,60) + 60 FORMAT(/' SET D2=0 IN SUBROUTINE MINX.') + ELSE + D2=D2 + ENDIF +C + IF(D2.LE.SMALL) THEN + D2=SMALL +C + IF(JPRINT.GE.5) WRITE(LP,70)D2 + 70 FORMAT(/' SET D2=SMALL=',1PG15.7,' IN SUBROUTINE MINX.') + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,80)X1,X2,FX,FM,SF1 + 80 FORMAT(/' SUBROUTINE MINX. X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'FX =',G15.7,5X,'FM =',G15.7,5X,'SF1 =',G15.7) +C + X1=X2 + FX=FM + IF(SF1.LT.FX) THEN + FX=SF1 + X1=SX1 + ENDIF +C +C UPDATE X FOR A LINEAR SEARCH BUT NOT FOR A PARABOLIC SEARCH. +C + IF(J.GT.0) THEN +C + DO 90 I=1,N + X(I)=X(I)+X1*V(I,J) + 90 CONTINUE + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,100)D2,X1,F1,FX + 100 FORMAT(/' LEAVE SUBROUTINE MINX.'/ + * 5X,'D2 =',1PG15.7,5X,'X1 =',G15.7,5X,'F1 =',G15.7/ + * 5X,'FX =',G15.7) +C + RETURN +C +C END MINX +C + END + SUBROUTINE FLIN(XL,J,F,FLN) +C +C FLIN IS A FUNCTION OF ONE VARIABLE XL WHICH IS MINIMIZED BY +C SUBROUTINE MINX. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE FLIN IS CALLED BY SUBROUTINE MINX. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J, I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION XL,F,FLN, TT, QA,QB,QC +C + DIMENSION TT(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + IF(J.GT.0) THEN +C +C LINEAR SEARCH... +C + DO 10 I=1,N + TT(I)=X(I)+XL*V(I,J) + 10 CONTINUE +C + ELSE +C +C SEARCH ALONG A PARABOLIC SPACE CURVE. +C + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) +C + DO 20 I=1,N + TT(I)=QA*Q0(I)+QB*X(I)+QC*Q1(I) + 20 CONTINUE + ENDIF +C +C INCREMENT FUNCTION EVALUATION COUNTER. +C + NF=NF+1 + FLN=F(TT,N) +C + RETURN +C +C END FLIN +C + END + SUBROUTINE MINFIT(N,EPS,TOL,AB,Q,E,NMAX,LP) +C +C AN IMPROVED VERSION OF MINFIT, RESTRICTED TO M=N, P=0. +C SEE GOLUB AND REINSCH (1970). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 156-158 +C +C G. H. GOLUB AND C. REINSCH, +C "SINGULAR VALUE DECOMPOSITION AND LEAST SQUARES SOLUTIONS', +C NUMERISCHE MATHEMATIK 14 (1970) PAGES 403-420 +C +C THE SINGULAR VALUES OF THE ARRAY AB ARE RETURNED IN Q, +C AND AB IS OVERWRITTEN WITH THE ORTHOGONAL MATRIX V SUCH THAT +C U.DIAG(Q)=AB.V, WHERE U IS ANOTHER ORTHOGONAL MATRIX. +C +C SUBROUTINE MINFIT IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NMAX,LP, + * I,II,J,JTHIRT,K,KK,KT,L,LL2,LPI,L2 +C + DOUBLE PRECISION EPS,TOL,AB,Q,E, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * C,DENOM,F,G,H,ONE,X,Y,Z,ZERO,S,TWO +C + DIMENSION AB(NMAX,N),Q(N),E(N) +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C + JTHIRT=30 +C + ZERO=0.0D0 + ONE=1.0D0 + TWO=2.0D0 +C +C HOUSEHOLDER'S REDUCTION TO BIDIAGONAL FORM... +C + X=ZERO + G=ZERO +C + DO 140 I=1,N + E(I)=G + S=ZERO + L=I+1 +C + DO 10 J=I,N + S=S+AB(J,I)**2 + 10 CONTINUE +C + IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I)=F-G +C + IF(L.GT.N) GO TO 60 + DO 50 J=L,N +C + F=ZERO + IF(I.GT.N) GO TO 30 + DO 20 K=I,N + F=F+AB(K,I)*AB(K,J) + 20 CONTINUE + 30 F=F/H +C + IF(I.GT.N) GO TO 50 + DO 40 K=I,N + AB(K,J)=AB(K,J)+F*AB(K,I) + 40 CONTINUE + 50 CONTINUE + ENDIF +C + 60 Q(I)=G + S=ZERO +C + IF(I.LE.N) THEN +C + IF(L.GT.N) GO TO 80 + DO 70 J=L,N + S=S+AB(I,J)**2 + 70 CONTINUE + ENDIF +C + 80 IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I+1) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I+1)=F-G + IF(L.GT.N) GO TO 130 + DO 90 J=L,N + E(J)=AB(I,J)/H + 90 CONTINUE +C + DO 120 J=L,N +C + S=ZERO + DO 100 K=L,N + S=S+AB(J,K)*AB(I,K) + 100 CONTINUE +C + DO 110 K=L,N + AB(J,K)=AB(J,K)+S*E(K) + 110 CONTINUE + 120 CONTINUE + ENDIF +C + 130 Y=ZABS(Q(I))+ZABS(E(I)) +C + IF(Y.GT.X) X=Y + 140 CONTINUE +C +C ACCUMULATION OF RIGHT-HAND TRANSFORMATIONS... +C + DO 210 II=1,N + I=N-II+1 +C + IF(G.NE.ZERO) THEN + H=AB(I,I+1)*G +C + IF(L.GT.N) GO TO 200 + DO 150 J=L,N + AB(J,I)=AB(I,J)/H + 150 CONTINUE +C + DO 180 J=L,N +C + S=ZERO + DO 160 K=L,N + S=S+AB(I,K)*AB(K,J) + 160 CONTINUE +C + DO 170 K=L,N + AB(K,J)=AB(K,J)+S*AB(K,I) + 170 CONTINUE + 180 CONTINUE + ENDIF +C + IF(L.GT.N) GO TO 200 + DO 190 J=L,N + AB(J,I)=ZERO + AB(I,J)=ZERO + 190 CONTINUE +C + 200 AB(I,I)=ONE + G=E(I) + L=I + 210 CONTINUE +C +C DIAGONALIZATION OF THE BIDIAGONAL FORM... +C + EPS=EPS*X + DO 330 KK=1,N + K=N-KK+1 + KT=0 +C +C LABEL TESTFSPLITTING... +C + 220 KT=KT+1 +C + IF(KT.GT.JTHIRT) THEN + E(K)=ZERO + WRITE(LP,230) + 230 FORMAT(' QR FAILED.') + ENDIF +C + DO 240 LL2=1,K + L2=K-LL2+1 + L=L2 +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(E(L)).LE.EPS) GO TO 270 +C +C IF(...) GO TO CANCELLATION +C + IF(ZABS(Q(L-1)).LE.EPS) GO TO 250 + 240 CONTINUE +C +C CANCELLATION OF E(L) IF L IS GREATER THAN 1... +C LABEL CANCELLATION... +C + 250 C=ZERO + S=ONE + IF(L.GT.K) GO TO 270 + DO 260 I=L,K + F=S*E(I) + E(I)=C*E(I) +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(F).LE.EPS) GO TO 270 + G=Q(I) +C + IF(ZABS(F).LT.ZABS(G)) THEN + H=ZABS(G)*ZSQRT(ONE+(F/G)**2) + ELSE IF(F.NE.ZERO) THEN + H=ZABS(F)*ZSQRT(ONE+(G/F)**2) + ELSE + H=ZERO + ENDIF +C + Q(I)=H +C + IF(H.EQ.ZERO) THEN + H=ONE + G=ONE + ENDIF +C +C THE ABOVE REPLACES Q(I) AND H BY SQUARE ROOT OF (G*G+F*F) +C WHICH MAY GIVE INCORRECT RESULTS IF THE SQUARES UNDERFLOW OR IF +C F = G = 0 . +C + C=G/H + S=-F/H + 260 CONTINUE +C +C LABEL TESTFCONVERGENCE... +C + 270 Z=Q(K) +C +C IF(...) GO TO CONVERGENCE +C + IF(L.EQ.K) GO TO 310 +C +C SHIFT FROM BOTTOM 2*2 MINOR. +C + X=Q(L) + Y=Q(K-1) + G=E(K-1) + H=E(K) + F=((Y-Z)*(Y+Z)+(G-H)*(G+H))/(TWO*H*Y) + G=ZSQRT(F*F+ONE) +C + IF(F.LT.ZERO) THEN + DENOM=F-G + ELSE + DENOM=F+G + ENDIF +C + F=((X-Z)*(X+Z)+H*(Y/DENOM-H))/X +C +C NEXT QR TRANSFORMATION... +C + S=ONE + C=ONE + LPI=L+1 + IF(LPI.GT.K) GO TO 300 + DO 290 I=LPI,K + G=E(I) + Y=Q(I) + H=S*G + G=G*C +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + E(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=X*C+G*S + G=-X*S+G*C + H=Y*S + Y=Y*C +C + DO 280 J=1,N + X=AB(J,I-1) + Z=AB(J,I) + AB(J,I-1)=X*C+Z*S + AB(J,I)=-X*S+Z*C + 280 CONTINUE +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + Q(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=C*G+S*Y + X=-S*G+C*Y + 290 CONTINUE +C + 300 E(L)=ZERO + E(K)=F + Q(K)=X +C +C GO TO TESTFSPLITTING +C + GO TO 220 +C +C LABEL CONVERGENCE... +C + 310 IF(Z.LT.ZERO) THEN +C +C Q(K) IS MADE NON-NEGATIVE. +C + Q(K)=-Z + DO 320 J=1,N + AB(J,K)=-AB(J,K) + 320 CONTINUE + ENDIF + 330 CONTINUE +C + RETURN +C +C END MINFIT +C + END + SUBROUTINE SORT +C +C THIS SUBROUTINE SORTS THE ELEMENTS OF D +C AND THE CORRESPONDING COLUMNS OF V INTO DESCENDING ORDER. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 158-159 +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I,IPI,J,K,NMI +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION S +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + NMI=N-1 + IF(NMI.LT.1) GO TO 50 + DO 40 I=1,NMI + K=I + S=D(I) + IPI=I+1 + IF(IPI.GT.N) GO TO 20 +C + DO 10 J=IPI,N +C + IF(D(J).GT.S) THEN + K=J + S=D(J) + ENDIF + 10 CONTINUE +C + 20 IF(K.GT.I) THEN + D(K)=D(I) + D(I)=S +C + DO 30 J=1,N + S=V(J,I) + V(J,I)=V(J,K) + V(J,K)=S + 30 CONTINUE + ENDIF + 40 CONTINUE +C + 50 RETURN +C +C END SORT +C + END + SUBROUTINE RANINI(RVALUE) +C +C SUBROUTINE RANINI PERFORMS INITIALIZATION FOR SUBROUTINE RANDOM. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C + INTEGER JRAN2,I +C + DOUBLE PRECISION RVALUE,R,RAN3,DMOD,DABS,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + R=DMOD(DABS(RVALUE),8190.0D0)+1 + JRAN2=127 +C + 10 IF(JRAN2.GT.0) THEN + JRAN2=JRAN2-1 + RAN1=-2.0D0**55 +C + DO 20 I=1,7 + R=DMOD(1756.0D0*R,8191.0D0) + RAN1=(RAN1+(R-DMOD(R,32.0D0))/32.0D0)/256.0D0 + 20 CONTINUE +C + RAN3(JRAN2+1)=RAN1 + GO TO 10 + ENDIF +C + RETURN +C +C END RANINI +C + END + SUBROUTINE RANDOM(RANVAL) +C +C SUBROUTINE RANDOM RETURNS A DOUBLE PRECISION PSEUDORANDOM NUMBER +C UNIFORMLY DISTRIBUTED IN (0,1) (INCLUDING 0 BUT NOT 1). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C +C BEFORE THE FIRST CALL TO RANDOM, THE USER MUST +C CALL RANINI(R) ONCE (ONLY) WITH R A DOUBLE PRECISION NUMBER +C EQUAL TO ANY INTEGER VALUE. +C BRENT (PAGE 166) USED THE EQUIVALENT OF +C CALL RANINI(4.0D0) . +C +C THE ALGORITHM USED IN SUBROUTINE RANDOM RETURNS X(N)/2**56, +C WHERE X(N) = X(N-1) + X(N-127) (MOD 2**56) . +C SINCE (1 + X + X**127) IS PRIMITIVE (MOD 2), +C THE PERIOD IS AT LEAST (2**127 - 1), WHICH EXCEEDS 10**38. +C +C SEE "SEMINUMERICAL ALGORITHMS", VOLUME 2 OF +C "THE ART OF COMPUTER PROGRAMMING" BY DONALD E. KNUTH, +C ADDISON-WESLEY 1969, PAGES 26, 34, AND 464. +C +C X(N) IS STORED IN DOUBLE PRECISION AS RAN3 = X(N)/2**56 - 1/2, +C AND ALL DOUBLE PRECISION ARITHMETIC IS EXACT. +C + INTEGER JRAN2 +C + DOUBLE PRECISION RANVAL,RAN3,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + IF(JRAN2.EQ.0) THEN + JRAN2=126 + ELSE + JRAN2=JRAN2-1 + ENDIF +C + RAN1=RAN1+RAN3(JRAN2+1) + IF(RAN1.LT.0.0D0) THEN + RAN1=RAN1+0.5D0 + ELSE + RAN1=RAN1-0.5D0 + ENDIF +C + RAN3(JRAN2+1)=RAN1 + RANVAL=RAN1+0.5D0 +C + RETURN +C +C END RANDOM +C + END + DOUBLE PRECISION FUNCTION DRANDM(DL) +C +C SIMPLE PORTABLE PSEUDORANDOM NUMBER GENERATOR. +C +C DRANDM RETURNS FUNCTION VALUES THAT ARE PSEUDORANDOM +C NUMBERS UNIFORMLY DISTRIBUTED ON THE INTERVAL (0,1). +C +C 'NUMERICAL MATHEMATICS AND COMPUTING' BY WARD CHENEY AND +C DAVID KINCAID, BROOKS/COLE PUBLISHING COMPANY +C (FIRST EDITION, 1980), PAGE 203 +C +C AT THE BEGINNING OF EXECUTION, OR WHENEVER A NEW SEQUENCE IS +C TO BE INITIATED, SET DL EQUAL TO AN INTEGER VALUE BETWEEN +C 1.0D0 AND 2147483646.0D0, INCLUSIVE. DO THIS ONLY ONCE. +C THEREAFTER, DO NOT SET OR ALTER DL IN ANY WAY. +C FUNCTION DRANDM WILL MODIFY DL FOR ITS OWN PURPOSES. +C +C DRANDM USES A MULTIPLICATIVE CONGRUENTIAL METHOD. +C THE NUMBERS GENERATED BY DRANDM SUFFER FROM THE PARALLEL +C PLANES DEFECT DISCOVERED BY G. MARSAGLIA, AND SHOULD NOT BE +C USED WHEN HIGH-QUALITY RANDOMNESS IS REQUIRED. IN THAT +C CASE, USE A "SHUFFLING" METHOD. +C + DOUBLE PRECISION DL,DMOD +C + 10 DL=DMOD(16807.0D0*DL,2147483647.0D0) + DRANDM=DL/2147483647.0D0 + IF(DRANDM.LE.0.0D0 .OR. DRANDM.GE.1.0D0) GO TO 10 + RETURN + END diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.txt b/gnuradio-core/src/gen_interpolator_taps/praxis.txt new file mode 100644 index 00000000..5c4b8155 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.txt @@ -0,0 +1,176 @@ +Brent's PRAXIS minimizer is available in FORTRAN 77. July 1995 + +"Algorithms for Minimization Without Derivatives" +by Richard P. Brent, Prentice-Hall, 1973 +ISBN: 0-13-022335-2 + +This book by Brent was a groundbreaking effort. +(I believe that it was his Ph.D. thesis at Stanford.) +His algorithms for finding roots and minima in +one dimension have good performance for typical problems +and guaranteed performance in the worst case. +(A later rootfinder by J. Bus and Dekker gave +a much lower bound for the worst case, +but no better performance in typical problems.) +These algorithms were implemented in both ALGOL W +and FORTRAN by Brent, and have been used fairly widely. + +Brent also gave a multi-dimensional minimization algorithm, +PRAXIS, but only shows an implementation in ALGOL W. +This routine has not been widely used, at least in the U.S. +The PRAXIS package has been translated into FORTRAN +by Rosalee Taylor, Sue Pinski, and me, and +I am making it available via anonymous ftp for use as +freeware (please do not remove our names). + + ftp a.cs.okstate.edu + anonymous + [enter your userid as password] + cd /pub/jpc + get praxis.f + quit + + +Brent's method and its performance + +Newton's method for minimization can find the minimum of a +quadratic function in one iteration, but is sometimes not +convenient to use. In the 1960s, several researchers found +iterative methods that solve quadratic problems exactly in a +finite number of steps. C. S. Smith (1962) and +M. J. D. Powell (1964) devised methods +that had this property and did not require derivatives. +G. W. Stewart modified the Davidon-Fletcher-Powell quasi-Newton +method to use finite difference approximations to approximate +the gradient. Powell's method, or later versions by Zangwill, +were the most successful of the early direct search methods +having the property of finite convergence on quadratic functions. + +Powell's method was programmed at Harwell as subroutine VA04A, +and is available as file va04a.f in the same directory as praxis.f. +VA04A is not extremely robust, and can give underflow, overflow, +or division by zero. va04a.f has several documented patches in it +where I tried to get around various abnormal terminations. +I do not recommend VA04A very strongly. + +Brent's PRAXIS added orthogonalization and several other features +to Powell's method. Brent also dealt carefully with roundoff. + +William H. Press et al. in their book "Numerical Recipes" +comment that +"Brent has a number of other cute tricks up his sleeve, +and his modification of Powell's method is probably +the best presently known." + +Roger Fletcher was less enthusiastic in his review of Brent's book +in The Computer Journal 16 (1973) 314: +"... I am not convinced that the modifications to Powell's +method are the best. Use of eigenvector directions +is not independent of scale changes to the variables, +and the use of searches in random directions is hardly +appealing. Nonetheless all the algorithms are demonstrated +to be competitive by numerical examples." + +The methods of Powell, Brent, et al. require that the function +for which a local minimum is sought must be smooth; +that is, the function and all of its first partial derivatives +must be continuous. + +Brent compared his method to the methods of Powell, of Stewart, +and of Davies, Swann, and Campey. Indirectly, he compared it +also to the Davidon-Fletcher-Powell quasi-Newton method. +He found that his method was about as efficient as the best +of these in most cases, and that it was more robust than others +in some cases. (Pages 139-155 in Brent's book give fair +comparisons to other methods. The results in Table 7.1 on +page 138 are correct, but do not include progress all the way +to convergence, and are therefore not too useful.) + +On least squares problems, all of these general minimization +methods are likely to be inefficient compared to least squares +methods such as the Gauss-Newton or Marquardt methods. + +In addition to the scale dependence that Fletcher deplored, +PRAXIS also had the disadvantage that it required N, the number +of parameters, to be greater than or equal to two. +The failure to handle N=1 is an unnecessary and pointless limitation. + + +The FORTRAN version + +We have followed Brent's PRAXIS rather closely. +I have added a patch to try to handle the case N=1, +and an option to use a simpler pseudorandom number generator, +DRANDM. The handling of N=1 is not guaranteed. + +The user writes a main program and a function subprogram +to compute the function to be minimized. +All communication between the user's main program and PRAXIS +is done via COMMON, except for an EXTERNAL parameter giving +the name of the function subprogram. +The disadvantages of using COMMON are at least two-fold: + + 1) Arrays cannot have adjustable dimensions. + + 2) Because some actual parameters are COMMON variables, + the FORTRAN version of PRAXIS probably will not pass + the Bell Labs PFORT package as being 100% standard FORTRAN. + Nevertheless, this usage will not cause any conflict in + any commercial FORTRAN compiler ever written. + (If it does, I will apologize and rewrite PRAXIS.) + +The advantage of using COMMON is that it is not necessary to pass +about fifteen more parameters every time the user calls PRAXIS. +At present all arrays are dimensioned (20) or (20,20), +and this can easily be increased using two simple global editing +commands. (In this case, increase the value of NMAX.) + +There are no DATA statements in PRAXIS, and it was not necessary +to use any SAVE statements. + +We have used DOUBLE PRECISION for all floating point computations, +as Brent did. We recommend using DOUBLE PRECISION on all computers +except possibly Cray computers, in which REAL is reasonably precise. +The value of "machine epsilon" is computed in subroutine PRASET +using bisection, and is called EPSMCH. +Brent computes EPSMCH**4 and 1/EPSMCH**4 in PRAXIS, +and uses these quantities later. +Because EPSMCH in DOUBLE PRECISION is less than 1E-16, +these fourth powers of EPSMCH and 1/EPSMCH will underflow +and overflow on such machines as VAXs and PCs, +which have a range of only about 1E38, grossly insufficient +for scientific computation. For such machines, Brent recommends +increasing the value of EPSMCH. +EPSMCH=1E-9 or possibly even 1E-8 might be necessary. +A better solution would be to eliminate the explicit use of +these fourth powers, accomplishing the same result implicitly. + +A "bug bounty" of $10 U.S. will be paid by me for the first +notification of any error in PRAXIS. +The same bounty also applies to any substantive poor design +choice (having no redeeming advantages whatever) in the FORTRAN +package. (The patch for N=1 is not included, although any +suggested improvements in that will be considered carefully.) + +praxis.f includes test software to run any of the test problems +that Brent ran, and is set to run at least one case of each problem. +I have run these on an IBM 3090, essentially the same +architecture that Brent used, and obtained essentially the same +results that Brent shows on pages 140-155. The Hilbert problem with +N=12, for which Brent shows no termination results and for which +the results in Table 7.1 are correct but not relevant, +runs a long time; I cut it off at 3000 function evaluations. +I don't particularly like Brent's convergence criterion, +which allows this sort of extremely slow creeping progress, +but have not modified it. + +Please notify me of any problems with this software, +or of any suggested modifications. + +John Chandler +Computer Science Department +Oklahoma State University +Stillwater, Oklahoma 74078, U.S.A. +(405) 744-5676 +jpc@a.cs.okstate.edu + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.c b/gnuradio-core/src/gen_interpolator_taps/simpson.c new file mode 100644 index 00000000..fc6dd6c2 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.c @@ -0,0 +1,76 @@ +/* -*- c -*- */ +#include +#include + +#define EPS (1.0e-5) +#define JMAX 16 + +/* + * Compute the Nth stage of refinement of an extended trapezoidal + * rule. FUNC is input as a pointer to a function to be integrated + * between limits A and B. When called with N = 1, the routine + * returns the crudest estimate of the integral from A to B of f(x) + * dx. Subsequent calls with N=2,3,... (in that sequential order) + * will improve the accuracy by adding 2**(N-2) additional interior + * points. + * + * N.B., this function contains static state and IS NEITHER RENTRANT + * NOR THREAD SAFE! + */ + +double +trapzd (double (*func)(double), + double a, double b, + int n) +{ + long double x, tnm, sum, del; + static long double s; + static int it; + int j; + + if (n == 1){ + it = 1; /* # of points to add on the next call */ + s = 0.5 * (b - a) * (func(a) + func(b)); + return s; + } + else { + tnm = it; + del = (b-a)/tnm; /* this is the spacing of the points to be added */ + x = a + 0.5*del; + for (sum = 0.0, j = 1; j <= it; j++, x += del) + sum += func(x); + it *= 2; + s = 0.5 * (s + (b-a) * sum/tnm); /* replace s by it's refined value */ + return s; + } +} + +/* + * Returns the integral of the function FUNC from A to B. The + * parameters EPS can be set to the desired fractional accuracy and + * JMAX so that 2**(JMAX-1) is the maximum allowed number of steps. + * Integration is performed by Simpson's rule. + */ + +double +qsimp (double (*func)(double), + double a, /* lower limit */ + double b) /* upper limit */ +{ + int j; + long double s, st, ost, os; + + ost = os = -1.0e30; + for (j = 1; j <= JMAX; j++){ + st = trapzd (func, a, b, j); + s = (4.0 * st - ost)/3.0; + if (fabs (s - os) < EPS * fabs(os)) + return s; + os = s; + ost = st; + } + fprintf (stderr, "Too many steps in routine QSIMP\n"); + // exit (1); + return s; +} + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.h b/gnuradio-core/src/gen_interpolator_taps/simpson.h new file mode 100644 index 00000000..68774f9a --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.h @@ -0,0 +1,3 @@ +double qsimp (double (*func)(double), + double a, double b); + diff --git a/gnuradio-core/src/lib/Makefile.am b/gnuradio-core/src/lib/Makefile.am new file mode 100644 index 00000000..2b31b3fc --- /dev/null +++ b/gnuradio-core/src/lib/Makefile.am @@ -0,0 +1,62 @@ +# +# Copyright 2001,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +## Process this file with automake to produce Makefile.in + +# We've got to build . before swig +# FIXME add atsc back +SUBDIRS = missing runtime filter general g72x reed-solomon omnithread io . swig + +# generate libgnuradio-core.la from the convenience libraries in subdirs + +lib_LTLIBRARIES = libgnuradio-core.la libgnuradio-core-qa.la + +libgnuradio_core_la_SOURCES = bug_work_around_6.cc +libgnuradio_core_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 + +libgnuradio_core_qa_la_SOURCES = bug_work_around_6.cc +libgnuradio_core_qa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 \ + $(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +FIXME = \ + atsc/libatsc.la + +libgnuradio_core_la_LIBADD = \ + filter/libfilter.la \ + g72x/libccitt.la \ + general/libgeneral.la \ + io/libio.la \ + missing/libmissing.la \ + omnithread/libomnithread.la \ + reed-solomon/librs.la \ + runtime/libruntime.la \ + $(FFTW3F_LIBS) + +libgnuradio_core_qa_la_LIBADD = \ + filter/libfilter-qa.la \ + general/libgeneral-qa.la \ + runtime/libruntime-qa.la \ + missing/libmissing.la \ + libgnuradio-core.la \ + $(CPPUNIT_LIBS) + diff --git a/gnuradio-core/src/lib/bug_work_around_6.cc b/gnuradio-core/src/lib/bug_work_around_6.cc new file mode 100644 index 00000000..929c7f81 --- /dev/null +++ b/gnuradio-core/src/lib/bug_work_around_6.cc @@ -0,0 +1,3 @@ +// if libgrio has no sources, it doesn't get built correctly + +static int gr_bug_work_around_6; diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S new file mode 100644 index 00000000..5aee102f --- /dev/null +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S @@ -0,0 +1,95 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# sse_float_dotprod (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + + + .file "3dnow_float_dotprod_really_simple.s" + .version "01.01" +.text + .p2align 4 +.globl sse_float_dotprod + .type sse_float_dotprod,@function +sse_float_dotprod: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + + # The plan is to get it computing the correct answer, and + # then to unroll and schedule the inner loop. + + pxor %mm4, %mm4 # mm4 = 0 0 + shll $1, %ecx # count * 2 + + .p2align 4 +.loop1: + movq (%eax), %mm0 + pfmul (%edx), %mm0 + pfadd %mm0, %mm4 + addl $8, %edx + addl $8, %eax + decl %ecx + jne .loop1 + + # at this point mm4 contains partial sums + + pfacc %mm4, %mm4 + movd %mm4, 16(%ebp) + femms + flds 16(%ebp) + + popl %ebp + ret +.Lfe1: + .size sse_float_dotprod,.Lfe1-sse_float_dotprod + .ident "Hand coded x86 3DNow! assembly" diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S new file mode 100644 index 00000000..4c4936d3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S @@ -0,0 +1,102 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# sse_float_dotprod (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + + + .file "3dnow_float_dotprod_simple.s" + .version "01.01" +.text + .p2align 4 +.globl sse_float_dotprod + .type sse_float_dotprod,@function +sse_float_dotprod: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + + # The plan is to get it computing the correct answer, and + # then to unroll and schedule the inner loop. + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + + .p2align 4 +.loop1: + movq 0(%eax), %mm0 + movq 8(%eax), %mm1 + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + + addl $16, %edx + addl $16, %eax + decl %ecx + jne .loop1 + + # at this point mm4 and mm5 contain partial sums + + pfadd %mm5, %mm4 + pfacc %mm4, %mm4 + movd %mm4, 16(%ebp) + femms + flds 16(%ebp) + + popl %ebp + ret +.Lfe1: + .size sse_float_dotprod,.Lfe1-sse_float_dotprod + .ident "Hand coded x86 3DNow! assembly" diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am new file mode 100644 index 00000000..01885a84 --- /dev/null +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -0,0 +1,306 @@ +# +# Copyright 2001,2002,2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# +# This directory contains mostly filter routines, plus a few +# other performance critical items +# + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +noinst_LTLIBRARIES = libfilter.la libfilter-qa.la + +# ---------------------------------------------------------------- +# these scripts generate FIR code +# + +CODE_GENERATOR = \ + generate_all.py \ + generate_gr_fir_XXX.py \ + generate_gr_fir_filter_XXX.py \ + generate_gr_interp_fir_filter_XXX.py \ + generate_gr_rational_resampler_base_XXX.py \ + generate_gr_fir_sysconfig.py \ + generate_gr_fir_sysconfig_generic.py \ + generate_gr_fir_util.py \ + generate_gr_freq_xlating_fir_filter_XXX.py \ + generate_utils.py \ + gr_fir_XXX.cc.t \ + gr_fir_XXX.h.t \ + gr_fir_XXX_generic.cc.t \ + gr_fir_XXX_generic.h.t \ + gr_fir_filter_XXX.cc.t \ + gr_fir_filter_XXX.h.t \ + gr_fir_filter_XXX.i.t \ + gr_interp_fir_filter_XXX.cc.t \ + gr_interp_fir_filter_XXX.h.t \ + gr_interp_fir_filter_XXX.i.t \ + gr_rational_resampler_base_XXX.cc.t \ + gr_rational_resampler_base_XXX.h.t \ + gr_rational_resampler_base_XXX.i.t \ + gr_freq_xlating_fir_filter_XXX.cc.t \ + gr_freq_xlating_fir_filter_XXX.h.t \ + gr_freq_xlating_fir_filter_XXX.i.t + + + +# include $(srcdir)/Makefile.gen +include Makefile.gen + + +$(GENERATED_H) $(GENERATED_I) $(GENERATED_CC): $(CODE_GENERATOR) + PYTHONPATH=$(top_srcdir)/gnuradio-core/src/python srcdir=$(srcdir) $(srcdir)/generate_all.py + + +BUILT_SOURCES = $(GENERATED_H) $(GENERATED_I) $(GENERATED_CC) + + +# ---------------------------------------------------------------- +# MD_CPU and MD_SUBCPU are set at configure time by way of +# gnuradio/config/gr_set_md_cpu.m4. +# It indicates which set of machine dependent code we should be building. +# We currently implement "generic" and "x86" + +# +# _CODE entry for each set of machine specific speedups +# + +generic_CODE = \ + sysconfig_generic.cc + +generic_qa_CODE = \ + qa_dotprod_generic.cc + +x86_CODE = \ + sysconfig_x86.cc \ + gr_fir_sysconfig_x86.cc \ + gr_cpu.cc \ + gr_fir_ccc_simd.cc \ + gr_fir_ccc_x86.cc \ + gr_fir_fff_simd.cc \ + gr_fir_fff_x86.cc \ + gr_fir_fsf_simd.cc \ + gr_fir_fsf_x86.cc \ + gr_fir_scc_simd.cc \ + gr_fir_scc_x86.cc \ + gr_fir_fcc_simd.cc \ + gr_fir_fcc_x86.cc \ + gr_fir_ccf_simd.cc \ + gr_fir_ccf_x86.cc \ + sse_debug.c + +x86_SUBCODE = \ + float_dotprod_sse.S \ + float_dotprod_3dnow.S \ + complex_dotprod_3dnowext.S \ + complex_dotprod_3dnow.S \ + complex_dotprod_sse.S \ + ccomplex_dotprod_3dnowext.S \ + ccomplex_dotprod_3dnow.S \ + ccomplex_dotprod_sse.S \ + fcomplex_dotprod_3dnow.S \ + fcomplex_dotprod_sse.S \ + short_dotprod_mmx.S \ + cpuid_x86.S + +x86_64_SUBCODE = \ + float_dotprod_sse64.S \ + float_dotprod_3dnow64.S \ + complex_dotprod_3dnowext64.S \ + complex_dotprod_3dnow64.S \ + complex_dotprod_sse64.S \ + ccomplex_dotprod_3dnowext64.S \ + ccomplex_dotprod_3dnow64.S \ + ccomplex_dotprod_sse64.S \ + fcomplex_dotprod_3dnow64.S \ + fcomplex_dotprod_sse64.S \ + short_dotprod_mmx64.S \ + cpuid_x86_64.S + +x86_qa_CODE = \ + qa_dotprod_x86.cc \ + qa_float_dotprod_x86.cc \ + qa_complex_dotprod_x86.cc \ + qa_ccomplex_dotprod_x86.cc + +# +# include each _CODE entry here... +# +EXTRA_libfilter_la_SOURCES = \ + $(generic_CODE) \ + $(generic_qa_CODE) \ + $(x86_CODE) \ + $(x86_SUBCODE) \ + $(x86_64_SUBCODE) \ + $(x86_qa_CODE) + + +EXTRA_DIST = \ + 3dnow_float_dotprod_really_simple.S \ + 3dnow_float_dotprod_simple.S \ + $(CODE_GENERATOR) + + +# work around automake deficiency +libfilter_la_common_SOURCES = \ + $(GENERATED_CC) \ + gr_adaptive_fir_ccf.cc \ + gr_cma_equalizer_cc.cc \ + gr_fft_filter_ccc.cc \ + gr_fft_filter_fff.cc \ + gr_goertzel_fc.cc \ + gr_filter_delay_fc.cc \ + gr_fractional_interpolator.cc \ + gr_hilbert_fc.cc \ + gr_iir_filter_ffd.cc \ + gr_sincos.c \ + gr_single_pole_iir_filter_ff.cc \ + gr_single_pole_avg_filter_ff.cc \ + gr_single_pole_rec_filter_ff.cc \ + gr_single_zero_avg_filter_ff.cc \ + gr_single_zero_rec_filter_ff.cc \ + gr_single_pole_iir_filter_cc.cc \ + gri_goertzel.cc \ + gri_mmse_fir_interpolator.cc \ + gri_mmse_fir_interpolator_cc.cc \ + complex_dotprod_generic.cc \ + ccomplex_dotprod_generic.cc \ + float_dotprod_generic.c \ + short_dotprod_generic.c + +libfilter_qa_la_common_SOURCES = \ + qa_filter.cc \ + qa_gr_fir_ccf.cc \ + qa_gr_fir_fcc.cc \ + qa_gr_fir_fff.cc \ + qa_gr_fir_ccc.cc \ + qa_gr_fir_scc.cc \ + qa_gri_mmse_fir_interpolator.cc + +if MD_CPU_generic +libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(generic_CODE) +libfilter_qa_la_SOURCES = $(libfilter_qa_la_common_SOURCES) $(generic_qa_CODE) +endif + +if MD_CPU_x86 +if MD_SUBCPU_x86_64 +libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(x86_64_SUBCODE) $(x86_CODE) +else +libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(x86_SUBCODE) $(x86_CODE) +endif + +libfilter_qa_la_SOURCES = $(libfilter_qa_la_common_SOURCES) $(x86_qa_CODE) +endif + + +grinclude_HEADERS = \ + $(GENERATED_H) \ + complex_dotprod_generic.h \ + complex_dotprod_x86.h \ + fcomplex_dotprod_x86.h \ + ccomplex_dotprod_generic.h \ + ccomplex_dotprod_x86.h \ + float_dotprod_generic.h \ + float_dotprod_x86.h \ + gr_adaptive_fir_ccf.h \ + gr_cma_equalizer_cc.h \ + gr_cpu.h \ + gr_fft_filter_ccc.h \ + gr_fft_filter_fff.h \ + gr_filter_delay_fc.h \ + gr_fir_sysconfig_x86.h \ + gr_fractional_interpolator.h \ + gr_goertzel_fc.h \ + gr_hilbert_fc.h \ + gr_iir_filter_ffd.h \ + gr_rotator.h \ + gr_sincos.h \ + gr_single_pole_avg.h \ + gr_single_pole_rec.h \ + gr_single_pole_iir.h \ + gr_single_pole_iir_filter_ff.h \ + gr_single_pole_avg_filter_ff.h \ + gr_single_pole_rec_filter_ff.h \ + gr_single_zero_avg_filter_ff.h \ + gr_single_zero_rec_filter_ff.h \ + gr_single_pole_iir_filter_cc.h \ + gr_single_zero_avg.h \ + gr_single_zero_rec.h \ + gri_goertzel.h \ + gri_iir.h \ + gri_mmse_fir_interpolator.h \ + gri_mmse_fir_interpolator_cc.h \ + qa_filter.h \ + short_dotprod_generic.h \ + short_dotprod_x86.h \ + sse_debug.h + +noinst_HEADERS = \ + assembly.h \ + gr_fir_scc_simd.h \ + gr_fir_scc_x86.h \ + gr_fir_fcc_simd.h \ + gr_fir_fcc_x86.h \ + gr_fir_ccf_simd.h \ + gr_fir_ccf_x86.h \ + gr_fir_ccc_simd.h \ + gr_fir_ccc_x86.h \ + gr_fir_fff_simd.h \ + gr_fir_fff_x86.h \ + gr_fir_fsf_simd.h \ + gr_fir_fsf_x86.h \ + interpolator_taps.h \ + qa_complex_dotprod_x86.h \ + qa_ccomplex_dotprod_x86.h \ + qa_dotprod.h \ + qa_float_dotprod_x86.h \ + qa_gr_fir_ccf.h \ + qa_gr_fir_fcc.h \ + qa_gr_fir_fff.h \ + qa_gr_fir_ccc.h \ + qa_gr_fir_scc.h \ + qa_gri_mmse_fir_interpolator.h + + + +swiginclude_HEADERS = \ + filter.i \ + filter_generated.i \ + gr_adaptive_fir_ccf.i \ + gr_cma_equalizer_cc.i \ + gr_fft_filter_ccc.i \ + gr_fft_filter_fff.i \ + gr_filter_delay_fc.i \ + gr_goertzel_fc.i \ + gr_hilbert_fc.i \ + gr_iir_filter_ffd.i \ + gr_single_pole_iir_filter_ff.i \ + gr_single_pole_avg_filter_ff.i \ + gr_single_pole_rec_filter_ff.i \ + gr_single_zero_avg_filter_ff.i \ + gr_single_zero_rec_filter_ff.i \ + gr_single_pole_iir_filter_cc.i \ + $(GENERATED_I) + + +CLEANFILES = $(BUILT_SOURCES) *.pyc diff --git a/gnuradio-core/src/lib/filter/Makefile.gen b/gnuradio-core/src/lib/filter/Makefile.gen new file mode 100644 index 00000000..6809274f --- /dev/null +++ b/gnuradio-core/src/lib/filter/Makefile.gen @@ -0,0 +1,111 @@ +# +# This file is machine generated. All edits will be overwritten +# +GENERATED_H = \ + gr_fir_ccc.h \ + gr_fir_ccc_generic.h \ + gr_fir_ccf.h \ + gr_fir_ccf_generic.h \ + gr_fir_fcc.h \ + gr_fir_fcc_generic.h \ + gr_fir_fff.h \ + gr_fir_fff_generic.h \ + gr_fir_filter_ccc.h \ + gr_fir_filter_ccf.h \ + gr_fir_filter_fcc.h \ + gr_fir_filter_fff.h \ + gr_fir_filter_fsf.h \ + gr_fir_filter_scc.h \ + gr_fir_fsf.h \ + gr_fir_fsf_generic.h \ + gr_fir_scc.h \ + gr_fir_scc_generic.h \ + gr_fir_sysconfig.h \ + gr_fir_sysconfig_generic.h \ + gr_fir_util.h \ + gr_freq_xlating_fir_filter_ccc.h \ + gr_freq_xlating_fir_filter_ccf.h \ + gr_freq_xlating_fir_filter_fcc.h \ + gr_freq_xlating_fir_filter_fcf.h \ + gr_freq_xlating_fir_filter_scc.h \ + gr_freq_xlating_fir_filter_scf.h \ + gr_interp_fir_filter_ccc.h \ + gr_interp_fir_filter_ccf.h \ + gr_interp_fir_filter_fcc.h \ + gr_interp_fir_filter_fff.h \ + gr_interp_fir_filter_fsf.h \ + gr_interp_fir_filter_scc.h \ + gr_rational_resampler_base_ccc.h \ + gr_rational_resampler_base_ccf.h \ + gr_rational_resampler_base_fcc.h \ + gr_rational_resampler_base_fff.h \ + gr_rational_resampler_base_fsf.h \ + gr_rational_resampler_base_scc.h + +GENERATED_I = \ + gr_fir_filter_ccc.i \ + gr_fir_filter_ccf.i \ + gr_fir_filter_fcc.i \ + gr_fir_filter_fff.i \ + gr_fir_filter_fsf.i \ + gr_fir_filter_scc.i \ + gr_freq_xlating_fir_filter_ccc.i \ + gr_freq_xlating_fir_filter_ccf.i \ + gr_freq_xlating_fir_filter_fcc.i \ + gr_freq_xlating_fir_filter_fcf.i \ + gr_freq_xlating_fir_filter_scc.i \ + gr_freq_xlating_fir_filter_scf.i \ + gr_interp_fir_filter_ccc.i \ + gr_interp_fir_filter_ccf.i \ + gr_interp_fir_filter_fcc.i \ + gr_interp_fir_filter_fff.i \ + gr_interp_fir_filter_fsf.i \ + gr_interp_fir_filter_scc.i \ + gr_rational_resampler_base_ccc.i \ + gr_rational_resampler_base_ccf.i \ + gr_rational_resampler_base_fcc.i \ + gr_rational_resampler_base_fff.i \ + gr_rational_resampler_base_fsf.i \ + gr_rational_resampler_base_scc.i + +GENERATED_CC = \ + gr_fir_ccc.cc \ + gr_fir_ccc_generic.cc \ + gr_fir_ccf.cc \ + gr_fir_ccf_generic.cc \ + gr_fir_fcc.cc \ + gr_fir_fcc_generic.cc \ + gr_fir_fff.cc \ + gr_fir_fff_generic.cc \ + gr_fir_filter_ccc.cc \ + gr_fir_filter_ccf.cc \ + gr_fir_filter_fcc.cc \ + gr_fir_filter_fff.cc \ + gr_fir_filter_fsf.cc \ + gr_fir_filter_scc.cc \ + gr_fir_fsf.cc \ + gr_fir_fsf_generic.cc \ + gr_fir_scc.cc \ + gr_fir_scc_generic.cc \ + gr_fir_sysconfig.cc \ + gr_fir_sysconfig_generic.cc \ + gr_fir_util.cc \ + gr_freq_xlating_fir_filter_ccc.cc \ + gr_freq_xlating_fir_filter_ccf.cc \ + gr_freq_xlating_fir_filter_fcc.cc \ + gr_freq_xlating_fir_filter_fcf.cc \ + gr_freq_xlating_fir_filter_scc.cc \ + gr_freq_xlating_fir_filter_scf.cc \ + gr_interp_fir_filter_ccc.cc \ + gr_interp_fir_filter_ccf.cc \ + gr_interp_fir_filter_fcc.cc \ + gr_interp_fir_filter_fff.cc \ + gr_interp_fir_filter_fsf.cc \ + gr_interp_fir_filter_scc.cc \ + gr_rational_resampler_base_ccc.cc \ + gr_rational_resampler_base_ccf.cc \ + gr_rational_resampler_base_fcc.cc \ + gr_rational_resampler_base_fff.cc \ + gr_rational_resampler_base_fsf.cc \ + gr_rational_resampler_base_scc.cc + diff --git a/gnuradio-core/src/lib/filter/README b/gnuradio-core/src/lib/filter/README new file mode 100644 index 00000000..00730f83 --- /dev/null +++ b/gnuradio-core/src/lib/filter/README @@ -0,0 +1,28 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This directory holds filtering code, some of which is machine +generated. Which variations are generated is controlled by two +variables. For most everything, the global "signatures" +in generate_utils.py controls. + +For GrFreqXlatingFIRfilter, the global "fx_signatures" in +generate_GrFreqXlatingFIRfilterXXX.py controls. diff --git a/gnuradio-core/src/lib/filter/assembly.h b/gnuradio-core/src/lib/filter/assembly.h new file mode 100644 index 00000000..9398a0a1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/assembly.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ASSEMBLY_H_ +#define _ASSEMBLY_H_ + + + +#ifndef __ELF__ + +/* + * Too bad, the following define does not work as expected --SF + * #define GLOB_SYMB(f) __USER_LABEL_PREFIX__ ## f + */ +#define GLOB_SYMB(f) _ ## f + +#define DEF_FUNC_HEAD(f) \ + .def GLOB_SYMB(f); .scl 2; .type 32; .endef + +#define FUNC_TAIL(f) /* none */ + + +#else /* !__ELF__ */ + + +#define GLOB_SYMB(f) f + +#define DEF_FUNC_HEAD(f) \ + .type GLOB_SYMB(f),@function \ + +#define FUNC_TAIL(f) \ + .Lfe1: \ + .size GLOB_SYMB(f),.Lfe1-GLOB_SYMB(f) + + +#endif /* !__ELF__ */ + + +#endif /* _ASSEMBLY_H_ */ diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S new file mode 100644 index 00000000..79826e8a --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S @@ -0,0 +1,216 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_3dnow.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnow) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnow) +GLOB_SYMB(ccomplex_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + + movq 0(%eax), %mm0 + + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%edx), %mm2 + + movq 8(%eax), %mm1 + + shrl $1, %ecx # ecx = n_2_ccomplex_blocks / 2 + + movq 8(%edx), %mm3 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + +# complex prod: C += A * B, w/ temp Z, mmPN=$80000000 +# +# movq (%eax), %mmA +# movq (%edx), %mmB +# +# # 3DNow! replacement for: pswapd %mmA, %mmZ +# # TODO: optimize the punpckhdq +# movq %mmA, %mmZ +# punpckhdq %mmZ, %mmZ +# punpckldq %mmA, %mmZ +# +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# +# # 3DNow! replacement for: pfpnacc %mmB, %mmA +# pxor %mmPN, %mmA +# pfacc %mmB, %mmA +# +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 16(%edx), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 16(%eax), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 24(%edx), %mm1 + + movq %mm0, %mm4 + movq %mm1, %mm5 + + pfadd %mm3, %mm7 + movq 24(%eax), %mm3 + +# unroll + + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 32(%edx), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 32(%eax), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 40(%edx), %mm1 + + addl $32, %eax + addl $32, %edx + + pfadd %mm3, %mm7 + movq 8(%eax), %mm3 + +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + andl $1, %ecx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + pfmul %mm5, %mm3 + pfadd %mm1, %mm6 + pfadd %mm3, %mm7 + +.Leven: + # mmNP: negative inversor + + pcmpeqd %mm0, %mm0 # set all bits to 1 + psllq $63, %mm0 # keep only hsb + + pxor %mm0, %mm6 + pfacc %mm7, %mm6 + + movl 20(%ebp), %eax # result + movq %mm6, (%eax) + + femms + + popl %ebp + ret + +FUNC_TAIL(ccomplex_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" + diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S new file mode 100644 index 00000000..bff045e1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S @@ -0,0 +1,213 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "ccomplex_dotprod_3dnow64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnow) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnow) +GLOB_SYMB(ccomplex_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + + movq 0(%rdi), %mm0 + + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%rsi), %mm2 + + movq 8(%rdi), %mm1 + + shr $1, %rax # rax = n_2_ccomplex_blocks / 2 + + movq 8(%rsi), %mm3 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + +# complex prod: C += A * B, w/ temp Z, mmPN=$80000000 +# +# movq (%rdx), %mmA +# movq (%rsi), %mmB +# +# # 3DNow! replacement for: pswapd %mmA, %mmZ +# # TODO: optimize the punpckhdq +# movq %mmA, %mmZ +# punpckhdq %mmZ, %mmZ +# punpckldq %mmA, %mmZ +# +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# +# # 3DNow! replacement for: pfpnacc %mmB, %mmA +# pxor %mmPN, %mmA +# pfacc %mmB, %mmA +# +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 16(%rsi), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 16(%rdi), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 24(%rsi), %mm1 + + movq %mm0, %mm4 + movq %mm1, %mm5 + + pfadd %mm3, %mm7 + movq 24(%rdi), %mm3 + +# unroll + + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 32(%rsi), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 32(%rdi), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 40(%rsi), %mm1 + + add $32, %rdi + add $32, %rsi + + pfadd %mm3, %mm7 + movq 8(%rdi), %mm3 + +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + and $1, %rdx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + pfmul %mm5, %mm3 + pfadd %mm1, %mm6 + pfadd %mm3, %mm7 + +.Leven: + # mmNP: negative inversor + + pcmpeqd %mm0, %mm0 # set all bits to 1 + psllq $63, %mm0 # keep only hsb + + pxor %mm0, %mm6 + pfacc %mm7, %mm6 + + movq %mm6, (%rcx) + + femms + + retq + +FUNC_TAIL(ccomplex_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" + diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S new file mode 100644 index 00000000..39057e46 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S @@ -0,0 +1,191 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_3dnowext.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnowext) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnowext) +GLOB_SYMB(ccomplex_dotprod_3dnowext): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%eax), %mm0 + movq 0(%edx), %mm2 + + shrl $1, %ecx # ecx = n_2_ccomplex_blocks / 2 + + movq 8(%eax), %mm1 + movq 8(%edx), %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + +# complex prod: C += A * B, w/ temp Z +# +# movq 0(%eax), %mmA +# movq 0(%edx), %mmB +# pswapd %mmA, %mmZ +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# pfpnacc %mmB, %mmA +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 16(%edx), %mm2 + pfpnacc %mm3, %mm1 + movq 24(%edx), %mm3 + + pfadd %mm0, %mm6 + movq 16(%eax), %mm0 + pfadd %mm1, %mm7 + movq 24(%eax), %mm1 + +# unroll + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 32(%edx), %mm2 + pfpnacc %mm3, %mm1 + movq 40(%edx), %mm3 + + pfadd %mm0, %mm6 + movq 32(%eax), %mm0 + pfadd %mm1, %mm7 + movq 40(%eax), %mm1 + + addl $32, %edx + addl $32, %eax + +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + andl $1, %ecx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + pfpnacc %mm3, %mm1 + + pfadd %mm0, %mm6 + pfadd %mm1, %mm7 + +.Leven: + # at this point mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + + movl 20(%ebp), %eax # result + movq %mm6, (%eax) + + femms + + popl %ebp + ret + +FUNC_TAIL(ccomplex_dotprod_3dnowext) + .ident "Hand coded x86 3DNow!Ext assembly" + diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S new file mode 100644 index 00000000..c6f907c9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S @@ -0,0 +1,188 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_3dnowext64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnowext) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnowext) +GLOB_SYMB(ccomplex_dotprod_3dnowext): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%rdi), %mm0 + movq 0(%rsi), %mm2 + + shr $1, %rax # rax = n_2_ccomplex_blocks / 2 + + movq 8(%rdi), %mm1 + movq 8(%rsi), %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + +# complex prod: C += A * B, w/ temp Z +# +# movq 0(%rdi), %mmA +# movq 0(%rsi), %mmB +# pswapd %mmA, %mmZ +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# pfpnacc %mmB, %mmA +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 16(%rsi), %mm2 + pfpnacc %mm3, %mm1 + movq 24(%rsi), %mm3 + + pfadd %mm0, %mm6 + movq 16(%rdi), %mm0 + pfadd %mm1, %mm7 + movq 24(%rdi), %mm1 + +# unroll + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 32(%rsi), %mm2 + pfpnacc %mm3, %mm1 + movq 40(%rsi), %mm3 + + pfadd %mm0, %mm6 + movq 32(%rdi), %mm0 + pfadd %mm1, %mm7 + movq 40(%rdi), %mm1 + + add $32, %rsi + add $32, %rdi + +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + and $1, %rdx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + pfpnacc %mm3, %mm1 + + pfadd %mm0, %mm6 + pfadd %mm1, %mm7 + +.Leven: + # at this point mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + + movq %mm6, (%rcx) # result + + femms + + retq + +FUNC_TAIL(ccomplex_dotprod_3dnowext) + .ident "Hand coded x86_64 3DNow!Ext assembly" + diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc new file mode 100644 index 00000000..edd5b1b0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc @@ -0,0 +1,59 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "gr_fir_ccc_simd.h" +#include "ccomplex_dotprod_generic.h" + +#include + +void +ccomplex_dotprod_generic (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, + float *result) +{ + gr_complex sum0(0,0); + gr_complex sum1(0,0); + + std::cerr << "Blah!!!\n"; + do { + const gr_complex tap0(taps[0], taps[1]); + const gr_complex tap1(taps[2], taps[3]); + const gr_complex input0(input[0], input[1]); + const gr_complex input1(input[2], input[3]); + + sum0 += input0 * tap0; + sum1 += input1 * tap1; + + input += 8; + taps += 8; + + } while (--n_2_ccomplex_blocks != 0); + + + sum0 += sum1; + result[0] = sum0.real(); + result[1] = sum0.imag(); +} diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h new file mode 100644 index 00000000..70d3b6bd --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CCOMPLEX_DOTPROD_GENERIC_H_ +#define _CCOMPLEX_DOTPROD_GENERIC_H_ + +void +ccomplex_dotprod_generic (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, + float *result); + + +#endif /* _CCOMPLEX_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S new file mode 100644 index 00000000..a16d0535 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S @@ -0,0 +1,194 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_sse.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_sse) + DEF_FUNC_HEAD(ccomplex_dotprod_sse) +GLOB_SYMB(ccomplex_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + + xorps %xmm6, %xmm6 # zero accumulators + + movaps 0(%eax), %xmm0 + + xorps %xmm7, %xmm7 # zero accumulators + + movaps 0(%edx), %xmm2 + + shrl $1, %ecx # ecx = n_2_ccomplex_blocks / 2 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + +# complex prod: C += A * B, w/ temp Z & Y (or B), xmmPN=$0x8000000080000000 +# +# movaps (%eax), %xmmA +# movaps (%edx), %xmmB +# +# movaps %xmmA, %xmmZ +# shufps $0xb1, %xmmZ, %xmmZ # swap internals +# +# mulps %xmmB, %xmmA +# mulps %xmmZ, %xmmB +# +# # SSE replacement for: pfpnacc %xmmB, %xmmA +# xorps %xmmPN, %xmmA +# movaps %xmmA, %xmmZ +# unpcklps %xmmB, %xmmA +# unpckhps %xmmB, %xmmZ +# movaps %xmmZ, %xmmY +# shufps $0x44, %xmmA, %xmmZ # b01000100 +# shufps $0xee, %xmmY, %xmmA # b11101110 +# addps %xmmZ, %xmmA +# +# addps %xmmA, %xmmC + +# A=xmm0, B=xmm2, Z=xmm4 +# A'=xmm1, B'=xmm3, Z'=xmm5 + + movaps 16(%eax), %xmm1 + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + + shufps $0xb1, %xmm4, %xmm4 # swap internals + movaps 16(%edx), %xmm3 + movaps %xmm1, %xmm5 + addps %xmm0, %xmm6 + mulps %xmm3, %xmm1 + shufps $0xb1, %xmm5, %xmm5 # swap internals + addps %xmm1, %xmm6 + mulps %xmm4, %xmm2 + movaps 32(%eax), %xmm0 + addps %xmm2, %xmm7 + mulps %xmm5, %xmm3 + + addl $32, %eax + + movaps 32(%edx), %xmm2 + addps %xmm3, %xmm7 + + addl $32, %edx + + + +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Let's sse if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + andl $1, %ecx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 preloaded + # from the main loop. + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + shufps $0xb1, %xmm4, %xmm4 # swap internals + addps %xmm0, %xmm6 + mulps %xmm4, %xmm2 + addps %xmm2, %xmm7 + + +.Leven: + # neg inversor + xorps %xmm1, %xmm1 + movl $0x80000000, 16(%ebp) + movss 16(%ebp), %xmm1 + shufps $0x11, %xmm1, %xmm1 # b00010001 # 0 -0 0 -0 + + # pfpnacc + xorps %xmm1, %xmm6 + + movaps %xmm6, %xmm2 + unpcklps %xmm7, %xmm6 + unpckhps %xmm7, %xmm2 + movaps %xmm2, %xmm3 + shufps $0x44, %xmm6, %xmm2 # b01000100 + shufps $0xee, %xmm3, %xmm6 # b11101110 + addps %xmm2, %xmm6 + + # xmm6 = r1 i2 r3 i4 + movl 20(%ebp), %eax # @result + movhlps %xmm6, %xmm4 # xmm4 = r3 i4 ?? ?? + addps %xmm4, %xmm6 # xmm6 = r1+r3 i2+i4 ?? ?? + movlps %xmm6, (%eax) # store low 2x32 bits (complex) to memory + + popl %ebp + ret + +FUNC_TAIL(ccomplex_dotprod_sse) + .ident "Hand coded x86 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S new file mode 100644 index 00000000..216df6e5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S @@ -0,0 +1,191 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "ccomplex_dotprod_sse64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_sse) + DEF_FUNC_HEAD(ccomplex_dotprod_sse) +GLOB_SYMB(ccomplex_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + xorps %xmm6, %xmm6 # zero accumulators + + movaps 0(%rdi), %xmm0 + + xorps %xmm7, %xmm7 # zero accumulators + + movaps 0(%rsi), %xmm2 + + shr $1, %rax # rax = n_2_ccomplex_blocks / 2 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + +# complex prod: C += A * B, w/ temp Z & Y (or B), xmmPN=$0x8000000080000000 +# +# movaps (%rdi), %xmmA +# movaps (%rsi), %xmmB +# +# movaps %xmmA, %xmmZ +# shufps $0xb1, %xmmZ, %xmmZ # swap internals +# +# mulps %xmmB, %xmmA +# mulps %xmmZ, %xmmB +# +# # SSE replacement for: pfpnacc %xmmB, %xmmA +# xorps %xmmPN, %xmmA +# movaps %xmmA, %xmmZ +# unpcklps %xmmB, %xmmA +# unpckhps %xmmB, %xmmZ +# movaps %xmmZ, %xmmY +# shufps $0x44, %xmmA, %xmmZ # b01000100 +# shufps $0xee, %xmmY, %xmmA # b11101110 +# addps %xmmZ, %xmmA +# +# addps %xmmA, %xmmC + +# A=xmm0, B=xmm2, Z=xmm4 +# A'=xmm1, B'=xmm3, Z'=xmm5 + + movaps 16(%rdi), %xmm1 + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + + shufps $0xb1, %xmm4, %xmm4 # swap internals + movaps 16(%rsi), %xmm3 + movaps %xmm1, %xmm5 + addps %xmm0, %xmm6 + mulps %xmm3, %xmm1 + shufps $0xb1, %xmm5, %xmm5 # swap internals + addps %xmm1, %xmm6 + mulps %xmm4, %xmm2 + movaps 32(%rdi), %xmm0 + addps %xmm2, %xmm7 + mulps %xmm5, %xmm3 + + add $32, %rdi + + movaps 32(%rsi), %xmm2 + addps %xmm3, %xmm7 + + add $32, %rsi + + + +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Let's sse if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + and $1, %rdx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 preloaded + # from the main loop. + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + shufps $0xb1, %xmm4, %xmm4 # swap internals + addps %xmm0, %xmm6 + mulps %xmm4, %xmm2 + addps %xmm2, %xmm7 + + +.Leven: + # neg inversor + xorps %xmm1, %xmm1 + movl $0x80000000, -8(%rsp) + movss -8(%rsp), %xmm1 + shufps $0x11, %xmm1, %xmm1 # b00010001 # 0 -0 0 -0 + + # pfpnacc + xorps %xmm1, %xmm6 + + movaps %xmm6, %xmm2 + unpcklps %xmm7, %xmm6 + unpckhps %xmm7, %xmm2 + movaps %xmm2, %xmm3 + shufps $0x44, %xmm6, %xmm2 # b01000100 + shufps $0xee, %xmm3, %xmm6 # b11101110 + addps %xmm2, %xmm6 + + # xmm6 = r1 i2 r3 i4 + movhlps %xmm6, %xmm4 # xmm4 = r3 i4 ?? ?? + addps %xmm4, %xmm6 # xmm6 = r1+r3 i2+i4 ?? ?? + movlps %xmm6, (%rcx) # store low 2x32 bits (complex) to memory + + retq + +FUNC_TAIL(ccomplex_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h b/gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h new file mode 100644 index 00000000..0a8c7363 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CCOMPLEX_DOTPROD_X86_H_ +#define _CCOMPLEX_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void +ccomplex_dotprod_3dnow (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, float *result); + +void +ccomplex_dotprod_3dnowext (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, float *result); + +void +ccomplex_dotprod_sse (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, float *result); + +#ifdef __cplusplus +} +#endif + +#endif /* _CCOMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S new file mode 100644 index 00000000..37608ece --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S @@ -0,0 +1,188 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + .file "complex_dotprod_3dnow.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnow) + DEF_FUNC_HEAD(complex_dotprod_3dnow) +GLOB_SYMB(complex_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shrl $1, %ecx # ecx = n_2_complex_blocks / 2 + + # pshufw & pi2fw + pxor %mm0, %mm0 + punpcklwd 0(%eax), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + pi2fd %mm0, %mm0 + + pxor %mm1, %mm1 + punpcklwd 0(%eax), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + pi2fd %mm1, %mm1 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + + pxor %mm2, %mm2 + punpcklwd 4(%eax), %mm2 + psrad $16, %mm2 + punpckldq %mm2, %mm2 + + pfmul 8(%edx), %mm1 + pfadd %mm3, %mm7 + pi2fd %mm2, %mm2 + + pxor %mm3, %mm3 + punpcklwd 4(%eax), %mm3 + psrad $16, %mm3 + punpckhdq %mm3, %mm3 + + pfmul 16(%edx), %mm2 + pfadd %mm0, %mm4 + pi2fd %mm3, %mm3 + + pxor %mm0, %mm0 + punpcklwd 8(%eax), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + + pfmul 24(%edx), %mm3 + pfadd %mm1, %mm5 + + pxor %mm1, %mm1 + punpcklwd 8(%eax), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + + pi2fd %mm0, %mm0 + pi2fd %mm1, %mm1 + +#TODO: add prefetch + + addl $32, %edx + addl $8, %eax + +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + movl 20(%ebp), %eax # result + + pfadd %mm6, %mm4 + + movq %mm4, (%eax) + femms + + popl %ebp + ret + +FUNC_TAIL(complex_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" + diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S new file mode 100644 index 00000000..1413c6ce --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S @@ -0,0 +1,183 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "complex_dotprod_3dnow64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnow) + DEF_FUNC_HEAD(complex_dotprod_3dnow) +GLOB_SYMB(complex_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shr $1, %rax # rax = n_2_complex_blocks / 2 + + # pshufw & pi2fw + pxor %mm0, %mm0 + punpcklwd 0(%rdi), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + pi2fd %mm0, %mm0 + + pxor %mm1, %mm1 + punpcklwd 0(%rdi), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + pi2fd %mm1, %mm1 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%rsi), %mm0 + pfadd %mm2, %mm6 + + pxor %mm2, %mm2 + punpcklwd 4(%rdi), %mm2 + psrad $16, %mm2 + punpckldq %mm2, %mm2 + + pfmul 8(%rsi), %mm1 + pfadd %mm3, %mm7 + pi2fd %mm2, %mm2 + + pxor %mm3, %mm3 + punpcklwd 4(%rdi), %mm3 + psrad $16, %mm3 + punpckhdq %mm3, %mm3 + + pfmul 16(%rsi), %mm2 + pfadd %mm0, %mm4 + pi2fd %mm3, %mm3 + + pxor %mm0, %mm0 + punpcklwd 8(%rdi), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + + pfmul 24(%rsi), %mm3 + pfadd %mm1, %mm5 + + pxor %mm1, %mm1 + punpcklwd 8(%rdi), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + + pi2fd %mm0, %mm0 + pi2fd %mm1, %mm1 + +#TODO: add prefetch + + add $32, %rsi + add $8, %rdi + +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rsi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rsi), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + + movq %mm4, (%rcx) + femms + + retq + +FUNC_TAIL(complex_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" + diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S new file mode 100644 index 00000000..443949ed --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S @@ -0,0 +1,167 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + .file "complex_dotprod_3dnowext.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnowext) + DEF_FUNC_HEAD(complex_dotprod_3dnowext) +GLOB_SYMB(complex_dotprod_3dnowext): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shrl $1, %ecx # ecx = n_2_complex_blocks / 2 + + movd 0(%eax), %mm0 + pshufw $0x55, %mm0, %mm1 # b01010101 + pshufw $0, %mm0, %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + pi2fw %mm1, %mm1 + pi2fw %mm0, %mm0 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + + pshufw $0, 4(%eax), %mm2 + + pfmul 8(%edx), %mm1 + pfadd %mm3, %mm7 + pi2fw %mm2, %mm2 + + pshufw $0x55, 4(%eax), %mm3 # b01010101 + + pfmul 16(%edx), %mm2 + pi2fw %mm3, %mm3 + pfadd %mm0, %mm4 + + pshufw $0, 8(%eax), %mm0 + + pfmul 24(%edx), %mm3 + pfadd %mm1, %mm5 + + pshufw $0x55, 8(%eax), %mm1 # b01010101 + pi2fw %mm0, %mm0 + +#TODO: add prefetch + + addl $32, %edx + addl $8, %eax + pi2fw %mm1, %mm1 + +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + movl 20(%ebp), %eax # result + pfadd %mm6, %mm4 + movq %mm4, (%eax) + + femms + + popl %ebp + ret + +FUNC_TAIL(complex_dotprod_3dnowext) + .ident "Hand coded x86 3DNow!Ext assembly" + diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S new file mode 100644 index 00000000..195dc377 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S @@ -0,0 +1,164 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "complex_dotprod_3dnowext64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnowext) + DEF_FUNC_HEAD(complex_dotprod_3dnowext) +GLOB_SYMB(complex_dotprod_3dnowext): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shr $1, %rax # rax = n_2_complex_blocks / 2 + + movd 0(%rdi), %mm0 + pshufw $0x55, %mm0, %mm1 # b01010101 + pshufw $0, %mm0, %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + pi2fw %mm1, %mm1 + pi2fw %mm0, %mm0 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%rsi), %mm0 + pfadd %mm2, %mm6 + + pshufw $0, 4(%rdi), %mm2 + + pfmul 8(%rsi), %mm1 + pfadd %mm3, %mm7 + pi2fw %mm2, %mm2 + + pshufw $0x55, 4(%rdi), %mm3 # b01010101 + + pfmul 16(%rsi), %mm2 + pi2fw %mm3, %mm3 + pfadd %mm0, %mm4 + + pshufw $0, 8(%rdi), %mm0 + + pfmul 24(%rsi), %mm3 + pfadd %mm1, %mm5 + + pshufw $0x55, 8(%rdi), %mm1 # b01010101 + pi2fw %mm0, %mm0 + +#TODO: add prefetch + + add $32, %rsi + add $8, %rdi + pi2fw %mm1, %mm1 + +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rsi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rsi), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + pfadd %mm6, %mm4 + movq %mm4, (%rcx) + + femms + + retq + +FUNC_TAIL(complex_dotprod_3dnowext) + .ident "Hand coded x86_64 3DNow!Ext assembly" + diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc b/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc new file mode 100644 index 00000000..300f4700 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc @@ -0,0 +1,55 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "gr_fir_scc_simd.h" +#include "complex_dotprod_generic.h" + + +void +complex_dotprod_generic (const short *input, + const float *taps, unsigned n_2_complex_blocks, + float *result) +{ + gr_complex sum0(0,0); + gr_complex sum1(0,0); + + do { + const gr_complex tap0(taps[0], taps[1]); + const gr_complex tap1(taps[2], taps[3]); + + sum0 += (float)input[0] * tap0; + sum1 += (float)input[1] * tap1; + + input += 4; + taps += 8; + + } while (--n_2_complex_blocks != 0); + + + sum0 += sum1; + result[0] = sum0.real(); + result[1] = sum0.imag(); +} diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_generic.h b/gnuradio-core/src/lib/filter/complex_dotprod_generic.h new file mode 100644 index 00000000..44a4ea55 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_generic.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _COMPLEX_DOTPROD_GENERIC_H_ +#define _COMPLEX_DOTPROD_GENERIC_H_ + +void +complex_dotprod_generic (const short *input, + const float *taps, unsigned n_2_complex_blocks, + float *result); + + +#endif /* _COMPLEX_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S new file mode 100644 index 00000000..acafb1a3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S @@ -0,0 +1,202 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "complex_dotprod_sse.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_sse) + DEF_FUNC_HEAD(complex_dotprod_sse) +GLOB_SYMB(complex_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + andl $0x3, %ecx + jmp .L1_test + + .p2align 4 +.loop1: + + pxor %mm0, %mm0 + punpcklwd 0(%eax), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps (%edx), %xmm0 + addl $0x10, %edx + addl $4, %eax + addps %xmm0, %xmm4 +.L1_test: + decl %ecx + jge .loop1 + + + # set up for primary loop which is unrolled 4 times + + movl 16(%ebp), %ecx + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shrl $2, %ecx # n_2_complex_blocks / 4 + je .cleanup # if zero, take short path + + # finish setup and loop priming + + pxor %mm0, %mm0 + punpcklwd 0(%eax), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + movaps %xmm5, %xmm2 + + pxor %mm1, %mm1 + punpcklwd 4(%eax), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + movaps %xmm5, %xmm3 + + # we know ecx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.loop2: + mulps (%edx), %xmm0 + addps %xmm2, %xmm6 + + pxor %mm2, %mm2 + punpcklwd 8(%eax), %mm2 + psrad $16, %mm2 + cvtpi2ps %mm2, %xmm2 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%edx), %xmm1 + addps %xmm3, %xmm7 + + pxor %mm3, %mm3 + punpcklwd 12(%eax), %mm3 + psrad $16, %mm3 + cvtpi2ps %mm3, %xmm3 + shufps $0x50, %xmm3, %xmm3 + + mulps 0x20(%edx), %xmm2 + addps %xmm0, %xmm4 + + pxor %mm0, %mm0 + punpcklwd 16(%eax), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%edx), %xmm3 + addps %xmm1, %xmm5 + + pxor %mm1, %mm1 + punpcklwd 20(%eax), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + addl $0x40, %edx + addl $0x10, %eax + decl %ecx + jne .loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.cleanup: # xmm4 = r1 i2 r3 i4 + movl 20(%ebp), %eax # @result + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%eax) # store low 2x32 bits (complex) to memory + + emms + popl %ebp + ret + +FUNC_TAIL(complex_dotprod_sse) + .ident "Hand coded x86 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S new file mode 100644 index 00000000..0fb95db0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S @@ -0,0 +1,198 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "complex_dotprod_sse64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_sse) + DEF_FUNC_HEAD(complex_dotprod_sse) +GLOB_SYMB(complex_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + and $0x3, %rax + jmp .L1_test + + .p2align 4 +.loop1: + + pxor %mm0, %mm0 + punpcklwd 0(%rdi), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps (%rsi), %xmm0 + add $0x10, %rsi + add $4, %rdi + addps %xmm0, %xmm4 +.L1_test: + dec %rax + jge .loop1 + + + # set up for primary loop which is unrolled 4 times + + movaps %xmm5, %xmm6 # zero remaining accumulators + shr $2, %rdx # n_2_complex_blocks / 4 + movaps %xmm5, %xmm7 + + je .cleanup # if zero, take short path + + # finish setup and loop priming + + pxor %mm0, %mm0 + punpcklwd 0(%rdi), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + movaps %xmm5, %xmm2 + + pxor %mm1, %mm1 + punpcklwd 4(%rdi), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + movaps %xmm5, %xmm3 + + # we know rax is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.loop2: + mulps (%rsi), %xmm0 + addps %xmm2, %xmm6 + + pxor %mm2, %mm2 + punpcklwd 8(%rdi), %mm2 + psrad $16, %mm2 + cvtpi2ps %mm2, %xmm2 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%rsi), %xmm1 + addps %xmm3, %xmm7 + + pxor %mm3, %mm3 + punpcklwd 12(%rdi), %mm3 + psrad $16, %mm3 + cvtpi2ps %mm3, %xmm3 + shufps $0x50, %xmm3, %xmm3 + + mulps 0x20(%rsi), %xmm2 + addps %xmm0, %xmm4 + + pxor %mm0, %mm0 + punpcklwd 16(%rdi), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%rsi), %xmm3 + addps %xmm1, %xmm5 + + pxor %mm1, %mm1 + punpcklwd 20(%rdi), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + add $0x40, %rsi + add $0x10, %rdi + dec %rdx + jne .loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.cleanup: # xmm4 = r1 i2 r3 i4 + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%rcx) # store low 2x32 bits (complex) to memory + + emms + retq + +FUNC_TAIL(complex_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_x86.h b/gnuradio-core/src/lib/filter/complex_dotprod_x86.h new file mode 100644 index 00000000..86ac0e78 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_x86.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _COMPLEX_DOTPROD_X86_H_ +#define _COMPLEX_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void +complex_dotprod_3dnow (const short *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +void +complex_dotprod_3dnowext (const short *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +void +complex_dotprod_sse (const short *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +#ifdef __cplusplus +} +#endif + +#endif /* _COMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/cpuid_x86.S b/gnuradio-core/src/lib/filter/cpuid_x86.S new file mode 100644 index 00000000..3152b91d --- /dev/null +++ b/gnuradio-core/src/lib/filter/cpuid_x86.S @@ -0,0 +1,56 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# +# execute CPUID instruction, return EAX, EBX, ECX and EDX values in result +# +# void cpuid_x86 (unsigned int op, unsigned int result[4]); +# + +#include "assembly.h" + +.file "cpuid_x86.S" + .version "01.01" +.text +.globl GLOB_SYMB(cpuid_x86) + DEF_FUNC_HEAD(cpuid_x86) +GLOB_SYMB(cpuid_x86): + pushl %ebp + movl %esp, %ebp + pushl %ebx # must save in PIC mode, holds GOT pointer + pushl %esi + + movl 8(%ebp), %eax # op + movl 12(%ebp), %esi # result + cpuid + movl %eax, 0(%esi) + movl %ebx, 4(%esi) + movl %ecx, 8(%esi) + movl %edx, 12(%esi) + + popl %esi + popl %ebx + popl %ebp + ret + +FUNC_TAIL(cpuid_x86) + .ident "Hand coded cpuid assembly" + diff --git a/gnuradio-core/src/lib/filter/cpuid_x86_64.S b/gnuradio-core/src/lib/filter/cpuid_x86_64.S new file mode 100644 index 00000000..98137db1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/cpuid_x86_64.S @@ -0,0 +1,50 @@ +# +# Copyright 2003,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# +# execute CPUID instruction, return EAX, EBX, ECX and EDX values in result +# +# void cpuid_x86 (unsigned int op, unsigned int result[4]); +# + +#include "assembly.h" + +.file "cpuid_x86_64.S" + .version "01.01" +.text +.globl GLOB_SYMB(cpuid_x86) + DEF_FUNC_HEAD(cpuid_x86) +GLOB_SYMB(cpuid_x86): + mov %rbx, %r11 # must save in PIC mode, holds GOT pointer + + mov %rdi, %rax # op + cpuid + movl %eax, 0(%rsi) # result + movl %ebx, 4(%rsi) + movl %ecx, 8(%rsi) + movl %edx, 12(%rsi) + + mov %r11, %rbx + retq + +FUNC_TAIL(cpuid_x86) + .ident "Hand coded cpuid64 assembly" + diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S new file mode 100644 index 00000000..20dc5b2d --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S @@ -0,0 +1,172 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "fcomplex_dotprod_3dnow.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_3dnow) + DEF_FUNC_HEAD(fcomplex_dotprod_3dnow) +GLOB_SYMB(fcomplex_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shrl $1, %ecx # ecx = n_2_complex_blocks / 2 + + movq 0(%eax), %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + punpckhdq %mm1, %mm1 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + + movq 8(%eax), %mm2 + + pfadd %mm3, %mm7 + + pfmul 8(%edx), %mm1 + + movq %mm2, %mm3 + punpckldq %mm2, %mm2 + punpckhdq %mm3, %mm3 + + + pfmul 16(%edx), %mm2 + pfadd %mm0, %mm4 + + movq 16(%eax), %mm0 + + pfadd %mm1, %mm5 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + + pfmul 24(%edx), %mm3 + + punpckhdq %mm1, %mm1 + + +#TODO: add prefetch? + + addl $32, %edx + addl $16, %eax + +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + movl 20(%ebp), %eax # result + + pfadd %mm6, %mm4 + + movq %mm4, (%eax) + femms + + popl %ebp + ret + +FUNC_TAIL(fcomplex_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S new file mode 100644 index 00000000..32772bf4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S @@ -0,0 +1,166 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "fcomplex_dotprod_3dnow64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_3dnow) + DEF_FUNC_HEAD(fcomplex_dotprod_3dnow) +GLOB_SYMB(fcomplex_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shr $1, %rax # rax = n_2_complex_blocks / 2 + + movq 0(%rdi), %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + punpckhdq %mm1, %mm1 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%rsi), %mm0 + pfadd %mm2, %mm6 + + movq 8(%rdi), %mm2 + + pfadd %mm3, %mm7 + + pfmul 8(%rsi), %mm1 + + movq %mm2, %mm3 + punpckldq %mm2, %mm2 + punpckhdq %mm3, %mm3 + + + pfmul 16(%rsi), %mm2 + pfadd %mm0, %mm4 + + movq 16(%rdi), %mm0 + + pfadd %mm1, %mm5 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + + pfmul 24(%rsi), %mm3 + + punpckhdq %mm1, %mm1 + + +#TODO: add prefetch? + + add $32, %rsi + add $16, %rdi + +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rsi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rsi), %mm1 + pfadd %mm1, %mm5 + + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + + movq %mm4, (%rcx) # result + femms + + retq + +FUNC_TAIL(fcomplex_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S new file mode 100644 index 00000000..2d8b4ccb --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S @@ -0,0 +1,184 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "fcomplex_dotprod_sse.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_sse) + DEF_FUNC_HEAD(fcomplex_dotprod_sse) +GLOB_SYMB(fcomplex_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + andl $0x3, %ecx + jmp .L1_test + + .p2align 4 +.loop1: + + movlps 0(%eax), %xmm0 + shufps $0x50, %xmm0, %xmm0 # b01010000 + + mulps (%edx), %xmm0 + addl $0x10, %edx + addl $8, %eax + addps %xmm0, %xmm4 +.L1_test: + decl %ecx + jge .loop1 + + + # set up for primary loop which is unrolled 4 times + + movl 16(%ebp), %ecx + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shrl $2, %ecx # n_2_complex_blocks / 4 + je .cleanup # if zero, take short path + + # finish setup and loop priming + + movlps 0(%eax), %xmm0 + + movaps %xmm5, %xmm2 + movaps %xmm5, %xmm3 + + movlps 8(%eax), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + shufps $0x50, %xmm1, %xmm1 + + # we know ecx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.loop2: + addps %xmm2, %xmm6 + movlps 0x10(%eax), %xmm2 + + addps %xmm3, %xmm7 + + mulps (%edx), %xmm0 + + movlps 0x18(%eax), %xmm3 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%edx), %xmm1 + + shufps $0x50, %xmm3, %xmm3 + + addps %xmm0, %xmm4 + movlps 0x20(%eax), %xmm0 + + addps %xmm1, %xmm5 + + mulps 0x20(%edx), %xmm2 + + movlps 0x28(%eax), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%edx), %xmm3 + + shufps $0x50, %xmm1, %xmm1 + + addl $0x40, %edx + addl $0x20, %eax + decl %ecx + jne .loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.cleanup: # xmm4 = r1 i2 r3 i4 + movl 20(%ebp), %eax # @result + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%eax) # store low 2x32 bits (complex) to memory + + popl %ebp + ret + +FUNC_TAIL(fcomplex_dotprod_sse) + .ident "Hand coded x86 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S new file mode 100644 index 00000000..cba03579 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S @@ -0,0 +1,179 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "fcomplex_dotprod_sse64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_sse) + DEF_FUNC_HEAD(fcomplex_dotprod_sse) +GLOB_SYMB(fcomplex_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + and $0x3, %rax + jmp .L1_test + + .p2align 4 +.loop1: + + movlps 0(%rdi), %xmm0 + shufps $0x50, %xmm0, %xmm0 # b01010000 + + mulps (%rsi), %xmm0 + add $0x10, %rsi + add $8, %rdi + addps %xmm0, %xmm4 +.L1_test: + dec %rax + jge .loop1 + + + # set up for primary loop which is unrolled 4 times + + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shr $2, %rdx # n_2_complex_blocks / 4 + je .cleanup # if zero, take short path + + # finish setup and loop priming + + movlps 0(%rdi), %xmm0 + + movaps %xmm5, %xmm2 + movaps %xmm5, %xmm3 + + movlps 8(%rdi), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + shufps $0x50, %xmm1, %xmm1 + + # we know rdx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.loop2: + addps %xmm2, %xmm6 + movlps 0x10(%rdi), %xmm2 + + addps %xmm3, %xmm7 + + mulps (%rsi), %xmm0 + + movlps 0x18(%rdi), %xmm3 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%rsi), %xmm1 + + shufps $0x50, %xmm3, %xmm3 + + addps %xmm0, %xmm4 + movlps 0x20(%rdi), %xmm0 + + addps %xmm1, %xmm5 + + mulps 0x20(%rsi), %xmm2 + + movlps 0x28(%rdi), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%rsi), %xmm3 + + shufps $0x50, %xmm1, %xmm1 + + add $0x40, %rsi + add $0x20, %rdi + dec %rdx + jne .loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.cleanup: # xmm4 = r1 i2 r3 i4 + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%rcx) # store low 2x32 bits (complex) to memory + + retq + +FUNC_TAIL(fcomplex_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h b/gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h new file mode 100644 index 00000000..d9f7eaca --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _FCOMPLEX_DOTPROD_X86_H_ +#define _FCOMPLEX_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void +fcomplex_dotprod_3dnow (const float *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +void +fcomplex_dotprod_sse (const float *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCOMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i new file mode 100644 index 00000000..2d434699 --- /dev/null +++ b/gnuradio-core/src/lib/filter/filter.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include "gr_iir_filter_ffd.i" +%include "gr_single_pole_iir_filter_ff.i" +%include "gr_single_pole_iir_filter_cc.i" +%include "gr_hilbert_fc.i" +%include "gr_filter_delay_fc.i" +%include "gr_fft_filter_ccc.i" +%include "gr_fft_filter_fff.i" +%include "gr_goertzel_fc.i" +%include "gr_cma_equalizer_cc.i" + +%include "filter_generated.i" diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S new file mode 100644 index 00000000..784fa0b5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S @@ -0,0 +1,148 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_3dnow.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_3dnow) + DEF_FUNC_HEAD(float_dotprod_3dnow) +GLOB_SYMB(float_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shrl $1, %ecx # ecx = n_4_float_blocks / 2 + movq 0(%eax), %mm0 + movq 8(%eax), %mm1 + pxor %mm2, %mm2 + pxor %mm3, %mm3 + jmp .L1_test + + # + # 8 taps / loop + # something like 6 cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + movq 16(%eax), %mm2 + + pfmul 8(%edx), %mm1 + pfadd %mm3, %mm7 + movq 24(%eax), %mm3 + + pfmul 16(%edx), %mm2 + pfadd %mm0, %mm4 + movq 32(%eax), %mm0 + + pfmul 24(%edx), %mm3 + pfadd %mm1, %mm5 + movq 40(%eax), %mm1 + + addl $32, %edx + addl $32, %eax +.L1_test: + decl %ecx + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_4_float_blocks was odd. If so, we've got 4 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 4 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + pfacc %mm4, %mm4 + + movd %mm4, 16(%ebp) + femms + flds 16(%ebp) + + popl %ebp + ret + +FUNC_TAIL(float_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S new file mode 100644 index 00000000..0f6a9480 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S @@ -0,0 +1,145 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_3dnow64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_3dnow) + DEF_FUNC_HEAD(float_dotprod_3dnow) +GLOB_SYMB(float_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shr $1, %rax # rax = n_4_float_blocks / 2 + movq 0(%rsi), %mm0 + movq 8(%rsi), %mm1 + pxor %mm2, %mm2 + pxor %mm3, %mm3 + jmp .L1_test + + # + # 8 taps / loop + # something like 6 cycles / loop + # + + .p2align 4 +.loop1: + pfmul 0(%rdi), %mm0 + pfadd %mm2, %mm6 + movq 16(%rsi), %mm2 + + pfmul 8(%rdi), %mm1 + pfadd %mm3, %mm7 + movq 24(%rsi), %mm3 + + pfmul 16(%rdi), %mm2 + pfadd %mm0, %mm4 + movq 32(%rsi), %mm0 + + pfmul 24(%rdi), %mm3 + pfadd %mm1, %mm5 + movq 40(%rsi), %mm1 + + add $32, %rdi + add $32, %rsi +.L1_test: + dec %rax + jge .loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_4_float_blocks was odd. If so, we've got 4 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 4 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rdi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rdi), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + pfacc %mm4, %mm4 + + movd %mm4, -8(%rsp) + movss -8(%rsp), %xmm0 + femms + + retq + +FUNC_TAIL(float_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" diff --git a/gnuradio-core/src/lib/filter/float_dotprod_generic.c b/gnuradio-core/src/lib/filter/float_dotprod_generic.c new file mode 100644 index 00000000..21912afd --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_generic.c @@ -0,0 +1,49 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "float_dotprod_generic.h" + + +float +float_dotprod_generic (const float *input, + const float *taps, unsigned n_4_float_blocks) +{ + float sum0 = 0; + float sum1 = 0; + float sum2 = 0; + float sum3 = 0; + + do { + + sum0 += input[0] * taps[0]; + sum1 += input[1] * taps[1]; + sum2 += input[2] * taps[2]; + sum3 += input[3] * taps[3]; + + input += 4; + taps += 4; + + } while (--n_4_float_blocks != 0); + + + return sum0 + sum1 + sum2 + sum3; +} diff --git a/gnuradio-core/src/lib/filter/float_dotprod_generic.h b/gnuradio-core/src/lib/filter/float_dotprod_generic.h new file mode 100644 index 00000000..4f4d4ebf --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_generic.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _FLOAT_DOTPROD_GENERIC_H_ +#define _FLOAT_DOTPROD_GENERIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +float +float_dotprod_generic (const float *input, + const float *taps, unsigned n_4_float_blocks); + + +#ifdef __cplusplus +} +#endif + + + +#endif /* _FLOAT_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse.S b/gnuradio-core/src/lib/filter/float_dotprod_sse.S new file mode 100644 index 00000000..0e59f5e3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse.S @@ -0,0 +1,167 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_sse.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_sse) + DEF_FUNC_HEAD(float_dotprod_sse) +GLOB_SYMB(float_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_4_float_blocks % 4) + + andl $0x3, %ecx + jmp .L1_test + + .p2align 4 +.loop1: + movaps (%eax), %xmm0 + mulps (%edx), %xmm0 + addl $0x10, %edx + addl $0x10, %eax + addps %xmm0, %xmm4 +.L1_test: + decl %ecx + jge .loop1 + + + # set up for primary loop which is unrolled 4 times + + movl 16(%ebp), %ecx + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shrl $2, %ecx # n_4_float_blocks / 4 + je .cleanup # if zero, take short path + + # finish setup and loop priming + + movaps 0x00(%eax), %xmm0 + movaps %xmm5, %xmm2 + movaps 0x10(%eax), %xmm1 + movaps %xmm5, %xmm3 + + # we know ecx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.loop2: + mulps (%edx), %xmm0 + addps %xmm2, %xmm6 + movaps 0x20(%eax), %xmm2 + + mulps 0x10(%edx), %xmm1 + addps %xmm3, %xmm7 + movaps 0x30(%eax), %xmm3 + + mulps 0x20(%edx), %xmm2 + addps %xmm0, %xmm4 + movaps 0x40(%eax), %xmm0 + + mulps 0x30(%edx), %xmm3 + addps %xmm1, %xmm5 + movaps 0x50(%eax), %xmm1 + + addl $0x40, %edx + addl $0x40, %eax + decl %ecx + jne .loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 4 partial sums. We need + # to compute a "horizontal add" across xmm4. + # This is a fairly nasty operation... + +.cleanup: # xmm4 = d1 d2 d3 d4 + xorps %xmm0, %xmm0 # xmm0 = 0 0 0 0 (may be unnecessary) + movhlps %xmm4, %xmm0 # xmm0 = 0 0 d1 d2 + addps %xmm4, %xmm0 # xmm0 = d1 d2 d1+d3 d2+d4 + movaps %xmm0, %xmm1 # xmm1 = d1 d2 d1+d3 d2+d4 + shufps $0xE1, %xmm4, %xmm1 # xmm1 = d1 d2 d2+d4 d1+d3 + addss %xmm1, %xmm0 # xmm1 = d1 d2 d1+d3 d1+d2+d3+d4 + movss %xmm0, 16(%ebp) # store low 32 bits (sum) to memory + flds 16(%ebp) # and load onto FPU stack for return + + popl %ebp + ret + +FUNC_TAIL(float_dotprod_sse) + .ident "Hand coded x86 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse64.S b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S new file mode 100644 index 00000000..c7f821a3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S @@ -0,0 +1,161 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_sse64.S" + .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_sse) + DEF_FUNC_HEAD(float_dotprod_sse) +GLOB_SYMB(float_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx + + mov %rdx, %rax + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_4_float_blocks % 4) + + and $0x3, %rax + jmp .L1_test + + .p2align 4 +.loop1: + movaps (%rsi), %xmm0 + mulps (%rdi), %xmm0 + add $0x10, %rdi + add $0x10, %rsi + addps %xmm0, %xmm4 +.L1_test: + dec %rax + jge .loop1 + + + # set up for primary loop which is unrolled 4 times + + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shr $2, %rdx # n_4_float_blocks / 4 + je .cleanup # if zero, take short path + + # finish setup and loop priming + + movaps 0x00(%rsi), %xmm0 + movaps %xmm5, %xmm2 + movaps 0x10(%rsi), %xmm1 + movaps %xmm5, %xmm3 + + # we know rdx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.loop2: + mulps (%rdi), %xmm0 + addps %xmm2, %xmm6 + movaps 0x20(%rsi), %xmm2 + + mulps 0x10(%rdi), %xmm1 + addps %xmm3, %xmm7 + movaps 0x30(%rsi), %xmm3 + + mulps 0x20(%rdi), %xmm2 + addps %xmm0, %xmm4 + movaps 0x40(%rsi), %xmm0 + + mulps 0x30(%rdi), %xmm3 + addps %xmm1, %xmm5 + movaps 0x50(%rsi), %xmm1 + + add $0x40, %rdi + add $0x40, %rsi + dec %rdx + jne .loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 4 partial sums. We need + # to compute a "horizontal add" across xmm4. + # This is a fairly nasty operation... + +.cleanup: # xmm4 = d1 d2 d3 d4 + xorps %xmm0, %xmm0 # xmm0 = 0 0 0 0 (may be unnecessary) + movhlps %xmm4, %xmm0 # xmm0 = 0 0 d1 d2 + addps %xmm4, %xmm0 # xmm0 = d1 d2 d1+d3 d2+d4 + movaps %xmm0, %xmm1 # xmm1 = d1 d2 d1+d3 d2+d4 + shufps $0xE1, %xmm4, %xmm1 # xmm1 = d1 d2 d2+d4 d1+d3 + addss %xmm1, %xmm0 # xmm1 = d1 d2 d1+d3 d1+d2+d3+d4 + + retq + +FUNC_TAIL(float_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" diff --git a/gnuradio-core/src/lib/filter/float_dotprod_x86.h b/gnuradio-core/src/lib/filter/float_dotprod_x86.h new file mode 100644 index 00000000..7a101920 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_x86.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _FLOAT_DOTPROD_X86_H_ +#define _FLOAT_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +float +float_dotprod_3dnow (const float *input, + const float *taps, unsigned n_4_float_blocks); + +float +float_dotprod_sse (const float *input, + const float *taps, unsigned n_4_float_blocks); + +#ifdef __cplusplus +} +#endif + + + +#endif /* _FLOAT_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/generate_all.py b/gnuradio-core/src/lib/filter/generate_all.py new file mode 100755 index 00000000..dcbe75df --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_all.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from build_utils import output_glue + +import generate_gr_fir_filter_XXX +import generate_gr_interp_fir_filter_XXX +import generate_gr_rational_resampler_base_XXX +import generate_gr_freq_xlating_fir_filter_XXX +import generate_gr_fir_sysconfig_generic +import generate_gr_fir_sysconfig +import generate_gr_fir_util +import generate_gr_fir_XXX + +def generate_all(): + generate_gr_fir_XXX.generate() + generate_gr_fir_filter_XXX.generate() + generate_gr_interp_fir_filter_XXX.generate() + generate_gr_rational_resampler_base_XXX.generate() + generate_gr_freq_xlating_fir_filter_XXX.generate() + generate_gr_fir_sysconfig_generic.generate() + generate_gr_fir_sysconfig.generate() + generate_gr_fir_util.generate() + output_glue('filter') + +if __name__ == '__main__': + generate_all() diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py new file mode 100755 index 00000000..e55ff854 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py @@ -0,0 +1,75 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +from generate_utils import * + +roots = ['gr_fir_XXX', 'gr_fir_XXX_generic'] + + +# figure out accumulator type. Use biggest of input, output and tap type + +def code3_to_acc_code (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c' or tap_code (code3) == 'c': + return 'c' + if i_code (code3) == 'f' or o_code (code3) == 'f' or tap_code (code3) == 'f': + return 'f' + if i_code (code3) == 'i' or o_code (code3) == 'i' or tap_code (code3) == 'i': + return 'i' + return 'i' # even short short short needs int accumulator + + +def code3_to_input_cast (code3): + if i_code (code3) == 's' and o_code (code3) == 'c': + return '(float)' + return '' + +def expand_h_cc (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + d['INPUT_CAST'] = code3_to_input_cast (code3) + acc_code = code3_to_acc_code (code3) + d['ACC_TYPE'] = char_to_type[acc_code] + if acc_code == 'c': + d['N_UNROLL'] = '2' + d['VRCOMPLEX_INCLUDE'] = '#include ' + else: + d['N_UNROLL'] = '4' + d['VRCOMPLEX_INCLUDE'] = '' + return d + + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc (r, s) + + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py new file mode 100755 index 00000000..e3c0ec7a --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py @@ -0,0 +1,49 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +from generate_utils import * + +roots = ['gr_fir_filter_XXX'] + + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + return d + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc_i (r, s) + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py new file mode 100755 index 00000000..3c78daa2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py @@ -0,0 +1,127 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from generate_utils import * + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_h (): + out = open_and_log_name ('gr_fir_sysconfig.h', 'w') + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by generate_gr_fir_sysconfig.py + * Any changes made to this file will be overwritten. + */ + +#ifndef INCLUDED_GR_FIR_SYSCONFIG_H +#define INCLUDED_GR_FIR_SYSCONFIG_H + +#include + +''') + + # for sig in fir_signatures: + # out.write ('class gr_fir_' + sig + ';\n') + + out.write ('#include \n') + + out.write ( +''' +/*! + * \\brief abstract base class for configuring the automatic selection of the + * fastest gr_fir for your platform. + * + * This is used internally by gr_fir_util. + */ + +class gr_fir_sysconfig { +public: + virtual ~gr_fir_sysconfig (); + +''') + + for sig in fir_signatures: + out.write ((' virtual gr_fir_%s *create_gr_fir_%s (const std::vector<%s> &taps) = 0;\n' % + (sig, sig, tap_type (sig)))) + + out.write ('\n') + + for sig in fir_signatures: + out.write ((' virtual void get_gr_fir_%s_info (std::vector *info) = 0;\n' % + (sig, sig))) + + out.write ( +''' +}; + +/* + * This returns the single instance of the appropriate derived class. + * This function must be defined only once in the system, and should be defined + * in the platform specific code. + */ + +gr_fir_sysconfig *gr_fir_sysconfig_singleton (); + + +#endif /* INCLUDED_GR_FIR_SYSCONFIG_H */ +''') + out.close () + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_cc (): + out = open_and_log_name ('gr_fir_sysconfig.cc', 'w') + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by generate_gr_fir_sysconfig.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +gr_fir_sysconfig::~gr_fir_sysconfig () +{ +} +''') + out.close () + + +# ---------------------------------------------------------------- + +def generate (): + make_gr_fir_sysconfig_h () + make_gr_fir_sysconfig_cc () + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py new file mode 100755 index 00000000..78cf3773 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py @@ -0,0 +1,182 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from generate_utils import * + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_generic_h (): + out = open_and_log_name ('gr_fir_sysconfig_generic.h', 'w') + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by + * generate_gr_fir_sysconfig_generic.py. + * + * Any changes made to this file will be overwritten. + */ + +#ifndef _GR_FIR_SYSCONFIG_GENERIC_H_ +#define _GR_FIR_SYSCONFIG_GENERIC_H_ + +#include + +''') + + out.write ( +''' +class gr_fir_sysconfig_generic : public gr_fir_sysconfig { +public: +''') + + for sig in fir_signatures: + out.write ((' virtual gr_fir_%s *create_gr_fir_%s (const std::vector<%s> &taps);\n' % + (sig, sig, tap_type (sig)))) + + out.write ('\n') + + for sig in fir_signatures: + out.write ((' virtual void get_gr_fir_%s_info (std::vector *info);\n' % + (sig, sig))) + + out.write ( +''' +}; + + +#endif /* _GR_FIR_SYSCONFIG_GENERIC_H_ */ +''') + out.close () + + +# ---------------------------------------------------------------- + +def make_constructor (sig, out): + out.write (''' +static gr_fir_%s * +make_gr_fir_%s (const std::vector<%s> &taps) +{ + return new gr_fir_%s_generic (taps); +} +''' % (sig, sig, tap_type (sig), sig)) + + +def make_creator (sig, out): + out.write (''' +gr_fir_%s * +gr_fir_sysconfig_generic::create_gr_fir_%s (const std::vector<%s> &taps) +{ + return make_gr_fir_%s (taps); +} +''' % (sig, sig, tap_type (sig), sig)) + + +def make_info (sig, out): + out.write (''' +void +gr_fir_sysconfig_generic::get_gr_fir_%s_info (std::vector *info) +{ + info->resize (1); + (*info)[0].name = "generic"; + (*info)[0].create = make_gr_fir_%s; +} +''' % (sig, sig, sig)) + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_generic_cc (): + out = open_and_log_name ('gr_fir_sysconfig_generic.cc', 'w') + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by + * generate_gr_fir_sysconfig_generic.py. + * + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +''') + + for sig in fir_signatures: + out.write ('#include \n' % (sig)) + + out.write ( +''' +/* + * ---------------------------------------------------------------- + * static functions that serve as constructors returned by info + * ---------------------------------------------------------------- + */ +''') + + for sig in fir_signatures: + make_constructor (sig, out) + + out.write ( +''' +/* + * ---------------------------------------------------------------- + * return instances of the generic C++ versions of these classes. + * ---------------------------------------------------------------- + */ +''') + + for sig in fir_signatures: + make_creator (sig, out) + + out.write ( +''' +/* + * Return info about available implementations. + * + * This is the bottom of the concrete hierarchy, so we set the + * size of the vector to 1, and install our info. Classes derived + * from us invoke us first, then append their own info. + */ +''') + + for sig in fir_signatures: + make_info (sig, out) + + + out.close () + +# ---------------------------------------------------------------- + +def generate (): + make_gr_fir_sysconfig_generic_h () + make_gr_fir_sysconfig_generic_cc () + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_util.py b/gnuradio-core/src/lib/filter/generate_gr_fir_util.py new file mode 100755 index 00000000..80d91863 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_util.py @@ -0,0 +1,185 @@ +#!/bin/env python +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from generate_utils import * + +def make_info_struct (out, sig): + out.write ( +''' +struct gr_fir_%s_info { + const char *name; // implementation name, e.g., "generic", "SSE", "3DNow!" + gr_fir_%s *(*create)(const std::vector<%s> &taps); +}; +''' % (sig, sig, tap_type(sig))) + +def make_create (out, sig): + out.write (''' static gr_fir_%s *create_gr_fir_%s (const std::vector<%s> &taps); +''' % (sig, sig, tap_type (sig))) + +def make_info (out, sig): + out.write (''' static void get_gr_fir_%s_info (std::vector *info); +''' % (sig, sig)) + + +# ---------------------------------------------------------------- + +def make_gr_fir_util_h (): + out = open_and_log_name ('gr_fir_util.h', 'w') + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by + * generate_gr_fir_util.py. + * + * Any changes made to this file will be overwritten. + */ + +#ifndef INCLUDED_GR_FIR_UTIL_H +#define INCLUDED_GR_FIR_UTIL_H + +/*! + * \\brief routines to create gr_fir_XXX's + * + * This class handles selecting the fastest version of the finite + * implulse response filter available for your platform. This + * interface should be used by the rest of the system for creating + * gr_fir_XXX's. + * + * The trailing suffix has the form _IOT where I codes the input type, + * O codes the output type, and T codes the tap type. + * I,O,T are elements of the set 's' (short), 'f' (float), 'c' (gr_complex), + * 'i' (short) + */ + +#include + +''') + + for sig in fir_signatures: + out.write ('class gr_fir_%s;\n' % sig); + + out.write ('\n// structures returned by get_gr_fir_XXX_info methods\n\n') + + for sig in fir_signatures: + make_info_struct (out, sig) + + out.write (''' +struct gr_fir_util { + + // create a fast version of gr_fir_XXX. + +''') + + for sig in fir_signatures: + make_create (out, sig) + + out.write (''' + // Get information about all gr_fir_XXX implementations. + // This is useful for benchmarking, testing, etc without having to + // know a priori what's linked into this image + // + // The caller must pass in a valid pointer to a vector. + // The vector will be filled with structs describing the + // available implementations. + +''') + + for sig in fir_signatures: + make_info (out, sig) + + out.write (''' +}; + +#endif /* INCLUDED_GR_FIR_UTIL_H */ +''') + out.close () + + +# ---------------------------------------------------------------- + +def make_constructor_cc (out, sig): + out.write ( +''' +gr_fir_%s * +gr_fir_util::create_gr_fir_%s (const std::vector<%s> &taps) +{ + return gr_fir_sysconfig_singleton()->create_gr_fir_%s (taps); +} +''' % (sig, sig, tap_type (sig), sig)) + + +def make_info_cc (out, sig): + out.write ( +''' +void +gr_fir_util::get_gr_fir_%s_info (std::vector *info) +{ + gr_fir_sysconfig_singleton()->get_gr_fir_%s_info (info); +} +''' % (sig, sig, sig)) + + +def make_gr_fir_util_cc (): + out = open_and_log_name ('gr_fir_util.cc', 'w') + out.write (copyright) + out.write (''' + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +// +// There's no problem that can't be solved by the addition of +// another layer of indirection... +// + +// --- constructors --- + +''') + + for sig in fir_signatures: + make_constructor_cc (out, sig) + + out.write (''' +// --- info gatherers --- + +''') + + for sig in fir_signatures: + make_info_cc (out, sig) + + out.close () + + +# ---------------------------------------------------------------- + +def generate (): + make_gr_fir_util_h () + make_gr_fir_util_cc () + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py new file mode 100755 index 00000000..4a34556f --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py @@ -0,0 +1,53 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +from generate_utils import * + +# files to generate + +fx_signatures = [ 'scf', 'scc', 'fcf', 'fcc', 'ccf', 'ccc' ] + +roots = ['gr_freq_xlating_fir_filter_XXX'] + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + i_code (code3) + 'cc' + return d + + +def generate (): + for r in roots: + for s in fx_signatures: + expand_h_cc_i (r, s) + + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py new file mode 100644 index 00000000..00b3c788 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py @@ -0,0 +1,48 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +from generate_utils import * + +roots = ['gr_interp_fir_filter_XXX'] + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + return d + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc_i (r, s) + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py new file mode 100644 index 00000000..0f96451a --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py @@ -0,0 +1,48 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +from generate_utils import * + +roots = ['gr_rational_resampler_base_XXX'] + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + return d + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc_i (r, s) + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_utils.py b/gnuradio-core/src/lib/filter/generate_utils.py new file mode 100644 index 00000000..2eeb38e7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_utils.py @@ -0,0 +1,31 @@ +# +# Copyright 2003,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +## ----------------------------------------------------------------------- +## signatures defines which variations to generate (input, output, taps) + +fir_signatures = [ 'ccf', 'fcc', 'ccc', 'fff', 'scc', 'fsf' ] + + +## ----------------------------------------------------------------------- + +from build_utils import expand_template, copyright, open_and_log_name, standard_dict +from build_utils_codes import * diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc new file mode 100644 index 00000000..f2ab319b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_adaptive_fir_ccf::gr_adaptive_fir_ccf(char *name, int decimation, const std::vector &taps) + : gr_sync_decimator (name, + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + decimation), + d_updated(false) +{ + d_taps = taps; + set_history(d_taps.size()); +} + +void gr_adaptive_fir_ccf::set_taps(const std::vector &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +int gr_adaptive_fir_ccf::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + if (d_updated) { + d_taps = d_new_taps; + set_history(d_taps.size()); + d_updated = false; + return 0; // history requirements may have changed. + } + + int j = 0, k, l = d_taps.size(); + for (int i = 0; i < noutput_items; i++) { + // Generic dot product of d_taps[] and in[] + gr_complex sum(0.0, 0.0); + for (k = 0; k < l; k++) + sum += d_taps[l-k-1]*in[j+k]; + out[i] = sum; + + // Adjust taps + d_error = error(sum); + for (k = 0; k < l; k++) { + //printf("%f ", d_taps[k]); + update_tap(d_taps[l-k-1], in[j+k]); + } + //printf("\n"); + + j += decimation(); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h new file mode 100644 index 00000000..57a95a33 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_ADAPTIVE_FIR_CCF_H +#define INCLUDED_GR_ADAPTIVE_FIR_CCF_H + +#include + +/*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * \ingroup filter + */ +class gr_adaptive_fir_ccf : public gr_sync_decimator +{ +private: + std::vector d_new_taps; + bool d_updated; + +protected: + float d_error; + std::vector d_taps; + + // Override to calculate error signal per output + virtual float error(const gr_complex &out) = 0; + + // Override to calculate new weight from old, corresponding input + virtual void update_tap(float &tap, const gr_complex &in) = 0; + +public: + gr_adaptive_fir_ccf(char *name, int decimation, const std::vector &taps); + void set_taps(const std::vector &taps); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.i b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.i new file mode 100644 index 00000000..896fb42c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_adaptive_fir_ccf : public gr_sync_decimator +{ +private: + gr_adaptive_fir_ccf(char *name, int decimation, const std::vector &taps); + +public: + void set_taps(const std::vector &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc new file mode 100644 index 00000000..29b8a3e4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_cma_equalizer_cc_sptr +gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu) +{ + return gr_cma_equalizer_cc_sptr(new gr_cma_equalizer_cc(num_taps, modulus, mu)); +} + +gr_cma_equalizer_cc::gr_cma_equalizer_cc(int num_taps, float modulus, float mu) + : gr_adaptive_fir_ccf("cma_equalizer_cc", 1, std::vector(num_taps)), + d_modulus(modulus), d_mu(mu) +{ + d_taps[0] = 1.0; +} + diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h new file mode 100644 index 00000000..25c99689 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CMA_EQUALIZER_CC_H +#define INCLUDED_GR_CMA_EQUALIZER_CC_H + +#include + +class gr_cma_equalizer_cc; +typedef boost::shared_ptr gr_cma_equalizer_cc_sptr; + +gr_cma_equalizer_cc_sptr +gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); + +/*! + * \brief Implements constant modulus adaptive filter on complex stream + * \ingroup filter + */ +class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf +{ +private: + float d_modulus; + float d_mu; + + friend gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); + gr_cma_equalizer_cc(int num_taps, float modulus, float mu); + +protected: + + virtual float error(const gr_complex &out) + { + return (d_modulus - norm(out)); + } + + virtual void update_tap(float &tap, const gr_complex &in) + { + tap += d_mu*d_error*abs(in); + } + +public: +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i new file mode 100644 index 00000000..c64bfc3a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,cma_equalizer_cc) + +%include + +gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); + +class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf +{ +private: + gr_cma_equalizer_cc(int num_taps, float modulus, float mu); + +public: +}; diff --git a/gnuradio-core/src/lib/filter/gr_cpu.cc b/gnuradio-core/src/lib/filter/gr_cpu.cc new file mode 100644 index 00000000..7e926f34 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu.cc @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +/* + * execute CPUID instruction, return EAX, EBX, ECX and EDX values in result + */ +extern "C" { +void cpuid_x86 (unsigned int op, unsigned int result[4]); +}; + +/* + * CPUID functions returning a single datum + */ + +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[0]; +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[1]; +} + +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[2]; +} + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[3]; +} + +// ---------------------------------------------------------------- + +bool +gr_cpu::has_mmx () +{ + unsigned int edx = cpuid_edx (1); // standard features + return (edx & (1 << 23)) != 0; +} + +bool +gr_cpu::has_sse () +{ + unsigned int edx = cpuid_edx (1); // standard features + return (edx & (1 << 25)) != 0; +} + +bool +gr_cpu::has_sse2 () +{ + unsigned int edx = cpuid_edx (1); // standard features + return (edx & (1 << 26)) != 0; +} + +bool +gr_cpu::has_3dnow () +{ + unsigned int extended_fct_count = cpuid_eax (0x80000000); + if (extended_fct_count < 0x80000001) + return false; + + unsigned int extended_features = cpuid_edx (0x80000001); + return (extended_features & (1 << 31)) != 0; +} + +bool +gr_cpu::has_3dnowext () +{ + unsigned int extended_fct_count = cpuid_eax (0x80000000); + if (extended_fct_count < 0x80000001) + return false; + + unsigned int extended_features = cpuid_edx (0x80000001); + return (extended_features & (1 << 30)) != 0; +} diff --git a/gnuradio-core/src/lib/filter/gr_cpu.h b/gnuradio-core/src/lib/filter/gr_cpu.h new file mode 100644 index 00000000..563b60cb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_CPU_H_ +#define _GR_CPU_H_ + +struct gr_cpu { + static bool has_mmx (); + static bool has_sse (); + static bool has_sse2 (); + static bool has_3dnow (); + static bool has_3dnowext (); +}; + +#endif /* _GR_CPU_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc new file mode 100644 index 00000000..c90e3a0f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc @@ -0,0 +1,210 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fft_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector &taps) +{ + return gr_fft_filter_ccc_sptr (new gr_fft_filter_ccc (decimation, taps)); +} + + +gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector &taps) + : gr_sync_decimator ("fft_filter_ccc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex)), + decimation), + d_fftsize(-1), d_fwdfft(0), d_invfft(0), d_updated(false) +{ + // if (decimation != 1) + // throw std::invalid_argument("gr_fft_filter_ccc: decimation must be 1"); + + set_history(1); + actual_set_taps(taps); +} + +gr_fft_filter_ccc::~gr_fft_filter_ccc () +{ + delete d_fwdfft; + delete d_invfft; +} + +static void +print_vector_complex(const std::string label, const std::vector &x) +{ + std::cout << label; + for (unsigned i = 0; i < x.size(); i++) + std::cout << x[i] << " "; + std::cout << "\n"; +} + +void +gr_fft_filter_ccc::set_taps (const std::vector &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +void +gr_fft_filter_ccc::actual_set_taps (const std::vector &taps) +{ + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for (i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + gr_complex *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize; i++) + d_xformed_taps[i] = out[i]; + + //print_vector_complex("transformed taps:", d_xformed_taps); +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gr_fft_filter_ccc::compute_sizes(int ntaps) +{ + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if (0) + fprintf(stderr, "gr_fft_filter: ntaps = %d, fftsize = %d, nsamples = %d\n", + d_ntaps, d_fftsize, d_nsamples); + + assert(d_fftsize == d_ntaps + d_nsamples -1 ); + + if (d_fftsize != old_fftsize){ // compute new plans + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new gri_fft_complex(d_fftsize, true); + d_invfft = new gri_fft_complex(d_fftsize, false); + d_xformed_taps.resize(d_fftsize); + } + + set_output_multiple(d_nsamples); +} + +int +gr_fft_filter_ccc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated){ + actual_set_taps(d_new_taps); + d_updated = false; + return 0; // output multiple may have changed + } + + assert(noutput_items % d_nsamples == 0); + + int dec_ctr = 0; + int j = 0; + int ninput_items = noutput_items * decimation(); + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &in[i], d_nsamples * sizeof(gr_complex)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + gr_complex *a = d_fwdfft->get_outbuf(); + gr_complex *b = &d_xformed_taps[0]; + gr_complex *c = d_invfft->get_inbuf(); + + for (j = 0; j < d_fftsize; j++) // filter in the freq domain + c[j] = a[j] * b[j]; + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + + //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(gr_complex)); + //out += d_nsamples; + + j = dec_ctr; + while (j < d_nsamples) { + *out++ = d_invfft->get_outbuf()[j]; + j += decimation(); + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(gr_complex)); + } + + assert((out - (gr_complex *) output_items[0]) == noutput_items); + assert(dec_ctr == 0); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h new file mode 100644 index 00000000..06bc7c1b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FFT_FILTER_CCC_H +#define INCLUDED_GR_FFT_FILTER_CCC_H + +#include + +class gr_fft_filter_ccc; +typedef boost::shared_ptr gr_fft_filter_ccc_sptr; +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector &taps); + +class gr_fir_ccc; +class gri_fft_complex; + +/*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter + */ +class gr_fft_filter_ccc : public gr_sync_decimator +{ + private: + friend gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector &taps); + + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + gri_fft_complex *d_fwdfft; // forward "plan" + gri_fft_complex *d_invfft; // inverse "plan" + std::vector d_tail; // state carried between blocks for overlap-add + std::vector d_xformed_taps; // Fourier xformed taps + std::vector d_new_taps; + bool d_updated; + + /*! + * Construct a FFT filter with the given taps + * + * \param decimation >= 1 + * \param taps complex filter taps + */ + gr_fft_filter_ccc (int decimation, const std::vector &taps); + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + void actual_set_taps (const std::vector &taps); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector &taps); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + + +#endif /* INCLUDED_GR_FFT_FILTER_CCC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i new file mode 100644 index 00000000..65cbb362 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,fft_filter_ccc) + +gr_fft_filter_ccc_sptr +gr_make_fft_filter_ccc (int decimation, + const std::vector &taps + ) throw (std::invalid_argument); + +class gr_fft_filter_ccc : public gr_sync_decimator +{ + private: + gr_fft_filter_ccc (int decimation, const std::vector &taps); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc new file mode 100644 index 00000000..ceb2e828 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc @@ -0,0 +1,211 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector &taps) +{ + return gr_fft_filter_fff_sptr (new gr_fft_filter_fff (decimation, taps)); +} + + +gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector &taps) + : gr_sync_decimator ("fft_filter_fff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float)), + decimation), + d_fftsize(-1), d_fwdfft(0), d_invfft(0), d_updated(false) +{ + set_history(1); + actual_set_taps(taps); +} + +gr_fft_filter_fff::~gr_fft_filter_fff () +{ + delete d_fwdfft; + delete d_invfft; +} + +static void +print_vector_complex(const std::string label, const std::vector &x) +{ + std::cout << label; + for (unsigned i = 0; i < x.size(); i++) + std::cout << x[i] << " "; + std::cout << "\n"; +} + +static void +print_vector_float(const std::string label, const std::vector &x) +{ + std::cout << label; + for (unsigned i = 0; i < x.size(); i++) + std::cout << x[i] << " "; + std::cout << "\n"; +} + +void +gr_fft_filter_fff::set_taps (const std::vector &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +void +gr_fft_filter_fff::actual_set_taps (const std::vector &taps) +{ + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for (i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + float *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize/2+1; i++) + d_xformed_taps[i] = out[i]; + + //print_vector_complex("transformed taps:", d_xformed_taps); +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gr_fft_filter_fff::compute_sizes(int ntaps) +{ + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if (0) + fprintf(stderr, "gr_fft_filter: ntaps = %d, fftsize = %d, nsamples = %d\n", + d_ntaps, d_fftsize, d_nsamples); + + assert(d_fftsize == d_ntaps + d_nsamples -1 ); + + if (d_fftsize != old_fftsize){ // compute new plans + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new gri_fft_real_fwd(d_fftsize); + d_invfft = new gri_fft_real_rev(d_fftsize); + d_xformed_taps.resize(d_fftsize/2+1); + } + + set_output_multiple(d_nsamples); +} + +int +gr_fft_filter_fff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + if (d_updated){ + actual_set_taps(d_new_taps); + d_updated = false; + return 0; // output multiple may have changed + } + + assert(noutput_items % d_nsamples == 0); + + int dec_ctr = 0; + int j = 0; + int ninput_items = noutput_items * decimation(); + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &in[i], d_nsamples * sizeof(float)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + gr_complex *a = d_fwdfft->get_outbuf(); + gr_complex *b = &d_xformed_taps[0]; + gr_complex *c = d_invfft->get_inbuf(); + + for (j = 0; j < d_fftsize/2+1; j++) // filter in the freq domain + c[j] = a[j] * b[j]; + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + + //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(float)); + //out += d_nsamples; + + j = dec_ctr; + while (j < d_nsamples) { + *out++ = d_invfft->get_outbuf()[j]; + j += decimation(); + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(float)); + } + + assert((out - (float *) output_items[0]) == noutput_items); + assert(dec_ctr == 0); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h new file mode 100644 index 00000000..bdd29b70 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FFT_FILTER_FFF_H +#define INCLUDED_GR_FFT_FILTER_FFF_H + +#include + +class gr_fft_filter_fff; +typedef boost::shared_ptr gr_fft_filter_fff_sptr; +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector &taps); + +class gr_fir_fff; +class gri_fft_real_fwd; +class gri_fft_real_rev; + +/*! + * \brief Fast FFT filter with float input, float output and float taps + * \ingroup filter + */ +class gr_fft_filter_fff : public gr_sync_decimator +{ + private: + friend gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector &taps); + + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + gri_fft_real_fwd *d_fwdfft; // forward "plan" + gri_fft_real_rev *d_invfft; // inverse "plan" + std::vector d_tail; // state carried between blocks for overlap-add + std::vector d_xformed_taps; // Fourier xformed taps + std::vector d_new_taps; + bool d_updated; + + /*! + * Construct a FFT filter with the given taps + * + * \param decimation >= 1 + * \param taps float filter taps + */ + gr_fft_filter_fff (int decimation, const std::vector &taps); + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + void actual_set_taps (const std::vector &taps); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector &taps); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FFT_FILTER_FFF_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i new file mode 100644 index 00000000..5ee30ebb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,fft_filter_fff) + +gr_fft_filter_fff_sptr +gr_make_fft_filter_fff (int decimation, + const std::vector &taps + ) throw (std::invalid_argument); + +class gr_fft_filter_fff : public gr_sync_decimator +{ + private: + gr_fft_filter_fff (int decimation, const std::vector &taps); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc new file mode 100644 index 00000000..09f181ea --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +// public constructor +gr_filter_delay_fc_sptr +gr_make_filter_delay_fc (const std::vector &taps) +{ + return gr_filter_delay_fc_sptr (new gr_filter_delay_fc (taps)); +} + +gr_filter_delay_fc::gr_filter_delay_fc (const std::vector &taps) + : gr_sync_block ("filter_delay_fc", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ + d_fir = gr_fir_util::create_gr_fir_fff (taps); + d_delay = d_fir->ntaps () / 2; + set_history (d_fir->ntaps ()); +} + +gr_filter_delay_fc::~gr_filter_delay_fc () +{ + delete d_fir; +} + +int +gr_filter_delay_fc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in0 = (float *) input_items[0]; + float *in1 = (float *) input_items[1]; + gr_complex *out = (gr_complex *) output_items[0]; + + switch (input_items.size ()){ + case 1: + for (int i = 0; i < noutput_items; i++) + out[i] = gr_complex (in0[i + d_delay], + d_fir->filter (&in0[i])); + break; + + case 2: + for (int j = 0; j < noutput_items; j++) + out[j] = gr_complex (in0[j + d_delay], + d_fir->filter (&in1[j])); + break; + + default: + assert (0); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h new file mode 100644 index 00000000..2b65c672 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILTER_DELAY_FC_H +#define INCLUDED_GR_FILTER_DELAY_FC_H + +#include +#include +#include + +class gr_filter_delay_fc; +typedef boost::shared_ptr gr_filter_delay_fc_sptr; + +// public constructor +gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector &taps); + +class gr_fir_fff; + +/*! + * \brief Filter-Delay Combination Block. + * \ingroup filter + * + * The block takes one or two float stream and outputs a complex + * stream. If only one float stream is input, the real output is + * a delayed version of this input and the imaginary output is the + * filtered output. If two floats are connected to the input, then + * the real output is the delayed version of the first input, and + * the imaginary output is the filtered output. The delay in the + * real path accounts for the group delay introduced by the filter + * in the imaginary path. The filter taps needs to be calculated + * before initializing this block. + * + */ +class gr_filter_delay_fc : public gr_sync_block +{ + public: + ~gr_filter_delay_fc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + protected: + gr_filter_delay_fc (const std::vector &taps); + + private: + unsigned int d_delay; + gr_fir_fff *d_fir; + + friend gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector &taps); +}; + +#endif /* INCLUDED_GR_FILTER_DELAY_FC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_filter_delay_fc.i b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.i new file mode 100644 index 00000000..85603ce2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,filter_delay_fc); + +gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector &taps); + +class gr_filter_delay_fc : public gr_sync_block +{ +private: + gr_filter_delay_fc (); +}; + +// ---------------------------------------------------------------- + diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t new file mode 100644 index 00000000..1f786622 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include <@FIR_TYPE@.h> + +@FIR_TYPE@::~@FIR_TYPE@ () +{ +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t b/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t new file mode 100644 index 00000000..a5bf3ed0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fir_XXX.py + * Any changes made to this file will be overwritten. + */ + + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +@VRCOMPLEX_INCLUDE@ +#include + +/*! + * \brief Abstract class for FIR with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_primitive + * + * This is the abstract class for a Finite Impulse Response filter. + * + * The trailing suffix has the form _IOT where I codes the input type, + * O codes the output type, and T codes the tap type. + * I,O,T are elements of the set 's' (short), 'f' (float), 'c' (gr_complex), 'i' (int) + */ + +class @FIR_TYPE@ { + +protected: + std::vector<@TAP_TYPE@> d_taps; // reversed taps + +public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + @FIR_TYPE@ () {} + @FIR_TYPE@ (const std::vector<@TAP_TYPE@> &taps) : d_taps (gr_reverse(taps)) {} + + virtual ~@FIR_TYPE@ (); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + virtual @O_TYPE@ filter (const @I_TYPE@ input[]) = 0; + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + virtual void filterN (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n) = 0; + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + virtual void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n, unsigned decimate) = 0; + + /*! + * \brief install \p new_taps as the current taps. + */ + virtual void set_taps (const std::vector<@TAP_TYPE@> &taps) + { + d_taps = gr_reverse(taps); + } + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_taps.size (); } + + /*! + * \return current taps + */ + virtual const std::vector<@TAP_TYPE@> get_taps () const + { + return gr_reverse(d_taps); + } +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t new file mode 100644 index 00000000..7bc7a5eb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t @@ -0,0 +1,103 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include <@FIR_TYPE@_generic.h> + +#if (@N_UNROLL@ == 4) + +@O_TYPE@ +@FIR_TYPE@_generic::filter (const @I_TYPE@ input[]) +{ + static const int N_UNROLL = 4; + + @ACC_TYPE@ acc0 = 0; + @ACC_TYPE@ acc1 = 0; + @ACC_TYPE@ acc2 = 0; + @ACC_TYPE@ acc3 = 0; + + + unsigned i = 0; + unsigned n = (ntaps () / N_UNROLL) * N_UNROLL; + + for (i = 0; i < n; i += N_UNROLL){ + acc0 += d_taps[i + 0] * @INPUT_CAST@ input[i + 0]; + acc1 += d_taps[i + 1] * @INPUT_CAST@ input[i + 1]; + acc2 += d_taps[i + 2] * @INPUT_CAST@ input[i + 2]; + acc3 += d_taps[i + 3] * @INPUT_CAST@ input[i + 3]; + } + + for (; i < ntaps (); i++) + acc0 += d_taps[i] * @INPUT_CAST@ input[i]; + + return (@O_TYPE@) (acc0 + acc1 + acc2 + acc3); +} + +#else + +@O_TYPE@ +@FIR_TYPE@_generic::filter (const @I_TYPE@ input[]) +{ + static const int N_UNROLL = 2; + + @ACC_TYPE@ acc0 = 0; + @ACC_TYPE@ acc1 = 0; + + unsigned i = 0; + unsigned n = (ntaps () / N_UNROLL) * N_UNROLL; + + for (i = 0; i < n; i += N_UNROLL){ + acc0 += d_taps[i + 0] * @INPUT_CAST@ input[i + 0]; + acc1 += d_taps[i + 1] * @INPUT_CAST@ input[i + 1]; + } + + for (; i < ntaps (); i++) + acc0 += d_taps[i] * @INPUT_CAST@ input[i]; + + return (@O_TYPE@) (acc0 + acc1); +} + +#endif // N_UNROLL + +void +@FIR_TYPE@_generic::filterN (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (&input[i]); +} + +void +@FIR_TYPE@_generic::filterNdec (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n, + unsigned decimate) +{ + unsigned j = 0; + for (unsigned i = 0; i < n; i++){ + output[i] = filter (&input[j]); + j += decimate; + } +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t new file mode 100644 index 00000000..b1b2f402 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <@FIR_TYPE@.h> + +/*! + * \brief Concrete class for generic implementation of FIR with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * + * The trailing suffix has the form _IOT where I codes the input type, + * O codes the output type, and T codes the tap type. + * I,O,T are elements of the set 's' (short), 'f' (float), 'c' (gr_complex), 'i' (int) + */ + +class @FIR_TYPE@_generic : public @FIR_TYPE@ { + +public: + + // CREATORS + + @FIR_TYPE@_generic () {} + @FIR_TYPE@_generic (const std::vector<@TAP_TYPE@> &taps) : @FIR_TYPE@ (taps) {} + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + virtual @O_TYPE@ filter (const @I_TYPE@ input[]); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + virtual void filterN (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + virtual void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n, unsigned decimate); + +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc new file mode 100644 index 00000000..6d5cba3b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc @@ -0,0 +1,139 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +using std::cerr; +using std::endl; + +gr_fir_ccc_simd::gr_fir_ccc_simd () + : gr_fir_ccc_generic () +{ + // cerr << "@@@ gr_fir_ccc_simd\n"; + + d_ccomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_ccc_simd::gr_fir_ccc_simd (const std::vector &new_taps) + : gr_fir_ccc_generic (new_taps) +{ + // cerr << "@@@ gr_fir_ccc_simd\n"; + + d_ccomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_ccc_simd::~gr_fir_ccc_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_ccc_simd::set_taps (const std::vector &inew_taps) +{ + gr_fir_ccc::set_taps (inew_taps); // call superclass + + const std::vector new_taps = gr_reverse(inew_taps); + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 2, + 2 * 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_ccc_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) { + d_aligned_taps[i][2*(j+i)] = new_taps[j].real(); + d_aligned_taps[i][2*(j+i)+1] = new_taps[j].imag(); + } + } +} + +gr_complex +gr_fir_ccc_simd::filter (const gr_complex input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const gr_complex *ar = (gr_complex *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + d_ccomplex_dotprod ((float*)ar, d_aligned_taps[al], (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h new file mode 100644 index 00000000..89888871 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_CCC_SIMD_H +#define INCLUDED_GR_FIR_CCC_SIMD_H + +#include + +/*! + * \brief common base class for SIMD versions of gr_fir_ccc + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class gr_fir_ccc_simd : public gr_fir_ccc_generic +{ +protected: + typedef void (*ccomplex_dotprod_t)(const float *input, + const float *taps, + unsigned n_2_ccomplex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 floats to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + ccomplex_dotprod_t d_ccomplex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_ccc_simd (); + gr_fir_ccc_simd (const std::vector &taps); + ~gr_fir_ccc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &taps); + virtual gr_complex filter (const gr_complex input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc new file mode 100644 index 00000000..8b96c23d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * --- 3DNow! version --- + */ + +gr_fir_ccc_3dnow::gr_fir_ccc_3dnow () + : gr_fir_ccc_simd () +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnow; +} + +gr_fir_ccc_3dnow::gr_fir_ccc_3dnow (const std::vector &new_taps) + : gr_fir_ccc_simd (new_taps) +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnow; +} + + +/* + * --- 3DNow!Ext version --- + */ + +gr_fir_ccc_3dnowext::gr_fir_ccc_3dnowext () + : gr_fir_ccc_simd () +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnowext; +} + +gr_fir_ccc_3dnowext::gr_fir_ccc_3dnowext (const std::vector &new_taps) + : gr_fir_ccc_simd (new_taps) +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnowext; +} + + +/* + * --- SSE version --- + */ + +gr_fir_ccc_sse::gr_fir_ccc_sse () + : gr_fir_ccc_simd () +{ + d_ccomplex_dotprod = ccomplex_dotprod_sse; +} + +gr_fir_ccc_sse::gr_fir_ccc_sse (const std::vector &new_taps) + : gr_fir_ccc_simd (new_taps) +{ + d_ccomplex_dotprod = ccomplex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h new file mode 100644 index 00000000..ee2fe9b1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_CCC_X86_H +#define INCLUDED_GR_FIR_CCC_X86_H + +#include + +/*! + * \brief 3DNow! version of gr_fir_ccc + */ +class gr_fir_ccc_3dnow : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_3dnow (); + gr_fir_ccc_3dnow (const std::vector &taps); +}; + +class gr_fir_ccc_3dnowext : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_3dnowext (); + gr_fir_ccc_3dnowext (const std::vector &taps); +}; + +/*! + * \brief SSE version of gr_fir_ccc + */ +class gr_fir_ccc_sse : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_sse (); + gr_fir_ccc_sse (const std::vector &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc new file mode 100644 index 00000000..d1992d7c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +using std::cerr; +using std::endl; + +gr_fir_ccf_simd::gr_fir_ccf_simd () + : gr_fir_ccf_generic () +{ + // cerr << "@@@ gr_fir_ccf_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_ccf_simd::gr_fir_ccf_simd (const std::vector &new_taps) + : gr_fir_ccf_generic (new_taps) +{ + // cerr << "@@@ gr_fir_ccf_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_ccf_simd::~gr_fir_ccf_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_ccf_simd::set_taps (const std::vector &inew_taps) +{ + gr_fir_ccf::set_taps (inew_taps); // call superclass + const std::vector new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 4, + 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_ccf_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) + d_aligned_taps[i][j+i] = new_taps[j]; + } +} + +gr_complex +gr_fir_ccf_simd::filter (const gr_complex input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const gr_complex *ar = (gr_complex *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + // the trick here is to invert input and taps, and reuse FCC speedup + d_fcomplex_dotprod (d_aligned_taps[al], (float*)ar, (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h new file mode 100644 index 00000000..60898b43 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_CCF_SIMD_H +#define INCLUDED_GR_FIR_CCF_SIMD_H + +#include + + +/*! + * \brief common base class for SIMD versions of gr_fir_ccf + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class gr_fir_ccf_simd : public gr_fir_ccf_generic +{ +protected: + typedef void (*fcomplex_dotprod_t)(const float *taps, + const float *input, + unsigned n_2_complex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 float pairs to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + fcomplex_dotprod_t d_fcomplex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_ccf_simd (); + gr_fir_ccf_simd (const std::vector &taps); + ~gr_fir_ccf_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &taps); + virtual gr_complex filter (const gr_complex input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc new file mode 100644 index 00000000..9f288fc2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * --- 3DNow! version --- + */ + +gr_fir_ccf_3dnow::gr_fir_ccf_3dnow () + : gr_fir_ccf_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + +gr_fir_ccf_3dnow::gr_fir_ccf_3dnow (const std::vector &new_taps) + : gr_fir_ccf_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_ccf_sse::gr_fir_ccf_sse () + : gr_fir_ccf_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} + +gr_fir_ccf_sse::gr_fir_ccf_sse (const std::vector &new_taps) + : gr_fir_ccf_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h new file mode 100644 index 00000000..5c51a5f9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_CCF_X86_H +#define INCLUDED_GR_FIR_CCF_X86_H + +#include + +/*! + * \brief 3DNow! version of gr_fir_ccf + */ +class gr_fir_ccf_3dnow : public gr_fir_ccf_simd +{ +public: + gr_fir_ccf_3dnow (); + gr_fir_ccf_3dnow (const std::vector &taps); +}; + +/*! + * \brief SSE version of gr_fir_ccf + */ +class gr_fir_ccf_sse : public gr_fir_ccf_simd +{ +public: + gr_fir_ccf_sse (); + gr_fir_ccf_sse (const std::vector &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc new file mode 100644 index 00000000..c17d29f7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc @@ -0,0 +1,139 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +using std::cerr; +using std::endl; + +gr_fir_fcc_simd::gr_fir_fcc_simd () + : gr_fir_fcc_generic () +{ + // cerr << "@@@ gr_fir_fcc_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_fcc_simd::gr_fir_fcc_simd (const std::vector &new_taps) + : gr_fir_fcc_generic (new_taps) +{ + // cerr << "@@@ gr_fir_fcc_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_fcc_simd::~gr_fir_fcc_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_fcc_simd::set_taps (const std::vector &inew_taps) +{ + gr_fir_fcc::set_taps (inew_taps); // call superclass + const std::vector new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 2, + 2 * 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_fcc_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) { + d_aligned_taps[i][2*(j+i)] = new_taps[j].real(); + d_aligned_taps[i][2*(j+i)+1] = new_taps[j].imag(); + } + } +} + +gr_complex +gr_fir_fcc_simd::filter (const float input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const float *ar = (float *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + d_fcomplex_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h new file mode 100644 index 00000000..56248209 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_FCC_SIMD_H +#define INCLUDED_GR_FIR_FCC_SIMD_H + +#include + + +/*! + * \brief common base class for SIMD versions of gr_fir_fcc + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class gr_fir_fcc_simd : public gr_fir_fcc_generic +{ +protected: + typedef void (*fcomplex_dotprod_t)(const float *input, + const float *taps, + unsigned n_2_complex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 float pairs to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + fcomplex_dotprod_t d_fcomplex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_fcc_simd (); + gr_fir_fcc_simd (const std::vector &taps); + ~gr_fir_fcc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &taps); + virtual gr_complex filter (const float input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc new file mode 100644 index 00000000..e80dfe1f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * --- 3DNow! version --- + */ + +gr_fir_fcc_3dnow::gr_fir_fcc_3dnow () + : gr_fir_fcc_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + +gr_fir_fcc_3dnow::gr_fir_fcc_3dnow (const std::vector &new_taps) + : gr_fir_fcc_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_fcc_sse::gr_fir_fcc_sse () + : gr_fir_fcc_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} + +gr_fir_fcc_sse::gr_fir_fcc_sse (const std::vector &new_taps) + : gr_fir_fcc_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h new file mode 100644 index 00000000..500f4fb5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_FCC_X86_H +#define INCLUDED_GR_FIR_FCC_X86_H + +#include + +/*! + * \brief 3DNow! version of gr_fir_fcc + */ +class gr_fir_fcc_3dnow : public gr_fir_fcc_simd +{ +public: + gr_fir_fcc_3dnow (); + gr_fir_fcc_3dnow (const std::vector &taps); +}; + +/*! + * \brief SSE version of gr_fir_fcc + */ +class gr_fir_fcc_sse : public gr_fir_fcc_simd +{ +public: + gr_fir_fcc_sse (); + gr_fir_fcc_sse (const std::vector &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc new file mode 100644 index 00000000..92c4256e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc @@ -0,0 +1,134 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +using std::cerr; + +gr_fir_fff_simd::gr_fir_fff_simd () + : gr_fir_fff_generic () +{ + // cerr << "@@@ gr_fir_fff_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_fff_simd::gr_fir_fff_simd (const std::vector &new_taps) + : gr_fir_fff_generic (new_taps) +{ + // cerr << "@@@ gr_fir_fff_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_fff_simd::~gr_fir_fff_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_fff_simd::set_taps (const std::vector &inew_taps) +{ + gr_fir_fff::set_taps (inew_taps); // call superclass + const std::vector new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 4, + 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_fff_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) + d_aligned_taps[i][j+i] = new_taps[j]; + } +} + +float +gr_fir_fff_simd::filter (const float input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const float *ar = (float *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/4 + 1: " << (ntaps() + al -1) / 4 + 1 << endl; + + float r = d_float_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 4 + 1); + + // cerr << "result = " << r << endl; + + return r; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h new file mode 100644 index 00000000..375b1191 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_FFF_SIMD_H +#define INCLUDED_GR_FIR_FFF_SIMD_H + +#include + +/*! + * \brief common base class for SIMD versions of gr_fir_fff + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class gr_fir_fff_simd : public gr_fir_fff_generic +{ +protected: + typedef float (*float_dotprod_t)(const float *input, + const float *taps, + unsigned n_4_float_blocks); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 floats to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + float_dotprod_t d_float_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_fff_simd (); + gr_fir_fff_simd (const std::vector &taps); + ~gr_fir_fff_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &taps); + virtual float filter (const float input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc new file mode 100644 index 00000000..494a0f7e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * --- 3DNow! version --- + */ + +gr_fir_fff_3dnow::gr_fir_fff_3dnow () + : gr_fir_fff_simd () +{ + d_float_dotprod = float_dotprod_3dnow; +} + +gr_fir_fff_3dnow::gr_fir_fff_3dnow (const std::vector &new_taps) + : gr_fir_fff_simd (new_taps) +{ + d_float_dotprod = float_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_fff_sse::gr_fir_fff_sse () + : gr_fir_fff_simd () +{ + d_float_dotprod = float_dotprod_sse; +} + +gr_fir_fff_sse::gr_fir_fff_sse (const std::vector &new_taps) + : gr_fir_fff_simd (new_taps) +{ + d_float_dotprod = float_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_x86.h b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.h new file mode 100644 index 00000000..407ae3ff --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_FFF_X86_H +#define INCLUDED_GR_FIR_FFF_X86_H + +#include + +/*! + * \brief 3DNow! version of gr_fir_fff + */ +class gr_fir_fff_3dnow : public gr_fir_fff_simd +{ +public: + gr_fir_fff_3dnow (); + gr_fir_fff_3dnow (const std::vector &taps); +}; + +/*! + * \brief SSE version of gr_fir_fff + */ +class gr_fir_fff_sse : public gr_fir_fff_simd +{ +public: + gr_fir_fff_sse (); + gr_fir_fff_sse (const std::vector &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t new file mode 100644 index 00000000..91b3111e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include +#include + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps) +{ + return @SPTR_NAME@ (new @NAME@ (decimation, taps)); +} + + +@NAME@::@NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps) + : gr_sync_decimator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + decimation), + d_updated (false) +{ + d_fir = gr_fir_util::create_@FIR_TYPE@ (taps); + set_history (d_fir->ntaps ()); +} + +@NAME@::~@NAME@ () +{ + delete d_fir; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *in = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + if (d_updated) { + d_fir->set_taps (d_new_taps); + set_history (d_fir->ntaps ()); + d_updated = false; + return 0; // history requirements may have changed. + } + + if (decimation() == 1) + d_fir->filterN (out, in, noutput_items); + + else + d_fir->filterNdec (out, in, noutput_items, decimation()); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t new file mode 100644 index 00000000..b6e5d1aa --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +@SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + +class @FIR_TYPE@; + +/*! + * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter + */ +class @NAME@ : public gr_sync_decimator +{ + private: + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + + @FIR_TYPE@ *d_fir; + std::vector<@TAP_TYPE@> d_new_taps; + bool d_updated; + + /*! + * Construct a FIR filter with the given taps + */ + @NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t new file mode 100644 index 00000000..13c919d1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_GrFIRfilterXXX.py + * Any changes made to this file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + +class @NAME@ : public gr_sync_decimator +{ + private: + @NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc new file mode 100644 index 00000000..00b4e609 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc @@ -0,0 +1,133 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +using std::cerr; + +gr_fir_fsf_simd::gr_fir_fsf_simd () + : gr_fir_fsf_generic () +{ + // cerr << "@@@ gr_fir_fsf_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_fsf_simd::gr_fir_fsf_simd (const std::vector &new_taps) + : gr_fir_fsf_generic (new_taps) +{ + // cerr << "@@@ gr_fir_fsf_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_fsf_simd::~gr_fir_fsf_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_fsf_simd::set_taps (const std::vector &inew_taps) +{ + gr_fir_fsf::set_taps (inew_taps); // call superclass + const std::vector new_taps = gr_reverse(inew_taps); + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 4, + 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_fsf_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) + d_aligned_taps[i][j+i] = new_taps[j]; + } +} + +short +gr_fir_fsf_simd::filter (const float input[]) +{ + if (ntaps () == 0) + return 0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const float *ar = (float *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/4 + 1: " << (ntaps() + al -1) / 4 + 1 << endl; + + float r = d_float_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 4 + 1); + + // cerr << "result = " << r << endl; + + return (short) r; // FIXME? may want to saturate here +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h new file mode 100644 index 00000000..77e093ca --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_FIR_FSF_SIMD_H_ +#define _GR_FIR_FSF_SIMD_H_ + +#include + +/*! + * \brief common base class for SIMD versions of gr_fir_fsf + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class gr_fir_fsf_simd : public gr_fir_fsf_generic +{ +protected: + typedef float (*float_dotprod_t)(const float *input, + const float *taps, + unsigned n_4_float_blocks); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 floats to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + float_dotprod_t d_float_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_fsf_simd (); + gr_fir_fsf_simd (const std::vector &taps); + ~gr_fir_fsf_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &taps); + virtual short filter (const float input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc new file mode 100644 index 00000000..c407789d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * --- 3DNow! version --- + */ + +gr_fir_fsf_3dnow::gr_fir_fsf_3dnow () + : gr_fir_fsf_simd () +{ + d_float_dotprod = float_dotprod_3dnow; +} + +gr_fir_fsf_3dnow::gr_fir_fsf_3dnow (const std::vector &new_taps) + : gr_fir_fsf_simd (new_taps) +{ + d_float_dotprod = float_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_fsf_sse::gr_fir_fsf_sse () + : gr_fir_fsf_simd () +{ + d_float_dotprod = float_dotprod_sse; +} + +gr_fir_fsf_sse::gr_fir_fsf_sse (const std::vector &new_taps) + : gr_fir_fsf_simd (new_taps) +{ + d_float_dotprod = float_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h new file mode 100644 index 00000000..e8ae763f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_FSF_X86_H +#define INCLUDED_GR_FIR_FSF_X86_H + +#include + +/*! + * \brief 3DNow! version of gr_fir_fsf + */ +class gr_fir_fsf_3dnow : public gr_fir_fsf_simd +{ +public: + gr_fir_fsf_3dnow (); + gr_fir_fsf_3dnow (const std::vector &taps); +}; + +/*! + * \brief SSE version of gr_fir_fsf + */ +class gr_fir_fsf_sse : public gr_fir_fsf_simd +{ +public: + gr_fir_fsf_sse (); + gr_fir_fsf_sse (const std::vector &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc new file mode 100644 index 00000000..b6f91a74 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +using std::cerr; +using std::endl; + +gr_fir_scc_simd::gr_fir_scc_simd () + : gr_fir_scc_generic () +{ + // cerr << "@@@ gr_fir_scc_simd\n"; + + d_complex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_scc_simd::gr_fir_scc_simd (const std::vector &new_taps) + : gr_fir_scc_generic (new_taps) +{ + // cerr << "@@@ gr_fir_scc_simd\n"; + + d_complex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_scc_simd::~gr_fir_scc_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_scc_simd::set_taps (const std::vector &inew_taps) +{ + gr_fir_scc::set_taps (inew_taps); // call superclass + + const std::vector new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 2, + 2 * 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_scc_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) { + d_aligned_taps[i][2*(j+i)] = new_taps[j].real(); + d_aligned_taps[i][2*(j+i)+1] = new_taps[j].imag(); + } + } +} + +gr_complex +gr_fir_scc_simd::filter (const short input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 8 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const short *ar = (short *)((unsigned long) input & ~7); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 7) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + d_complex_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_simd.h b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.h new file mode 100644 index 00000000..098b02a5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_SCC_SIMD_H +#define INCLUDED_GR_FIR_SCC_SIMD_H + +#include + + +/*! + * \brief common base class for SIMD versions of gr_fir_scc + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class gr_fir_scc_simd : public gr_fir_scc_generic +{ +protected: + typedef void (*complex_dotprod_t)(const short *input, + const float *taps, + unsigned n_2_complex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 float pairs to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + complex_dotprod_t d_complex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_scc_simd (); + gr_fir_scc_simd (const std::vector &taps); + ~gr_fir_scc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &taps); + virtual gr_complex filter (const short input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc new file mode 100644 index 00000000..c654fce1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * --- 3DNow! version --- + */ + +gr_fir_scc_3dnow::gr_fir_scc_3dnow () + : gr_fir_scc_simd () +{ + d_complex_dotprod = complex_dotprod_3dnow; +} + +gr_fir_scc_3dnow::gr_fir_scc_3dnow (const std::vector &new_taps) + : gr_fir_scc_simd (new_taps) +{ + d_complex_dotprod = complex_dotprod_3dnow; +} + + +/* + * --- 3DNow! Ext version --- + */ + +gr_fir_scc_3dnowext::gr_fir_scc_3dnowext () + : gr_fir_scc_simd () +{ + d_complex_dotprod = complex_dotprod_3dnowext; +} + +gr_fir_scc_3dnowext::gr_fir_scc_3dnowext (const std::vector &new_taps) + : gr_fir_scc_simd (new_taps) +{ + d_complex_dotprod = complex_dotprod_3dnowext; +} + + +/* + * --- SSE version --- + */ + +gr_fir_scc_sse::gr_fir_scc_sse () + : gr_fir_scc_simd () +{ + d_complex_dotprod = complex_dotprod_sse; +} + +gr_fir_scc_sse::gr_fir_scc_sse (const std::vector &new_taps) + : gr_fir_scc_simd (new_taps) +{ + d_complex_dotprod = complex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h new file mode 100644 index 00000000..bbdf5eb7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_SCC_X86_H +#define INCLUDED_GR_FIR_SCC_X86_H + +#include + +/*! + * \brief 3DNow! version of gr_fir_scc + */ +class gr_fir_scc_3dnow : public gr_fir_scc_simd +{ +public: + gr_fir_scc_3dnow (); + gr_fir_scc_3dnow (const std::vector &taps); +}; + +/*! + * \brief 3DNow! Ext version of gr_fir_scc + */ +class gr_fir_scc_3dnowext : public gr_fir_scc_simd +{ +public: + gr_fir_scc_3dnowext (); + gr_fir_scc_3dnowext (const std::vector &taps); +}; + +/*! + * \brief SSE version of gr_fir_scc + */ +class gr_fir_scc_sse : public gr_fir_scc_simd +{ +public: + gr_fir_scc_sse (); + gr_fir_scc_sse (const std::vector &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc new file mode 100644 index 00000000..7d576e8b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc @@ -0,0 +1,553 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include +// #include +// #include + +#include +using std::cerr; + +/* + * ---------------------------------------------------------------- + * static functions that serve as constructors... + * Is it possible to take the address of a normal constructor? + * ---------------------------------------------------------------- + */ + +static gr_fir_ccf * +make_gr_fir_ccf_3dnow(const std::vector &taps) +{ + return new gr_fir_ccf_3dnow(taps); +} + +static gr_fir_ccf * +make_gr_fir_ccf_sse(const std::vector &taps) +{ + return new gr_fir_ccf_sse(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_3dnow(const std::vector &taps) +{ + return new gr_fir_fcc_3dnow(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_sse(const std::vector &taps) +{ + return new gr_fir_fcc_sse(taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_3dnow (const std::vector &taps) +{ + return new gr_fir_ccc_3dnow (taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_3dnowext (const std::vector &taps) +{ + return new gr_fir_ccc_3dnowext (taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_sse (const std::vector &taps) +{ + return new gr_fir_ccc_sse (taps); +} + +static gr_fir_fff * +make_gr_fir_fff_3dnow (const std::vector &taps) +{ + return new gr_fir_fff_3dnow (taps); +} + +static gr_fir_fff * +make_gr_fir_fff_sse (const std::vector &taps) +{ + return new gr_fir_fff_sse (taps); +} + +static gr_fir_fsf * +make_gr_fir_fsf_3dnow (const std::vector &taps) +{ + return new gr_fir_fsf_3dnow (taps); +} + +static gr_fir_fsf * +make_gr_fir_fsf_sse (const std::vector &taps) +{ + return new gr_fir_fsf_sse (taps); +} + +#if 0 +static gr_fir_sss * +make_gr_fir_sss_mmx (const std::vector &taps) +{ + return new gr_fir_sss_mmx (taps); +} + +static gr_fir_sss * +make_gr_fir_sss_sse2 (const std::vector &taps) +{ + return new gr_fir_sss_sse2 (taps); +} +#endif + +static gr_fir_scc * +make_gr_fir_scc_3dnow(const std::vector &taps) +{ + return new gr_fir_scc_3dnow(taps); +} + +static gr_fir_scc * +make_gr_fir_scc_3dnowext(const std::vector &taps) +{ + return new gr_fir_scc_3dnowext(taps); +} + +static gr_fir_scc * +make_gr_fir_scc_sse(const std::vector &taps) +{ + return new gr_fir_scc_sse(taps); +} + +/* + * ---------------------------------------------------------------- + * Return instances of the fastest x86 versions of these classes. + * + * check CPUID, if has 3DNowExt, return 3DNow!Ext version, + * else if 3DNow, return 3DNow! version, + * else if SSE2, return SSE2 version, + * else if SSE, return SSE version, + * else if MMX, return MMX version, + * else return generic version. + * + * FIXME: benchmark, store result, use stored result to + * select the fastest version. + * ---------------------------------------------------------------- + */ + +gr_fir_ccf * +gr_fir_sysconfig_x86::create_gr_fir_ccf (const std::vector &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first){ + cerr << ">>> gr_fir_ccf: using 3DNow!\n"; + first = false; + } + return make_gr_fir_ccf_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_ccf: using SSE\n"; + first = false; + } + return make_gr_fir_ccf_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_ccf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccf (taps); +} + +gr_fir_fcc * +gr_fir_sysconfig_x86::create_gr_fir_fcc (const std::vector &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first){ + cerr << ">>> gr_fir_fcc: using 3DNow!\n"; + first = false; + } + return make_gr_fir_fcc_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_fcc: using SSE\n"; + first = false; + } + return make_gr_fir_fcc_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_fcc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fcc (taps); +} + +gr_fir_ccc * +gr_fir_sysconfig_x86::create_gr_fir_ccc (const std::vector &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnowext ()){ + if (first) { + cerr << ">>> gr_fir_ccc: using 3DNow!Ext\n"; + first = false; + } + return make_gr_fir_ccc_3dnowext (taps); + } + + if (gr_cpu::has_3dnow ()){ + if (first) { + cerr << ">>> gr_fir_ccc: using 3DNow!\n"; + first = false; + } + return make_gr_fir_ccc_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_ccc: using SSE\n"; + first = false; + } + return make_gr_fir_ccc_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_ccc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccc (taps); +} + +gr_fir_fff * +gr_fir_sysconfig_x86::create_gr_fir_fff (const std::vector &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first) { + cerr << ">>> gr_fir_fff: using 3DNow!\n"; + first = false; + } + return make_gr_fir_fff_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_fff: using SSE\n"; + first = false; + } + return make_gr_fir_fff_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_fff: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fff (taps); +} + +gr_fir_fsf * +gr_fir_sysconfig_x86::create_gr_fir_fsf (const std::vector &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first) { + cerr << ">>> gr_fir_fsf: using 3DNow!\n"; + first = false; + } + return make_gr_fir_fsf_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_fsf: using SSE\n"; + first = false; + } + return make_gr_fir_fsf_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_fsf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fsf (taps); +} + +#if 0 +gr_fir_sss * +gr_fir_sysconfig_x86::create_gr_fir_sss (const std::vector &taps) +{ + // FIXME -- probably want to figure out best answer for Athlon and code + // add code to select it here... + + if (gr_cpu::has_sse2 ()){ + cerr << ">>> gr_fir_sss: using SSE2\n"; + return make_gr_fir_sss_sse2 (taps); + } + + if (gr_cpu::has_mmx ()){ + cerr << ">>> gr_fir_sss: using MMX\n"; + return make_gr_fir_sss_mmx (taps); + } + + cerr << ">>> gr_fir_sss: handing off to parent class\n"; + return gr_fir_sysconfig_generic::create_gr_fir_sss (taps); +} +#endif + +gr_fir_scc * +gr_fir_sysconfig_x86::create_gr_fir_scc (const std::vector &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnowext ()){ + if (first){ + cerr << ">>> gr_fir_scc: using 3DNow!Ext\n"; + first = false; + } + return make_gr_fir_scc_3dnowext (taps); + } + + if (gr_cpu::has_3dnow ()){ + if (first){ + cerr << ">>> gr_fir_scc: using 3DNow!\n"; + first = false; + } + return make_gr_fir_scc_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_scc: using SSE\n"; + first = false; + } + return make_gr_fir_scc_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_scc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_scc (taps); +} + +/* + * ---------------------------------------------------------------- + * Return info about available implementations + * ---------------------------------------------------------------- + */ + +void +gr_fir_sysconfig_x86::get_gr_fir_ccf_info (std::vector *info) +{ + gr_fir_ccf_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccf_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_ccf_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_ccf_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_fcc_info (std::vector *info) +{ + gr_fir_fcc_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fcc_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_fcc_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_fcc_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_ccc_info (std::vector *info) +{ + gr_fir_ccc_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccc_info (info); + + // add our stuff... + if (gr_cpu::has_3dnowext ()){ + t.name = "3DNow!Ext"; + t.create = make_gr_fir_ccc_3dnowext; + (*info).push_back (t); + } + + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_ccc_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_ccc_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_fff_info (std::vector *info) +{ + gr_fir_fff_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fff_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_fff_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_fff_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_fsf_info (std::vector *info) +{ + gr_fir_fsf_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fsf_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_fsf_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_fsf_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_scc_info (std::vector *info) +{ + gr_fir_scc_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_scc_info (info); + + // add our stuff... + if (gr_cpu::has_3dnowext ()){ + t.name = "3DNow!Ext"; + t.create = make_gr_fir_scc_3dnowext; + (*info).push_back (t); + } + + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_scc_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_scc_sse; + (*info).push_back (t); + } +} + +#if 0 +void +gr_fir_sysconfig_x86::get_gr_fir_sss_info (std::vector *info) +{ + gr_fir_sss_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_sss_info (info); + + // add our stuff... + if (gr_cpu::has_mmx ()){ + t.name = "MMX"; + t.create = make_gr_fir_sss_mmx; + (*info).push_back (t); + } + + if (gr_cpu::has_sse2 ()){ + t.name = "SSE2"; + t.create = make_gr_fir_sss_sse2; + (*info).push_back (t); + } +} +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h new file mode 100644 index 00000000..2f1d48ef --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_SYSCONFIG_X86_H +#define INCLUDED_GR_FIR_SYSCONFIG_X86_H + +#include + +class gr_fir_sysconfig_x86 : public gr_fir_sysconfig_generic { +public: + virtual gr_fir_ccf *create_gr_fir_ccf (const std::vector &taps); + virtual gr_fir_fcc *create_gr_fir_fcc (const std::vector &taps); + virtual gr_fir_fff *create_gr_fir_fff (const std::vector &taps); + virtual gr_fir_fsf *create_gr_fir_fsf (const std::vector &taps); + virtual gr_fir_scc *create_gr_fir_scc (const std::vector &taps); + virtual gr_fir_ccc *create_gr_fir_ccc (const std::vector &taps); +//virtual gr_fir_sss *create_gr_fir_sss (const std::vector &taps); + + virtual void get_gr_fir_ccf_info (std::vector *info); + virtual void get_gr_fir_fcc_info (std::vector *info); + virtual void get_gr_fir_fff_info (std::vector *info); + virtual void get_gr_fir_fsf_info (std::vector *info); + virtual void get_gr_fir_scc_info (std::vector *info); + virtual void get_gr_fir_ccc_info (std::vector *info); +//virtual void get_gr_fir_sss_info (std::vector *info); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator.cc b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.cc new file mode 100644 index 00000000..6abb963d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +// Public constructor +gr_fractional_interpolator_sptr gr_make_fractional_interpolator(float phase_shift, float interp_ratio) +{ + return gr_fractional_interpolator_sptr(new gr_fractional_interpolator(phase_shift, interp_ratio)); +} + +gr_fractional_interpolator::gr_fractional_interpolator(float phase_shift, float interp_ratio) + : gr_block ("fractional_interpolator", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_mu (phase_shift), d_mu_inc (interp_ratio), d_interp() +{ + if (interp_ratio <= 0) + throw std::out_of_range ("interpolation ratio must be > 0"); + if (phase_shift < 0 || phase_shift > 1) + throw std::out_of_range ("phase shift ratio must be > 0 and < 1"); + + set_relative_rate (1.0 / interp_ratio); +} + +gr_fractional_interpolator::~gr_fractional_interpolator() +{ + delete d_interp; +} + +void +gr_fractional_interpolator::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i=0; i < ninputs; i++) + + ninput_items_required[i] = + (int) ceil((noutput_items * d_mu_inc) + d_interp->ntaps()); +} + +int +gr_fractional_interpolator::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + int ii = 0; // input index + int oo = 0; // output index + + while (oo < noutput_items){ + + // produce output sample + + out[oo++] = d_interp->interpolate(&in[ii], d_mu); + + // printf( "%4d %9.6f\n", ii, d_mu); + + double s = d_mu + d_mu_inc; + double f = floor (s); + int incr = (int) f; + d_mu = s - f; + ii += incr; + } + + consume_each (ii); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator.h b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.h new file mode 100644 index 00000000..b024c441 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FRACTIONAL_INTERPOLATOR_H +#define INCLUDED_GR_FRACTIONAL_INTERPOLATOR_H + +#include + +class gri_mmse_fir_interpolator; + +class gr_fractional_interpolator; +typedef boost::shared_ptr gr_fractional_interpolator_sptr; + +// public constructor +gr_fractional_interpolator_sptr gr_make_fractional_interpolator (float phase_shift, float interp_ratio); + +/*! + * \brief Interpolating mmse filter with float input, float output + * \ingroup filter + */ +class gr_fractional_interpolator : public gr_block +{ + public: + ~gr_fractional_interpolator (); + 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); + +protected: + gr_fractional_interpolator (float phase_shift, float interp_ratio); + + private: + float d_mu; + float d_mu_inc; + gri_mmse_fir_interpolator *d_interp; + + friend gr_fractional_interpolator_sptr + gr_make_fractional_interpolator (float phase_shift, float interp_ratio); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t new file mode 100644 index 00000000..4592e754 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t @@ -0,0 +1,122 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_freq_xlating_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq) +{ + return @SPTR_NAME@ (new @NAME@ (decimation, taps, center_freq, sampling_freq)); +} + + +@NAME@::@NAME@ ( + + int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, + double sampling_freq) + + : gr_sync_decimator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + decimation), + d_proto_taps (taps), d_center_freq (center_freq), d_sampling_freq (sampling_freq), + d_updated (false) +{ + std::vector dummy_taps; + d_composite_fir = gr_fir_util::create_@FIR_TYPE@ (dummy_taps); + + set_history (d_proto_taps.size ()); + build_composite_fir (); +} + +@NAME@::~@NAME@ () +{ + delete d_composite_fir; +} + +void +@NAME@::build_composite_fir () +{ + std::vector ctaps (d_proto_taps.size ()); + + float fwT0 = 2 * M_PI * d_center_freq / d_sampling_freq; + for (unsigned int i = 0; i < d_proto_taps.size (); i++) + ctaps[i] = d_proto_taps[i] * exp (gr_complex (0, i * fwT0)); + + d_composite_fir->set_taps (gr_reverse(ctaps)); + d_r.set_phase_incr (exp (gr_complex (0, fwT0 * decimation ()))); +} + +void +@NAME@::set_center_freq (double center_freq) +{ + d_center_freq = center_freq; + d_updated = true; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_proto_taps = taps; + d_updated = true; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *in = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + // rebuild composite FIR if the center freq has changed + + if (d_updated){ + set_history (d_proto_taps.size ()); + build_composite_fir (); + d_updated = false; + } + + unsigned j = 0; + for (int i = 0; i < noutput_items; i++){ + out[i] = d_r.rotate (d_composite_fir->filter (&in[j])); + j += decimation (); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t new file mode 100644 index 00000000..d1351e20 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_freq_xlating_fir_filter_XXX.py Any changes made to this file + * will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +/*! + * Construct a FIR filter with the given taps and a composite frequency + * translation that shifts center_freq down to zero Hz. The frequency + * translation logically comes before the filtering operation. + */ +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + +class @FIR_TYPE@; + +/*! + * \brief FIR filter combined with frequency translation with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter + * + * This class efficiently combines a frequency translation + * (typically "down conversion") with a FIR filter (typically low-pass) + * and decimation. It is ideally suited for a "channel selection filter" + * and can be efficiently used to select and decimate a narrow band signal + * out of wide bandwidth input. + * + * Uses a single input array to produce a single output array. + * Additional inputs and/or outputs are ignored. + */ +class @NAME@ : public gr_sync_decimator +{ + public: + virtual ~@NAME@ (); + + void set_center_freq (double center_freq); + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + private: + friend @SPTR_NAME@ + gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + protected: + std::vector<@TAP_TYPE@> d_proto_taps; + @FIR_TYPE@ *d_composite_fir; + gr_rotator d_r; + double d_center_freq; + double d_sampling_freq; + bool d_updated; + + virtual void build_composite_fir (); + + /*! + * Construct a FIR filter with the given taps and a composite frequency + * translation that shifts center_freq down to zero Hz. The frequency + * translation logically comes before the filtering operation. + */ + @NAME@ (int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); +}; + +#endif /* _@NAME@_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t new file mode 100644 index 00000000..0a4f8b31 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_freq_xlating_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + +class @NAME@ : public gr_sync_decimator +{ + protected: + @NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + public: + ~@NAME@ (); + + void set_center_freq (double center_freq); + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc b/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc new file mode 100644 index 00000000..264b96e6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +// public constructor +gr_goertzel_fc_sptr +gr_make_goertzel_fc(int rate, int len, float freq) +{ + return gr_goertzel_fc_sptr (new gr_goertzel_fc(rate, len, freq)); +} + +gr_goertzel_fc::gr_goertzel_fc(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; +} + +int gr_goertzel_fc::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; +} diff --git a/gnuradio-core/src/lib/filter/gr_goertzel_fc.h b/gnuradio-core/src/lib/filter/gr_goertzel_fc.h new file mode 100644 index 00000000..c8363bc4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_GOERTZEL_FC_H +#define INCLUDED_GR_GOERTZEL_FC_H + +#include +#include + +class gr_goertzel_fc; +typedef boost::shared_ptr gr_goertzel_fc_sptr; + +// public constructor +gr_goertzel_fc_sptr gr_make_goertzel_fc(int rate, int len, float freq); + +/*! + * \brief Goertzel single-bin DFT calculation. + * \ingroup filter + */ +class gr_goertzel_fc : public gr_sync_decimator +{ +private: + friend gr_goertzel_fc_sptr gr_make_goertzel_fc (int rate, int len, float freq); + + gr_goertzel_fc(int rate, int len, float freq); + gri_goertzel d_goertzel; + int d_len; + +public: + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_GOERTZEL_FC_H */ + diff --git a/gnuradio-core/src/lib/filter/gr_goertzel_fc.i b/gnuradio-core/src/lib/filter/gr_goertzel_fc.i new file mode 100644 index 00000000..6d5efd23 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,goertzel_fc); + +gr_goertzel_fc_sptr gr_make_goertzel_fc(int rate, int len, float freq); + +class gr_goertzel_fc : public gr_sync_decimator +{ +private: + gr_goertzel_fc(); +}; diff --git a/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc b/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc new file mode 100644 index 00000000..371363c3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +// public constructor +gr_hilbert_fc_sptr +gr_make_hilbert_fc (unsigned int ntaps) +{ + return gr_hilbert_fc_sptr (new gr_hilbert_fc (ntaps)); +} + +gr_hilbert_fc::gr_hilbert_fc (unsigned int ntaps) + : gr_sync_block ("hilbert_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_ntaps (ntaps | 0x1), // ensure ntaps is odd + d_hilb (gr_fir_util::create_gr_fir_fff (gr_firdes::hilbert (d_ntaps))) +{ + set_history (d_ntaps); +} + +gr_hilbert_fc::~gr_hilbert_fc () +{ + delete d_hilb; +} + +int +gr_hilbert_fc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) + out[i] = gr_complex (in[i + d_ntaps/2], + d_hilb->filter (&in[i])); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_hilbert_fc.h b/gnuradio-core/src/lib/filter/gr_hilbert_fc.h new file mode 100644 index 00000000..54082a95 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_HILBERT_FC_H +#define INCLUDED_GR_HILBERT_FC_H + +#include +#include +#include + +class gr_hilbert_fc; +typedef boost::shared_ptr gr_hilbert_fc_sptr; + +// public constructor +gr_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); + + +class gr_fir_fff; + +/*! + * \brief Hilbert transformer. + * \ingroup filter + * + * real output is input appropriately delayed. + * imaginary output is hilbert filtered (90 degree phase shift) + * version of input. + */ +class gr_hilbert_fc : public gr_sync_block +{ + public: + ~gr_hilbert_fc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + protected: + gr_hilbert_fc (unsigned int ntaps); + + private: + unsigned int d_ntaps; + gr_fir_fff *d_hilb; + + friend gr_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); +}; + + + +#endif /* INCLUDED_GR_HILBERT_FC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_hilbert_fc.i b/gnuradio-core/src/lib/filter/gr_hilbert_fc.i new file mode 100644 index 00000000..f69f624a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,hilbert_fc); + +gr_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); + +class gr_hilbert_fc : public gr_sync_block +{ +protected: + gr_hilbert_fc (unsigned int ntaps); + +public: + ~gr_hilbert_fc (); +}; diff --git a/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc new file mode 100644 index 00000000..4e825e7a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument) +{ + return gr_iir_filter_ffd_sptr (new gr_iir_filter_ffd (fftaps, fbtaps)); +} + +gr_iir_filter_ffd::gr_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument) + + : gr_sync_block ("iir_filter_ffd", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_iir (fftaps, fbtaps), + d_updated (false) +{ + // fprintf (stderr, "gr_iir_filter_ffd::ctor\n"); +} + +gr_iir_filter_ffd::~gr_iir_filter_ffd () +{ + // nop +} + +void +gr_iir_filter_ffd::set_taps (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument) +{ + if (fftaps.size () != fbtaps.size ()){ + fprintf (stderr, + "gr_iir_filter_ffd::set_taps: fftaps and fbtaps must have the same number of elements.\n"); + throw std::invalid_argument ("gr_iir_filter_ffd::set_taps"); + } + + d_new_fftaps = fftaps; + d_new_fbtaps = fbtaps; + d_updated = true; +} + +int +gr_iir_filter_ffd::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + // fprintf (stderr, "gr_iir_filter_ffd::work noutput_items = %d\n", noutput_items); + + if (d_updated){ + d_iir.set_taps (d_new_fftaps, d_new_fbtaps); + d_updated = false; + } + + d_iir.filter_n (out, in, noutput_items); + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h new file mode 100644 index 00000000..5ef36349 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_IIR_FILTER_FFD_H +#define INCLUDED_GR_IIR_FILTER_FFD_H + +#include +#include +#include + +class gr_iir_filter_ffd; +typedef boost::shared_ptr gr_iir_filter_ffd_sptr; +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + +/*! + * \brief IIR filter with float input, float output and double taps + * \ingroup filter + * + * This filter uses the Direct Form I implementation, where + * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones. + * + * \p fftaps and \p fbtaps must have equal numbers of taps + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - \sum_{k=1}^{N} a_k y[n-k] = \sum_{k=0}^{M} b_k x[n-k] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback taps. + */ +class gr_iir_filter_ffd : public gr_sync_block +{ + private: + friend gr_iir_filter_ffd_sptr + gr_make_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + gri_iir d_iir; + std::vector d_new_fftaps; + std::vector d_new_fbtaps; + bool d_updated; + + /*! + * Construct an IIR filter with the given taps + */ + gr_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + public: + ~gr_iir_filter_ffd (); + + void set_taps (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.i b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.i new file mode 100644 index 00000000..bab8310f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,iir_filter_ffd); + +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + +class gr_iir_filter_ffd : public gr_sync_block +{ + private: + gr_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + public: + ~gr_iir_filter_ffd (); + + void set_taps (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); +}; diff --git a/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t new file mode 100644 index 00000000..f382a7cd --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t @@ -0,0 +1,146 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include +#include +#include +#include + +@SPTR_NAME@ gr_make_@BASE_NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps) +{ + return @SPTR_NAME@ (new @NAME@ (interpolation, taps)); +} + + +@NAME@::@NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps) + : gr_sync_interpolator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + interpolation), + d_updated (false), d_firs (interpolation) +{ + if (interpolation == 0) + throw std::out_of_range ("interpolation must be > 0"); + + std::vector<@TAP_TYPE@> dummy_taps; + + for (unsigned i = 0; i < interpolation; i++) + d_firs[i] = gr_fir_util::create_@FIR_TYPE@ (dummy_taps); + + set_taps (taps); + install_taps(d_new_taps); +} + +@NAME@::~@NAME@ () +{ + int interp = interpolation (); + for (int i = 0; i < interp; i++) + delete d_firs[i]; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_new_taps = taps; + d_updated = true; + + // round up length to a multiple of the interpolation factor + int n = taps.size () % interpolation (); + if (n > 0){ + n = interpolation () - n; + while (n-- > 0) + d_new_taps.insert(d_new_taps.begin(), 0); + } + + assert (d_new_taps.size () % interpolation () == 0); +} + + +void +@NAME@::install_taps (const std::vector<@TAP_TYPE@> &taps) +{ + int nfilters = interpolation (); + int nt = taps.size () / nfilters; + + assert (nt * nfilters == (int) taps.size ()); + + std::vector< std::vector <@TAP_TYPE@> > xtaps (nfilters); + + for (int n = 0; n < nfilters; n++) + xtaps[n].resize (nt); + + for (int i = 0; i < (int) taps.size(); i++) + xtaps[i % nfilters][i / nfilters] = taps[i]; + + for (int n = 0; n < nfilters; n++) + d_firs[n]->set_taps (xtaps[n]); + + set_history (nt); + d_updated = false; + +#if 0 + for (int i = 0; i < nfilters; i++){ + std::cout << "filter[" << i << "] = "; + for (int j = 0; j < nt; j++) + std::cout << xtaps[i][j] << " "; + + std::cout << "\n"; + } +#endif + +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + if (d_updated) { + install_taps (d_new_taps); + return 0; // history requirements may have changed. + } + + int nfilters = interpolation (); + int ni = noutput_items / interpolation (); + + for (int i = 0; i < ni; i++){ + for (int nf = 0; nf < nfilters; nf++) + out[nf] = d_firs[nf]->filter (&in[i]); + out += nfilters; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t new file mode 100644 index 00000000..866c43ab --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +@SPTR_NAME@ gr_make_@BASE_NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps); + +class @FIR_TYPE@; + +/*! + * \brief Interpolating FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter + */ +class @NAME@ : public gr_sync_interpolator +{ + private: + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps); + + std::vector<@TAP_TYPE@> d_new_taps; + bool d_updated; + std::vector<@FIR_TYPE@ *> d_firs; + + /*! + * Construct a FIR filter with the given taps + */ + @NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps); + + void install_taps (const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.i.t new file mode 100644 index 00000000..d58c823f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.i.t @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_GrFIRfilterXXX.py + * Any changes made to this file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int interpolation, const std::vector<@TAP_TYPE@> &taps); + +class @NAME@ : public gr_sync_interpolator +{ + private: + @NAME@ (int interpolation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t new file mode 100644 index 00000000..a07b739e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t @@ -0,0 +1,172 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_rational_resampler_base_XXX.py Any changes made to this + * file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include +#include +#include +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps) +{ + return @SPTR_NAME@ (new @NAME@ (interpolation, decimation, taps)); +} + +@NAME@::@NAME@ (unsigned interpolation, unsigned decimation, + const std::vector<@TAP_TYPE@> &taps) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_history(1), + d_interpolation(interpolation), d_decimation(decimation), + d_ctr(0), d_updated(false), + d_firs(interpolation) +{ + if (interpolation == 0) + throw std::out_of_range ("interpolation must be > 0"); + if (decimation == 0) + throw std::out_of_range ("decimation must be > 0"); + + set_relative_rate (1.0 * interpolation / decimation); + set_output_multiple (1); + + std::vector<@TAP_TYPE@> dummy_taps; + + for (unsigned i = 0; i < interpolation; i++) + d_firs[i] = gr_fir_util::create_@FIR_TYPE@ (dummy_taps); + + set_taps (taps); + install_taps (d_new_taps); +} + +@NAME@::~@NAME@ () +{ + int interp = interpolation(); + for (int i = 0; i < interp; i++) + delete d_firs[i]; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_new_taps = taps; + d_updated = true; + + // round up length to a multiple of the interpolation factor + int n = taps.size () % interpolation (); + if (n > 0){ + n = interpolation () - n; + while (n-- > 0) + d_new_taps.insert(d_new_taps.begin(), 0); + } + + assert (d_new_taps.size () % interpolation () == 0); +} + + +void +@NAME@::install_taps (const std::vector<@TAP_TYPE@> &taps) +{ + int nfilters = interpolation (); + int nt = taps.size () / nfilters; + + assert (nt * nfilters == (int) taps.size ()); + + std::vector< std::vector <@TAP_TYPE@> > xtaps (nfilters); + + for (int n = 0; n < nfilters; n++) + xtaps[n].resize (nt); + + for (int i = 0; i < (int) taps.size(); i++) + xtaps[i % nfilters][i / nfilters] = taps[i]; + + for (int n = 0; n < nfilters; n++) + d_firs[n]->set_taps (xtaps[n]); + + set_history (nt); + d_updated = false; + +#if 0 + for (int i = 0; i < nfilters; i++){ + std::cout << "filter[" << i << "] = "; + for (int j = 0; j < nt; j++) + std::cout << xtaps[i][j] << " "; + + std::cout << "\n"; + } +#endif + +} + +void +@NAME@::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + int nreqd = std::max((unsigned)1, (int)((double) (noutput_items+1) * decimation() / interpolation()) + history() - 1); + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = nreqd; +} + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + if (d_updated) { + install_taps (d_new_taps); + return 0; // history requirement may have increased. + } + + unsigned int ctr = d_ctr; + + int i = 0; + while (i < noutput_items){ + out[i++] = d_firs[ctr]->filter(in); + ctr += decimation(); + while (ctr >= interpolation()){ + ctr -= interpolation(); + in++; + } + } + + d_ctr = ctr; + consume_each(in - (@I_TYPE@ *) input_items[0]); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t new file mode 100644 index 00000000..01172693 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_rational_resampler_base_XXX.py Any changes made to this + * file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps); + +class @FIR_TYPE@; + +/*! + * \brief Rational Resampling Polyphase FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter + */ +class @NAME@ : public gr_block +{ + private: + unsigned d_history; + unsigned d_interpolation, d_decimation; + unsigned d_ctr; + std::vector<@TAP_TYPE@> d_new_taps; + bool d_updated; + std::vector<@FIR_TYPE@ *> d_firs; + + friend @SPTR_NAME@ + gr_make_@BASE_NAME@ (unsigned interpolation, unsigned decimation, const std::vector<@TAP_TYPE@> &taps); + + + /*! + * Construct a FIR filter with the given taps + */ + @NAME@ (unsigned interpolation, unsigned decimation, + const std::vector<@TAP_TYPE@> &taps); + + void install_taps (const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + unsigned history () const { return d_history; } + void set_history (unsigned history) { d_history = history; } + + unsigned interpolation() const { return d_interpolation; } + unsigned decimation() const { return d_decimation; } + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t new file mode 100644 index 00000000..2411d034 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_rational_resampler_base_XXX.py Any changes made to this + * file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int interpolation, int decimation, const std::vector<@TAP_TYPE@> &taps); + +class @NAME@ : public gr_block +{ + private: + @NAME@ (int interpolation, int decimation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_rotator.h b/gnuradio-core/src/lib/filter/gr_rotator.h new file mode 100644 index 00000000..930b1cc2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rotator.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_ROTATOR_H_ +#define _GR_ROTATOR_H_ + +#include + +class gr_rotator { + gr_complex d_phase; + gr_complex d_phase_incr; + + public: + gr_rotator () : d_phase (1), d_phase_incr (0) { } + + void set_phase (gr_complex phase) { d_phase = phase; } + void set_phase_incr (gr_complex incr) { d_phase_incr = incr; } + + gr_complex rotate (gr_complex in){ + d_phase *= d_phase_incr; // incr our phase (complex mult == add phases) + + d_phase /= abs(d_phase); // ensure multiplication is rotation + // FIXME. This is expensive. Maybe workaround using + // double precision complex??? + + return in * d_phase; // rotate in by phase + } + +}; + +#endif /* _GR_ROTATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_sincos.c b/gnuradio-core/src/lib/filter/gr_sincos.c new file mode 100644 index 00000000..44c85740 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_sincos.c @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _GNU_SOURCE // ask for GNU extensions if available + +#include +#include + +// ---------------------------------------------------------------- + +#if defined (HAVE_SINCOS) + +void +gr_sincos (double x, double *sinx, double *cosx) +{ + sincos (x, sinx, cosx); +} + +#else + +void +gr_sincos (double x, double *sinx, double *cosx) +{ + *sinx = sin (x); + *cosx = cos (x); +} + +#endif + +// ---------------------------------------------------------------- + +#if defined (HAVE_SINCOSF) + +void +gr_sincosf (float x, float *sinx, float *cosx) +{ + sincosf (x, sinx, cosx); +} + +#elif defined (HAVE_SINF) && defined (HAVE_COSF) + +void +gr_sincosf (float x, float *sinx, float *cosx) +{ + *sinx = sinf (x); + *cosx = cosf (x); +} + +#else + +void +gr_sincosf (float x, float *sinx, float *cosx) +{ + *sinx = sin (x); + *cosx = cos (x); +} + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_sincos.h b/gnuradio-core/src/lib/filter/gr_sincos.h new file mode 100644 index 00000000..2e8f3ff7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_sincos.h @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINCOS_H +#define INCLUDED_GR_SINCOS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// compute sine and cosine at the same time + +void gr_sincos (double x, double *sin, double *cos); +void gr_sincosf (float x, float *sin, float *cos); + +#ifdef __cplusplus +}; +#endif + +#endif /* INCLUDED_GR_SINCOS_H */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_avg.h b/gnuradio-core/src/lib/filter/gr_single_pole_avg.h new file mode 100644 index 00000000..adf871ae --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_POLE_AVG_H_ +#define _GR_SINGLE_POLE_AVG_H_ + +#include + +/*! + * \brief class template for single pole moving average filter + */ +template +class gr_single_pole_avg { +public: + /*! + * \brief construct new single pole moving average filter with given alpha + * + * computes y(i) = alpha * x(i) - (1-alpha) * y(i-1) + */ + gr_single_pole_avg (tap_type alpha = 1.0) + { + d_prev_input = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (tap_type alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_input = 0; + } + + tap_type prev_input () { return d_prev_input; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gr_single_pole_avg::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input - d_one_minus_alpha * d_prev_input; + d_prev_input = input; + + return (o_type) output; +} + + +template +void +gr_single_pole_avg::filterN (o_type output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + + +#endif /* _GR_SINGLE_POLE_AVG_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc new file mode 100644 index 00000000..99f8b110 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_single_pole_avg_filter_ff_sptr +gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_pole_avg_filter_ff_sptr(new gr_single_pole_avg_filter_ff(alpha, vlen)); +} + +gr_single_pole_avg_filter_ff::gr_single_pole_avg_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_avg_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_avg_filter_ff::~gr_single_pole_avg_filter_ff () +{ + // nop +} + +void +gr_single_pole_avg_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_pole_avg_filter_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h new file mode 100644 index 00000000..cc3640f6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H + +#include +#include +#include + +class gr_single_pole_avg_filter_ff; +typedef boost::shared_ptr gr_single_pole_avg_filter_ff_sptr; + +gr_single_pole_avg_filter_ff_sptr +gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole moving average filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class gr_single_pole_avg_filter_ff : public gr_sync_block +{ + private: + friend gr_single_pole_avg_filter_ff_sptr + gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector > d_rec; + + gr_single_pole_avg_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_avg_filter_ff (); + + void set_taps (double alpha); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.i new file mode 100644 index 00000000..f0ffe6ce --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_pole_avg_filter_ff); + +gr_single_pole_avg_filter_ff_sptr +gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_pole_avg_filter_ff : public gr_sync_block +{ + public: + ~gr_single_pole_avg_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h new file mode 100644 index 00000000..c1d3f748 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h @@ -0,0 +1,190 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_POLE_IIR_H_ +#define _GR_SINGLE_POLE_IIR_H_ + +#include +#include +/*! + * \brief class template for single pole IIR filter + */ +template +class gr_single_pole_iir { +public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) + */ + gr_single_pole_iir (tap_type alpha = 1.0) + { + d_prev_output = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (tap_type alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_output = 0; + } + + tap_type prev_output () { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_output; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gr_single_pole_iir::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (o_type) output; +} + + +template +void +gr_single_pole_iir::filterN (o_type output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + + +// +// Specialized case for gr_complex output and double taps +// We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double) + +template +class gr_single_pole_iir { +public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) + */ + gr_single_pole_iir (double alpha = 1.0) + { + d_prev_output = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + gr_complex filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (gr_complex output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (double alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_output = 0; + } + + gr_complexd prev_output () { return d_prev_output; } + +protected: + double d_alpha; + double d_one_minus_alpha; + gr_complexd d_prev_output; +}; + +template< class i_type> +gr_complex +gr_single_pole_iir::filter (const i_type input) +{ + gr_complexd output; + + output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (gr_complex) output; +} + +//Do we need to specialize this, although it is the same as the general case? + +template +void +gr_single_pole_iir::filterN (gr_complex output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + +#endif /* _GR_SINGLE_POLE_IIR_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc new file mode 100644 index 00000000..0218452c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_single_pole_iir_filter_cc_sptr +gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen) +{ + return gr_single_pole_iir_filter_cc_sptr(new gr_single_pole_iir_filter_cc(alpha, vlen)); +} + +gr_single_pole_iir_filter_cc::gr_single_pole_iir_filter_cc ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_iir_filter_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen)), + d_vlen(vlen), d_iir(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_iir_filter_cc::~gr_single_pole_iir_filter_cc () +{ + // nop +} + +void +gr_single_pole_iir_filter_cc::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_iir[i].set_taps(alpha); +} + +int +gr_single_pole_iir_filter_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]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_iir[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_iir[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h new file mode 100644 index 00000000..38caa614 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_IIR_FILTER_CC_H +#define INCLUDED_GR_SINGLE_POLE_IIR_FILTER_CC_H + +#include +#include +#include +#include + +class gr_single_pole_iir_filter_cc; +typedef boost::shared_ptr gr_single_pole_iir_filter_cc_sptr; + +gr_single_pole_iir_filter_cc_sptr +gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole IIR filter with complex input, complex output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class gr_single_pole_iir_filter_cc : public gr_sync_block +{ + private: + friend gr_single_pole_iir_filter_cc_sptr + gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector > d_iir; + + gr_single_pole_iir_filter_cc (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_iir_filter_cc (); + + void set_taps (double alpha); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.i b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.i new file mode 100644 index 00000000..683bbe99 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_pole_iir_filter_cc); + +gr_single_pole_iir_filter_cc_sptr +gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen=1); + +class gr_single_pole_iir_filter_cc : public gr_sync_block +{ + public: + ~gr_single_pole_iir_filter_cc (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc new file mode 100644 index 00000000..03e27484 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_single_pole_iir_filter_ff_sptr +gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_pole_iir_filter_ff_sptr(new gr_single_pole_iir_filter_ff(alpha, vlen)); +} + +gr_single_pole_iir_filter_ff::gr_single_pole_iir_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_iir_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_iir(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_iir_filter_ff::~gr_single_pole_iir_filter_ff () +{ + // nop +} + +void +gr_single_pole_iir_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_iir[i].set_taps(alpha); +} + +int +gr_single_pole_iir_filter_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_iir[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_iir[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h new file mode 100644 index 00000000..ff6bae3b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_IIR_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_IIR_FILTER_FF_H + +#include +#include +#include + +class gr_single_pole_iir_filter_ff; +typedef boost::shared_ptr gr_single_pole_iir_filter_ff_sptr; + +gr_single_pole_iir_filter_ff_sptr +gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole IIR filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class gr_single_pole_iir_filter_ff : public gr_sync_block +{ + private: + friend gr_single_pole_iir_filter_ff_sptr + gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector > d_iir; + + gr_single_pole_iir_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_iir_filter_ff (); + + void set_taps (double alpha); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.i new file mode 100644 index 00000000..6680c84e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_pole_iir_filter_ff); + +gr_single_pole_iir_filter_ff_sptr +gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_pole_iir_filter_ff : public gr_sync_block +{ + public: + ~gr_single_pole_iir_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_rec.h b/gnuradio-core/src/lib/filter/gr_single_pole_rec.h new file mode 100644 index 00000000..f443678d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_POLE_REC_H_ +#define _GR_SINGLE_POLE_REC_H_ + +#include + +/*! + * \brief class template for single pole recursive filter + */ +template +class gr_single_pole_rec { +public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = alpha * x(i) - (1-alpha) * y(i-1) + */ + gr_single_pole_rec (tap_type alpha = 1.0) + { + d_prev_output = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (tap_type alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to pole + void reset () + { + d_prev_output = 0; + } + + tap_type prev_output () { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_output; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gr_single_pole_rec::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (o_type) output; +} + + +template +void +gr_single_pole_rec::filterN (o_type output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + + +#endif /* _GR_SINGLE_POLE_REC_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc new file mode 100644 index 00000000..7c0a9aa9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_single_pole_rec_filter_ff_sptr +gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_pole_rec_filter_ff_sptr(new gr_single_pole_rec_filter_ff(alpha, vlen)); +} + +gr_single_pole_rec_filter_ff::gr_single_pole_rec_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_rec_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_rec_filter_ff::~gr_single_pole_rec_filter_ff () +{ + // nop +} + +void +gr_single_pole_rec_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_pole_rec_filter_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h new file mode 100644 index 00000000..d1861e75 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H + +#include +#include +#include + +class gr_single_pole_rec_filter_ff; +typedef boost::shared_ptr gr_single_pole_rec_filter_ff_sptr; + +gr_single_pole_rec_filter_ff_sptr +gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole recursive filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class gr_single_pole_rec_filter_ff : public gr_sync_block +{ + private: + friend gr_single_pole_rec_filter_ff_sptr + gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector > d_rec; + + gr_single_pole_rec_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_rec_filter_ff (); + + void set_taps (double alpha); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.i new file mode 100644 index 00000000..06da737b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_pole_rec_filter_ff); + +gr_single_pole_rec_filter_ff_sptr +gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_pole_rec_filter_ff : public gr_sync_block +{ + public: + ~gr_single_pole_rec_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg.h b/gnuradio-core/src/lib/filter/gr_single_zero_avg.h new file mode 100644 index 00000000..def340a0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_ZERO_AVG_H_ +#define _GR_SINGLE_ZERO_AVG_H_ + +#include + +/*! + * \brief class template for single zero moving average filter + */ +template +class gr_single_zero_avg { +public: + /*! + * \brief construct new single zero moving average filter with given alpha + * + * computes y(i) = alpha * x(i) + (1-alpha) * y(i-1) + */ + gr_single_zero_avg (tap_type alpha = 1.0) + { + d_prev_input = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (tap_type alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_input = 0; + } + + tap_type prev_input () { return d_prev_input; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gr_single_zero_avg::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input + d_one_minus_alpha * d_prev_input; + d_prev_input = input; + + return (o_type) output; +} + + +template +void +gr_single_zero_avg::filterN (o_type output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + + +#endif /* _GR_SINGLE_ZERO_AVG_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc new file mode 100644 index 00000000..62feb4ca --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_single_zero_avg_filter_ff_sptr +gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_zero_avg_filter_ff_sptr(new gr_single_zero_avg_filter_ff(alpha, vlen)); +} + +gr_single_zero_avg_filter_ff::gr_single_zero_avg_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_zero_avg_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_zero_avg_filter_ff::~gr_single_zero_avg_filter_ff () +{ + // nop +} + +void +gr_single_zero_avg_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_zero_avg_filter_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h new file mode 100644 index 00000000..4a283d3c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_ZERO_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_ZERO_REC_FILTER_FF_H + +#include +#include +#include + +class gr_single_zero_avg_filter_ff; +typedef boost::shared_ptr gr_single_zero_avg_filter_ff_sptr; + +gr_single_zero_avg_filter_ff_sptr +gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single zero moving average filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class gr_single_zero_avg_filter_ff : public gr_sync_block +{ + private: + friend gr_single_zero_avg_filter_ff_sptr + gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector > d_rec; + + gr_single_zero_avg_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_zero_avg_filter_ff (); + + void set_taps (double alpha); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.i new file mode 100644 index 00000000..0e6d84fa --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_zero_avg_filter_ff); + +gr_single_zero_avg_filter_ff_sptr +gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_zero_avg_filter_ff : public gr_sync_block +{ + public: + ~gr_single_zero_avg_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec.h b/gnuradio-core/src/lib/filter/gr_single_zero_rec.h new file mode 100644 index 00000000..f91640c5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_ZERO_REC_H_ +#define _GR_SINGLE_ZERO_REC_H_ + +#include + +/*! + * \brief class template for single zero recursive filter + */ +template +class gr_single_zero_rec { +public: + /*! + * \brief construct new single zero IIR with given alpha + * + * computes y(i) = alpha * x(i) - (1-alpha) * y(i-1) + */ + gr_single_zero_rec (tap_type alpha = 1.0) + { + d_prev_output = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (tap_type alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_output = 0; + } + + tap_type prev_output () { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_output; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gr_single_zero_rec::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input - d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (o_type) output; +} + + +template +void +gr_single_zero_rec::filterN (o_type output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + + +#endif /* _GR_SINGLE_ZERO_REC_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc new file mode 100644 index 00000000..fe704f45 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_single_zero_rec_filter_ff_sptr +gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_zero_rec_filter_ff_sptr(new gr_single_zero_rec_filter_ff(alpha, vlen)); +} + +gr_single_zero_rec_filter_ff::gr_single_zero_rec_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_zero_rec_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_zero_rec_filter_ff::~gr_single_zero_rec_filter_ff () +{ + // nop +} + +void +gr_single_zero_rec_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_zero_rec_filter_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h new file mode 100644 index 00000000..98215e90 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H + +#include +#include +#include + +class gr_single_zero_rec_filter_ff; +typedef boost::shared_ptr gr_single_zero_rec_filter_ff_sptr; + +gr_single_zero_rec_filter_ff_sptr +gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single zero recursive filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = -alpha x[n] + \f] + + * with the corresponding system function + + \f[ + H(z) = {alpha - (1-alpha) z^{-1}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class gr_single_zero_rec_filter_ff : public gr_sync_block +{ + private: + friend gr_single_zero_rec_filter_ff_sptr + gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector > d_rec; + + gr_single_zero_rec_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_zero_rec_filter_ff (); + + void set_taps (double alpha); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.i new file mode 100644 index 00000000..e2cbbfc9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_zero_rec_filter_ff); + +gr_single_zero_rec_filter_ff_sptr +gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_zero_rec_filter_ff : public gr_sync_block +{ + public: + ~gr_single_zero_rec_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gri_goertzel.cc b/gnuradio-core/src/lib/filter/gri_goertzel.cc new file mode 100644 index 00000000..571de616 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_goertzel.cc @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include + +gri_goertzel::gri_goertzel(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 gri_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 gri_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 gri_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; +} diff --git a/gnuradio-core/src/lib/filter/gri_goertzel.h b/gnuradio-core/src/lib/filter/gri_goertzel.h new file mode 100644 index 00000000..6baf94e9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_goertzel.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_GOERTZEL_H +#define INCLUDED_GRI_GOERTZEL_H + +#include + +/*! + * \brief implements Goertzel single-bin DFT calculation + */ + +class gri_goertzel +{ +public: + gri_goertzel() {} + gri_goertzel(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; +}; + +#endif /* INCLUDED_GRI_GOERTZEL_H */ diff --git a/gnuradio-core/src/lib/filter/gri_iir.h b/gnuradio-core/src/lib/filter/gri_iir.h new file mode 100644 index 00000000..7de8c69a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_iir.h @@ -0,0 +1,164 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_IIR_H +#define INCLUDED_GRI_IIR_H + +#include +#include + +/*! + * \brief base class template for Infinite Impulse Response filter (IIR) + */ +template +class gri_iir { +public: + /*! + * \brief Construct an IIR with the given taps. + * + * This filter uses the Direct Form I implementation, where + * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones. + * + * \p fftaps and \p fbtaps must have equal numbers of taps + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - \sum_{k=1}^{N} a_k y[n-k] = \sum_{k=0}^{M} b_k x[n-k] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback taps. + */ + gri_iir (const std::vector& fftaps, + const std::vector& fbtaps) throw (std::invalid_argument) + { + set_taps (fftaps, fbtaps); + } + + gri_iir () : d_latest(0) { } + + ~gri_iir () {} + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have N valid entries. + */ + void filter_n (o_type output[], const i_type input[], long n); + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_fftaps.size (); } + + /*! + * \brief install new taps. + */ + void set_taps (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument) + { + if (fftaps.size () != fbtaps.size ()) + throw std::invalid_argument ("gri_iir::set_taps"); + + d_latest = 0; + d_fftaps = fftaps; + d_fbtaps = fbtaps; + + int n = fftaps.size (); + d_prev_input.resize (2 * n); + d_prev_output.resize (2 * n); + + for (int i = 0; i < 2 * n; i++){ + d_prev_input[i] = 0; + d_prev_output[i] = 0; + } + } + +protected: + std::vector d_fftaps; + std::vector d_fbtaps; + int d_latest; + std::vector d_prev_output; + std::vector d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gri_iir::filter (const i_type input) +{ + tap_type acc; + unsigned i = 0; + unsigned n = ntaps (); + + if (n == 0) + return (o_type) 0; + + int latest = d_latest; + + acc = d_fftaps[0] * input; + for (i = 1; i < n; i ++) + acc += (d_fftaps[i] * d_prev_input[latest + i] + + d_fbtaps[i] * d_prev_output[latest + i]); + + // store the values twice to avoid having to handle wrap-around in the loop + d_prev_output[latest] = acc; + d_prev_output[latest+n] = acc; + d_prev_input[latest] = input; + d_prev_input[latest+n] = input; + + latest--; + if (latest < 0) + latest += n; + + d_latest = latest; + return (o_type) acc; +} + + +template +void +gri_iir::filter_n (o_type output[], + const i_type input[], + long n) +{ + for (int i = 0; i < n; i++) + output[i] = filter (input[i]); +} + +#endif /* INCLUDED_GRI_IIR_H */ + diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc new file mode 100644 index 00000000..ff7eca89 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include "interpolator_taps.h" + +gri_mmse_fir_interpolator::gri_mmse_fir_interpolator () +{ + filters.resize (NSTEPS + 1); + + for (int i = 0; i < NSTEPS + 1; i++){ + std::vector t (&taps[i][0], &taps[i][NTAPS]); + filters[i] = gr_fir_util::create_gr_fir_fff (t); + } +} + +gri_mmse_fir_interpolator::~gri_mmse_fir_interpolator () +{ + for (int i = 0; i < NSTEPS + 1; i++) + delete filters[i]; +} + +unsigned +gri_mmse_fir_interpolator::ntaps () const +{ + return NTAPS; +} + +unsigned +gri_mmse_fir_interpolator::nsteps () const +{ + return NSTEPS; +} + +float +gri_mmse_fir_interpolator::interpolate (const float input[], float mu) const +{ + int imu = (int) rint (mu * NSTEPS); + + assert (imu >= 0); + assert (imu <= NSTEPS); + + float r = filters[imu]->filter (input); + return r; +} diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h new file mode 100644 index 00000000..e2fb8f79 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRI_MMSE_FIR_INTERPOLATOR_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_H_ + +#include + +class gr_fir_fff; + +/*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * + * This implements a Mininum Mean Squared Error interpolator with 8 taps. + * It is suitable for signals where the bandwidth of interest B = 1/(4*Ts) + * Where Ts is the time between samples. + * + * Although mu, the fractional delay, is specified as a float, it is actually + * quantized. 0.0 <= mu <= 1.0. That is, mu is quantized in the interpolate + * method to 32nd's of a sample. + */ + +class gri_mmse_fir_interpolator { +public: + gri_mmse_fir_interpolator (); + ~gri_mmse_fir_interpolator (); + + unsigned ntaps () const; + unsigned nsteps () const; + + /*! + * \brief compute a single interpolated output value. + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \p mu must be in the range [0, 1] and specifies the fractional delay. + * + * \returns the interpolated input value. + */ + float interpolate (const float input[], float mu) const; + +protected: + std::vector filters; +}; + + +#endif /* _GRI_MMSE_FIR_INTERPOLATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc new file mode 100644 index 00000000..3f75aedc --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include "interpolator_taps.h" + +gri_mmse_fir_interpolator_cc::gri_mmse_fir_interpolator_cc () +{ + filters.resize (NSTEPS + 1); + + for (int i = 0; i < NSTEPS + 1; i++){ + std::vector t (&taps[i][0], &taps[i][NTAPS]); + filters[i] = gr_fir_util::create_gr_fir_ccf (t); + } +} + +gri_mmse_fir_interpolator_cc::~gri_mmse_fir_interpolator_cc () +{ + for (int i = 0; i < NSTEPS + 1; i++) + delete filters[i]; +} + +unsigned +gri_mmse_fir_interpolator_cc::ntaps () const +{ + return NTAPS; +} + +unsigned +gri_mmse_fir_interpolator_cc::nsteps () const +{ + return NSTEPS; +} + +gr_complex +gri_mmse_fir_interpolator_cc::interpolate (const gr_complex input[], float mu) +{ + int imu = (int) rint (mu * NSTEPS); + + assert (imu >= 0); + assert (imu <= NSTEPS); + + gr_complex r = filters[imu]->filter (input); + return r; +} diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h new file mode 100644 index 00000000..d0c14117 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ + +#include +#include + +class gr_fir_ccf; + +/*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * + * This implements a Mininum Mean Squared Error interpolator with 8 taps. + * It is suitable for signals where the bandwidth of interest B = 1/(4*Ts) + * Where Ts is the time between samples. + * + * Although mu, the fractional delay, is specified as a float, it is actually + * quantized. 0.0 <= mu <= 1.0. That is, mu is quantized in the interpolate + * method to 32nd's of a sample. + */ + +class gri_mmse_fir_interpolator_cc { +public: + gri_mmse_fir_interpolator_cc (); + ~gri_mmse_fir_interpolator_cc (); + + unsigned ntaps () const; + unsigned nsteps () const; + + /*! + * \brief compute a single interpolated output value. + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \p mu must be in the range [0, 1] and specifies the fractional delay. + * + * \returns the interpolated input value. + */ + gr_complex interpolate (const gr_complex input[], float mu); + +protected: + std::vector filters; +}; + + +#endif /* _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ */ diff --git a/gnuradio-core/src/lib/filter/interpolator_taps.h b/gnuradio-core/src/lib/filter/interpolator_taps.h new file mode 100644 index 00000000..76702b63 --- /dev/null +++ b/gnuradio-core/src/lib/filter/interpolator_taps.h @@ -0,0 +1,141 @@ +/* + * This file was machine generated by gen_interpolator_taps. + * DO NOT EDIT BY HAND. + */ + +static const int NTAPS = 8; +static const int NSTEPS = 128; + +static const float taps[NSTEPS+1][NTAPS] = { + // -4 -3 -2 -1 0 1 2 3 mu + { 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 0/128 + { -1.54700e-04, 8.53777e-04, -2.76968e-03, 7.89295e-03, 9.98534e-01, -5.41054e-03, 1.24642e-03, -1.98993e-04 }, // 1/128 + { -3.09412e-04, 1.70888e-03, -5.55134e-03, 1.58840e-02, 9.96891e-01, -1.07209e-02, 2.47942e-03, -3.96391e-04 }, // 2/128 + { -4.64053e-04, 2.56486e-03, -8.34364e-03, 2.39714e-02, 9.95074e-01, -1.59305e-02, 3.69852e-03, -5.92100e-04 }, // 3/128 + { -6.18544e-04, 3.42130e-03, -1.11453e-02, 3.21531e-02, 9.93082e-01, -2.10389e-02, 4.90322e-03, -7.86031e-04 }, // 4/128 + { -7.72802e-04, 4.27773e-03, -1.39548e-02, 4.04274e-02, 9.90917e-01, -2.60456e-02, 6.09305e-03, -9.78093e-04 }, // 5/128 + { -9.26747e-04, 5.13372e-03, -1.67710e-02, 4.87921e-02, 9.88580e-01, -3.09503e-02, 7.26755e-03, -1.16820e-03 }, // 6/128 + { -1.08030e-03, 5.98883e-03, -1.95925e-02, 5.72454e-02, 9.86071e-01, -3.57525e-02, 8.42626e-03, -1.35627e-03 }, // 7/128 + { -1.23337e-03, 6.84261e-03, -2.24178e-02, 6.57852e-02, 9.83392e-01, -4.04519e-02, 9.56876e-03, -1.54221e-03 }, // 8/128 + { -1.38589e-03, 7.69462e-03, -2.52457e-02, 7.44095e-02, 9.80543e-01, -4.50483e-02, 1.06946e-02, -1.72594e-03 }, // 9/128 + { -1.53777e-03, 8.54441e-03, -2.80746e-02, 8.31162e-02, 9.77526e-01, -4.95412e-02, 1.18034e-02, -1.90738e-03 }, // 10/128 + { -1.68894e-03, 9.39154e-03, -3.09033e-02, 9.19033e-02, 9.74342e-01, -5.39305e-02, 1.28947e-02, -2.08645e-03 }, // 11/128 + { -1.83931e-03, 1.02356e-02, -3.37303e-02, 1.00769e-01, 9.70992e-01, -5.82159e-02, 1.39681e-02, -2.26307e-03 }, // 12/128 + { -1.98880e-03, 1.10760e-02, -3.65541e-02, 1.09710e-01, 9.67477e-01, -6.23972e-02, 1.50233e-02, -2.43718e-03 }, // 13/128 + { -2.13733e-03, 1.19125e-02, -3.93735e-02, 1.18725e-01, 9.63798e-01, -6.64743e-02, 1.60599e-02, -2.60868e-03 }, // 14/128 + { -2.28483e-03, 1.27445e-02, -4.21869e-02, 1.27812e-01, 9.59958e-01, -7.04471e-02, 1.70776e-02, -2.77751e-03 }, // 15/128 + { -2.43121e-03, 1.35716e-02, -4.49929e-02, 1.36968e-01, 9.55956e-01, -7.43154e-02, 1.80759e-02, -2.94361e-03 }, // 16/128 + { -2.57640e-03, 1.43934e-02, -4.77900e-02, 1.46192e-01, 9.51795e-01, -7.80792e-02, 1.90545e-02, -3.10689e-03 }, // 17/128 + { -2.72032e-03, 1.52095e-02, -5.05770e-02, 1.55480e-01, 9.47477e-01, -8.17385e-02, 2.00132e-02, -3.26730e-03 }, // 18/128 + { -2.86289e-03, 1.60193e-02, -5.33522e-02, 1.64831e-01, 9.43001e-01, -8.52933e-02, 2.09516e-02, -3.42477e-03 }, // 19/128 + { -3.00403e-03, 1.68225e-02, -5.61142e-02, 1.74242e-01, 9.38371e-01, -8.87435e-02, 2.18695e-02, -3.57923e-03 }, // 20/128 + { -3.14367e-03, 1.76185e-02, -5.88617e-02, 1.83711e-01, 9.33586e-01, -9.20893e-02, 2.27664e-02, -3.73062e-03 }, // 21/128 + { -3.28174e-03, 1.84071e-02, -6.15931e-02, 1.93236e-01, 9.28650e-01, -9.53307e-02, 2.36423e-02, -3.87888e-03 }, // 22/128 + { -3.41815e-03, 1.91877e-02, -6.43069e-02, 2.02814e-01, 9.23564e-01, -9.84679e-02, 2.44967e-02, -4.02397e-03 }, // 23/128 + { -3.55283e-03, 1.99599e-02, -6.70018e-02, 2.12443e-01, 9.18329e-01, -1.01501e-01, 2.53295e-02, -4.16581e-03 }, // 24/128 + { -3.68570e-03, 2.07233e-02, -6.96762e-02, 2.22120e-01, 9.12947e-01, -1.04430e-01, 2.61404e-02, -4.30435e-03 }, // 25/128 + { -3.81671e-03, 2.14774e-02, -7.23286e-02, 2.31843e-01, 9.07420e-01, -1.07256e-01, 2.69293e-02, -4.43955e-03 }, // 26/128 + { -3.94576e-03, 2.22218e-02, -7.49577e-02, 2.41609e-01, 9.01749e-01, -1.09978e-01, 2.76957e-02, -4.57135e-03 }, // 27/128 + { -4.07279e-03, 2.29562e-02, -7.75620e-02, 2.51417e-01, 8.95936e-01, -1.12597e-01, 2.84397e-02, -4.69970e-03 }, // 28/128 + { -4.19774e-03, 2.36801e-02, -8.01399e-02, 2.61263e-01, 8.89984e-01, -1.15113e-01, 2.91609e-02, -4.82456e-03 }, // 29/128 + { -4.32052e-03, 2.43930e-02, -8.26900e-02, 2.71144e-01, 8.83893e-01, -1.17526e-01, 2.98593e-02, -4.94589e-03 }, // 30/128 + { -4.44107e-03, 2.50946e-02, -8.52109e-02, 2.81060e-01, 8.77666e-01, -1.19837e-01, 3.05345e-02, -5.06363e-03 }, // 31/128 + { -4.55932e-03, 2.57844e-02, -8.77011e-02, 2.91006e-01, 8.71305e-01, -1.22047e-01, 3.11866e-02, -5.17776e-03 }, // 32/128 + { -4.67520e-03, 2.64621e-02, -9.01591e-02, 3.00980e-01, 8.64812e-01, -1.24154e-01, 3.18153e-02, -5.28823e-03 }, // 33/128 + { -4.78866e-03, 2.71272e-02, -9.25834e-02, 3.10980e-01, 8.58189e-01, -1.26161e-01, 3.24205e-02, -5.39500e-03 }, // 34/128 + { -4.89961e-03, 2.77794e-02, -9.49727e-02, 3.21004e-01, 8.51437e-01, -1.28068e-01, 3.30021e-02, -5.49804e-03 }, // 35/128 + { -5.00800e-03, 2.84182e-02, -9.73254e-02, 3.31048e-01, 8.44559e-01, -1.29874e-01, 3.35600e-02, -5.59731e-03 }, // 36/128 + { -5.11376e-03, 2.90433e-02, -9.96402e-02, 3.41109e-01, 8.37557e-01, -1.31581e-01, 3.40940e-02, -5.69280e-03 }, // 37/128 + { -5.21683e-03, 2.96543e-02, -1.01915e-01, 3.51186e-01, 8.30432e-01, -1.33189e-01, 3.46042e-02, -5.78446e-03 }, // 38/128 + { -5.31716e-03, 3.02507e-02, -1.04150e-01, 3.61276e-01, 8.23188e-01, -1.34699e-01, 3.50903e-02, -5.87227e-03 }, // 39/128 + { -5.41467e-03, 3.08323e-02, -1.06342e-01, 3.71376e-01, 8.15826e-01, -1.36111e-01, 3.55525e-02, -5.95620e-03 }, // 40/128 + { -5.50931e-03, 3.13987e-02, -1.08490e-01, 3.81484e-01, 8.08348e-01, -1.37426e-01, 3.59905e-02, -6.03624e-03 }, // 41/128 + { -5.60103e-03, 3.19495e-02, -1.10593e-01, 3.91596e-01, 8.00757e-01, -1.38644e-01, 3.64044e-02, -6.11236e-03 }, // 42/128 + { -5.68976e-03, 3.24843e-02, -1.12650e-01, 4.01710e-01, 7.93055e-01, -1.39767e-01, 3.67941e-02, -6.18454e-03 }, // 43/128 + { -5.77544e-03, 3.30027e-02, -1.14659e-01, 4.11823e-01, 7.85244e-01, -1.40794e-01, 3.71596e-02, -6.25277e-03 }, // 44/128 + { -5.85804e-03, 3.35046e-02, -1.16618e-01, 4.21934e-01, 7.77327e-01, -1.41727e-01, 3.75010e-02, -6.31703e-03 }, // 45/128 + { -5.93749e-03, 3.39894e-02, -1.18526e-01, 4.32038e-01, 7.69305e-01, -1.42566e-01, 3.78182e-02, -6.37730e-03 }, // 46/128 + { -6.01374e-03, 3.44568e-02, -1.20382e-01, 4.42134e-01, 7.61181e-01, -1.43313e-01, 3.81111e-02, -6.43358e-03 }, // 47/128 + { -6.08674e-03, 3.49066e-02, -1.22185e-01, 4.52218e-01, 7.52958e-01, -1.43968e-01, 3.83800e-02, -6.48585e-03 }, // 48/128 + { -6.15644e-03, 3.53384e-02, -1.23933e-01, 4.62289e-01, 7.44637e-01, -1.44531e-01, 3.86247e-02, -6.53412e-03 }, // 49/128 + { -6.22280e-03, 3.57519e-02, -1.25624e-01, 4.72342e-01, 7.36222e-01, -1.45004e-01, 3.88454e-02, -6.57836e-03 }, // 50/128 + { -6.28577e-03, 3.61468e-02, -1.27258e-01, 4.82377e-01, 7.27714e-01, -1.45387e-01, 3.90420e-02, -6.61859e-03 }, // 51/128 + { -6.34530e-03, 3.65227e-02, -1.28832e-01, 4.92389e-01, 7.19116e-01, -1.45682e-01, 3.92147e-02, -6.65479e-03 }, // 52/128 + { -6.40135e-03, 3.68795e-02, -1.30347e-01, 5.02377e-01, 7.10431e-01, -1.45889e-01, 3.93636e-02, -6.68698e-03 }, // 53/128 + { -6.45388e-03, 3.72167e-02, -1.31800e-01, 5.12337e-01, 7.01661e-01, -1.46009e-01, 3.94886e-02, -6.71514e-03 }, // 54/128 + { -6.50285e-03, 3.75341e-02, -1.33190e-01, 5.22267e-01, 6.92808e-01, -1.46043e-01, 3.95900e-02, -6.73929e-03 }, // 55/128 + { -6.54823e-03, 3.78315e-02, -1.34515e-01, 5.32164e-01, 6.83875e-01, -1.45993e-01, 3.96678e-02, -6.75943e-03 }, // 56/128 + { -6.58996e-03, 3.81085e-02, -1.35775e-01, 5.42025e-01, 6.74865e-01, -1.45859e-01, 3.97222e-02, -6.77557e-03 }, // 57/128 + { -6.62802e-03, 3.83650e-02, -1.36969e-01, 5.51849e-01, 6.65779e-01, -1.45641e-01, 3.97532e-02, -6.78771e-03 }, // 58/128 + { -6.66238e-03, 3.86006e-02, -1.38094e-01, 5.61631e-01, 6.56621e-01, -1.45343e-01, 3.97610e-02, -6.79588e-03 }, // 59/128 + { -6.69300e-03, 3.88151e-02, -1.39150e-01, 5.71370e-01, 6.47394e-01, -1.44963e-01, 3.97458e-02, -6.80007e-03 }, // 60/128 + { -6.71985e-03, 3.90083e-02, -1.40136e-01, 5.81063e-01, 6.38099e-01, -1.44503e-01, 3.97077e-02, -6.80032e-03 }, // 61/128 + { -6.74291e-03, 3.91800e-02, -1.41050e-01, 5.90706e-01, 6.28739e-01, -1.43965e-01, 3.96469e-02, -6.79662e-03 }, // 62/128 + { -6.76214e-03, 3.93299e-02, -1.41891e-01, 6.00298e-01, 6.19318e-01, -1.43350e-01, 3.95635e-02, -6.78902e-03 }, // 63/128 + { -6.77751e-03, 3.94578e-02, -1.42658e-01, 6.09836e-01, 6.09836e-01, -1.42658e-01, 3.94578e-02, -6.77751e-03 }, // 64/128 + { -6.78902e-03, 3.95635e-02, -1.43350e-01, 6.19318e-01, 6.00298e-01, -1.41891e-01, 3.93299e-02, -6.76214e-03 }, // 65/128 + { -6.79662e-03, 3.96469e-02, -1.43965e-01, 6.28739e-01, 5.90706e-01, -1.41050e-01, 3.91800e-02, -6.74291e-03 }, // 66/128 + { -6.80032e-03, 3.97077e-02, -1.44503e-01, 6.38099e-01, 5.81063e-01, -1.40136e-01, 3.90083e-02, -6.71985e-03 }, // 67/128 + { -6.80007e-03, 3.97458e-02, -1.44963e-01, 6.47394e-01, 5.71370e-01, -1.39150e-01, 3.88151e-02, -6.69300e-03 }, // 68/128 + { -6.79588e-03, 3.97610e-02, -1.45343e-01, 6.56621e-01, 5.61631e-01, -1.38094e-01, 3.86006e-02, -6.66238e-03 }, // 69/128 + { -6.78771e-03, 3.97532e-02, -1.45641e-01, 6.65779e-01, 5.51849e-01, -1.36969e-01, 3.83650e-02, -6.62802e-03 }, // 70/128 + { -6.77557e-03, 3.97222e-02, -1.45859e-01, 6.74865e-01, 5.42025e-01, -1.35775e-01, 3.81085e-02, -6.58996e-03 }, // 71/128 + { -6.75943e-03, 3.96678e-02, -1.45993e-01, 6.83875e-01, 5.32164e-01, -1.34515e-01, 3.78315e-02, -6.54823e-03 }, // 72/128 + { -6.73929e-03, 3.95900e-02, -1.46043e-01, 6.92808e-01, 5.22267e-01, -1.33190e-01, 3.75341e-02, -6.50285e-03 }, // 73/128 + { -6.71514e-03, 3.94886e-02, -1.46009e-01, 7.01661e-01, 5.12337e-01, -1.31800e-01, 3.72167e-02, -6.45388e-03 }, // 74/128 + { -6.68698e-03, 3.93636e-02, -1.45889e-01, 7.10431e-01, 5.02377e-01, -1.30347e-01, 3.68795e-02, -6.40135e-03 }, // 75/128 + { -6.65479e-03, 3.92147e-02, -1.45682e-01, 7.19116e-01, 4.92389e-01, -1.28832e-01, 3.65227e-02, -6.34530e-03 }, // 76/128 + { -6.61859e-03, 3.90420e-02, -1.45387e-01, 7.27714e-01, 4.82377e-01, -1.27258e-01, 3.61468e-02, -6.28577e-03 }, // 77/128 + { -6.57836e-03, 3.88454e-02, -1.45004e-01, 7.36222e-01, 4.72342e-01, -1.25624e-01, 3.57519e-02, -6.22280e-03 }, // 78/128 + { -6.53412e-03, 3.86247e-02, -1.44531e-01, 7.44637e-01, 4.62289e-01, -1.23933e-01, 3.53384e-02, -6.15644e-03 }, // 79/128 + { -6.48585e-03, 3.83800e-02, -1.43968e-01, 7.52958e-01, 4.52218e-01, -1.22185e-01, 3.49066e-02, -6.08674e-03 }, // 80/128 + { -6.43358e-03, 3.81111e-02, -1.43313e-01, 7.61181e-01, 4.42134e-01, -1.20382e-01, 3.44568e-02, -6.01374e-03 }, // 81/128 + { -6.37730e-03, 3.78182e-02, -1.42566e-01, 7.69305e-01, 4.32038e-01, -1.18526e-01, 3.39894e-02, -5.93749e-03 }, // 82/128 + { -6.31703e-03, 3.75010e-02, -1.41727e-01, 7.77327e-01, 4.21934e-01, -1.16618e-01, 3.35046e-02, -5.85804e-03 }, // 83/128 + { -6.25277e-03, 3.71596e-02, -1.40794e-01, 7.85244e-01, 4.11823e-01, -1.14659e-01, 3.30027e-02, -5.77544e-03 }, // 84/128 + { -6.18454e-03, 3.67941e-02, -1.39767e-01, 7.93055e-01, 4.01710e-01, -1.12650e-01, 3.24843e-02, -5.68976e-03 }, // 85/128 + { -6.11236e-03, 3.64044e-02, -1.38644e-01, 8.00757e-01, 3.91596e-01, -1.10593e-01, 3.19495e-02, -5.60103e-03 }, // 86/128 + { -6.03624e-03, 3.59905e-02, -1.37426e-01, 8.08348e-01, 3.81484e-01, -1.08490e-01, 3.13987e-02, -5.50931e-03 }, // 87/128 + { -5.95620e-03, 3.55525e-02, -1.36111e-01, 8.15826e-01, 3.71376e-01, -1.06342e-01, 3.08323e-02, -5.41467e-03 }, // 88/128 + { -5.87227e-03, 3.50903e-02, -1.34699e-01, 8.23188e-01, 3.61276e-01, -1.04150e-01, 3.02507e-02, -5.31716e-03 }, // 89/128 + { -5.78446e-03, 3.46042e-02, -1.33189e-01, 8.30432e-01, 3.51186e-01, -1.01915e-01, 2.96543e-02, -5.21683e-03 }, // 90/128 + { -5.69280e-03, 3.40940e-02, -1.31581e-01, 8.37557e-01, 3.41109e-01, -9.96402e-02, 2.90433e-02, -5.11376e-03 }, // 91/128 + { -5.59731e-03, 3.35600e-02, -1.29874e-01, 8.44559e-01, 3.31048e-01, -9.73254e-02, 2.84182e-02, -5.00800e-03 }, // 92/128 + { -5.49804e-03, 3.30021e-02, -1.28068e-01, 8.51437e-01, 3.21004e-01, -9.49727e-02, 2.77794e-02, -4.89961e-03 }, // 93/128 + { -5.39500e-03, 3.24205e-02, -1.26161e-01, 8.58189e-01, 3.10980e-01, -9.25834e-02, 2.71272e-02, -4.78866e-03 }, // 94/128 + { -5.28823e-03, 3.18153e-02, -1.24154e-01, 8.64812e-01, 3.00980e-01, -9.01591e-02, 2.64621e-02, -4.67520e-03 }, // 95/128 + { -5.17776e-03, 3.11866e-02, -1.22047e-01, 8.71305e-01, 2.91006e-01, -8.77011e-02, 2.57844e-02, -4.55932e-03 }, // 96/128 + { -5.06363e-03, 3.05345e-02, -1.19837e-01, 8.77666e-01, 2.81060e-01, -8.52109e-02, 2.50946e-02, -4.44107e-03 }, // 97/128 + { -4.94589e-03, 2.98593e-02, -1.17526e-01, 8.83893e-01, 2.71144e-01, -8.26900e-02, 2.43930e-02, -4.32052e-03 }, // 98/128 + { -4.82456e-03, 2.91609e-02, -1.15113e-01, 8.89984e-01, 2.61263e-01, -8.01399e-02, 2.36801e-02, -4.19774e-03 }, // 99/128 + { -4.69970e-03, 2.84397e-02, -1.12597e-01, 8.95936e-01, 2.51417e-01, -7.75620e-02, 2.29562e-02, -4.07279e-03 }, // 100/128 + { -4.57135e-03, 2.76957e-02, -1.09978e-01, 9.01749e-01, 2.41609e-01, -7.49577e-02, 2.22218e-02, -3.94576e-03 }, // 101/128 + { -4.43955e-03, 2.69293e-02, -1.07256e-01, 9.07420e-01, 2.31843e-01, -7.23286e-02, 2.14774e-02, -3.81671e-03 }, // 102/128 + { -4.30435e-03, 2.61404e-02, -1.04430e-01, 9.12947e-01, 2.22120e-01, -6.96762e-02, 2.07233e-02, -3.68570e-03 }, // 103/128 + { -4.16581e-03, 2.53295e-02, -1.01501e-01, 9.18329e-01, 2.12443e-01, -6.70018e-02, 1.99599e-02, -3.55283e-03 }, // 104/128 + { -4.02397e-03, 2.44967e-02, -9.84679e-02, 9.23564e-01, 2.02814e-01, -6.43069e-02, 1.91877e-02, -3.41815e-03 }, // 105/128 + { -3.87888e-03, 2.36423e-02, -9.53307e-02, 9.28650e-01, 1.93236e-01, -6.15931e-02, 1.84071e-02, -3.28174e-03 }, // 106/128 + { -3.73062e-03, 2.27664e-02, -9.20893e-02, 9.33586e-01, 1.83711e-01, -5.88617e-02, 1.76185e-02, -3.14367e-03 }, // 107/128 + { -3.57923e-03, 2.18695e-02, -8.87435e-02, 9.38371e-01, 1.74242e-01, -5.61142e-02, 1.68225e-02, -3.00403e-03 }, // 108/128 + { -3.42477e-03, 2.09516e-02, -8.52933e-02, 9.43001e-01, 1.64831e-01, -5.33522e-02, 1.60193e-02, -2.86289e-03 }, // 109/128 + { -3.26730e-03, 2.00132e-02, -8.17385e-02, 9.47477e-01, 1.55480e-01, -5.05770e-02, 1.52095e-02, -2.72032e-03 }, // 110/128 + { -3.10689e-03, 1.90545e-02, -7.80792e-02, 9.51795e-01, 1.46192e-01, -4.77900e-02, 1.43934e-02, -2.57640e-03 }, // 111/128 + { -2.94361e-03, 1.80759e-02, -7.43154e-02, 9.55956e-01, 1.36968e-01, -4.49929e-02, 1.35716e-02, -2.43121e-03 }, // 112/128 + { -2.77751e-03, 1.70776e-02, -7.04471e-02, 9.59958e-01, 1.27812e-01, -4.21869e-02, 1.27445e-02, -2.28483e-03 }, // 113/128 + { -2.60868e-03, 1.60599e-02, -6.64743e-02, 9.63798e-01, 1.18725e-01, -3.93735e-02, 1.19125e-02, -2.13733e-03 }, // 114/128 + { -2.43718e-03, 1.50233e-02, -6.23972e-02, 9.67477e-01, 1.09710e-01, -3.65541e-02, 1.10760e-02, -1.98880e-03 }, // 115/128 + { -2.26307e-03, 1.39681e-02, -5.82159e-02, 9.70992e-01, 1.00769e-01, -3.37303e-02, 1.02356e-02, -1.83931e-03 }, // 116/128 + { -2.08645e-03, 1.28947e-02, -5.39305e-02, 9.74342e-01, 9.19033e-02, -3.09033e-02, 9.39154e-03, -1.68894e-03 }, // 117/128 + { -1.90738e-03, 1.18034e-02, -4.95412e-02, 9.77526e-01, 8.31162e-02, -2.80746e-02, 8.54441e-03, -1.53777e-03 }, // 118/128 + { -1.72594e-03, 1.06946e-02, -4.50483e-02, 9.80543e-01, 7.44095e-02, -2.52457e-02, 7.69462e-03, -1.38589e-03 }, // 119/128 + { -1.54221e-03, 9.56876e-03, -4.04519e-02, 9.83392e-01, 6.57852e-02, -2.24178e-02, 6.84261e-03, -1.23337e-03 }, // 120/128 + { -1.35627e-03, 8.42626e-03, -3.57525e-02, 9.86071e-01, 5.72454e-02, -1.95925e-02, 5.98883e-03, -1.08030e-03 }, // 121/128 + { -1.16820e-03, 7.26755e-03, -3.09503e-02, 9.88580e-01, 4.87921e-02, -1.67710e-02, 5.13372e-03, -9.26747e-04 }, // 122/128 + { -9.78093e-04, 6.09305e-03, -2.60456e-02, 9.90917e-01, 4.04274e-02, -1.39548e-02, 4.27773e-03, -7.72802e-04 }, // 123/128 + { -7.86031e-04, 4.90322e-03, -2.10389e-02, 9.93082e-01, 3.21531e-02, -1.11453e-02, 3.42130e-03, -6.18544e-04 }, // 124/128 + { -5.92100e-04, 3.69852e-03, -1.59305e-02, 9.95074e-01, 2.39714e-02, -8.34364e-03, 2.56486e-03, -4.64053e-04 }, // 125/128 + { -3.96391e-04, 2.47942e-03, -1.07209e-02, 9.96891e-01, 1.58840e-02, -5.55134e-03, 1.70888e-03, -3.09412e-04 }, // 126/128 + { -1.98993e-04, 1.24642e-03, -5.41054e-03, 9.98534e-01, 7.89295e-03, -2.76968e-03, 8.53777e-04, -1.54700e-04 }, // 127/128 + { 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 128/128 +}; + diff --git a/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc new file mode 100644 index 00000000..ad6f6c6e --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc @@ -0,0 +1,341 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cerr; + +/// Macro for primitive value comparisons +#define assertcomplexEqual(expected0,expected1,actual,delta) \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected0, actual[0], delta); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected1, actual[1], delta); + + +#define MAX_BLKS 10 +#define FLOATS_PER_BLK 4 + +#define ERR_DELTA (1e-6) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = rint (uniform () * 32767); +} + +static void +zero_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0.0; +} + +void +ref_ccomplex_dotprod (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, + float *result) +{ + float sum0[2] = {0,0}; + float sum1[2] = {0,0}; + + do { + + sum0[0] += input[0] * taps[0] - input[1] * taps[1]; + sum0[1] += input[0] * taps[1] + input[1] * taps[0]; + sum1[0] += input[2] * taps[2] - input[3] * taps[3]; + sum1[1] += input[2] * taps[3] + input[3] * taps[2]; + + input += 4; + taps += 4; + + } while (--n_2_ccomplex_blocks != 0); + + + result[0] = sum0[0] + sum1[0]; + result[1] = sum0[1] + sum1[1]; +} + +void +qa_ccomplex_dotprod_x86::setUp () +{ + taps = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + input = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + if (taps == 0 || input == 0) + abort (); +} + +void +qa_ccomplex_dotprod_x86::tearDown () +{ + free16Align (taps); + free16Align (input); + taps = 0; + input = 0; +} + + +void +qa_ccomplex_dotprod_x86::zb () // "zero both" +{ + zero_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + zero_floats (input, MAX_BLKS * FLOATS_PER_BLK); +} + +// +// t1 +// + +void +qa_ccomplex_dotprod_x86::t1_base (ccomplex_dotprod_t ccomplex_dotprod) +{ + float result[2]; + + // cerr << "Testing dump_xmm_regs\n"; + // dump_xmm_regs (); + + // test basic cases, 1 block + + zb (); + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.0, 0.0, result, ERR_DELTA); + + // vary each input + + zb (); + input[0] = 1.0; taps[0] = 1.0; taps[1] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + //cerr << result[0] << " " << result[1] << "\n"; + assertcomplexEqual (1.0, -1.0, result, ERR_DELTA); + + zb (); + input[1] = 2.0; taps[0] = 1.0; taps[1] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, 2.0, result, ERR_DELTA); + + zb (); + input[2] = 3.0; taps[2] = 1.0; taps[3] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[3] = 4.0; taps[2] = 1.0; taps[3] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (4.0, 4.0, result, ERR_DELTA); + + // vary each tap + + zb (); + input[0] = 1.0; taps[0] = 0.5; taps[1] = -0.5; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.5, -0.5, result, ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 2.0; taps[1] = -2.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, -2.0, result, ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 3.0; taps[1] = -3.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 4.0; taps[1] = -4.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (4.0, -4.0, result, ERR_DELTA); +} + +// +// t2 +// +void +qa_ccomplex_dotprod_x86::t2_base (ccomplex_dotprod_t ccomplex_dotprod) +{ + float result[2]; + + zb (); + input[0] = 1.0; input[1] = 3.0; taps[0] = 5.0; taps[1] = -2.0; + + //1*5-3*-2 =11, 1*-2+3*5=13 + + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (11.0, 13.0, result, ERR_DELTA); + + //7*5-13*-5 =100, 7*-5+13*5=30 + + input[2] = 7.0; input[3] = 13.0; taps[2] = 5.0; taps[3] = -5.0; + + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (111.0, 43.0, result, ERR_DELTA); + + input[4] = 19; input[5] = -19; taps[4] = 23.0; taps[5] = -23.0; + + //19*23--19*-23 =0, 19*-23+-19*23=-874 + + ccomplex_dotprod (input, taps, 2, result); + assertcomplexEqual (111.0, -831.0, result, ERR_DELTA); + +} + +// +// t3 +// +void +qa_ccomplex_dotprod_x86::t3_base (ccomplex_dotprod_t ccomplex_dotprod) +{ + srandom (0); // we want reproducibility + + for (unsigned int i = 0; i < 10; i++){ + random_floats (input, MAX_BLKS * FLOATS_PER_BLK); + random_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + float ref[2]; + ref_ccomplex_dotprod (input, taps, MAX_BLKS, ref); + float calc[2]; + ccomplex_dotprod (input, taps, MAX_BLKS, calc); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[0], + calc[0], + fabs (ref[0]) * 1e-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[1], + calc[1], + fabs (ref[1]) * 1e-4); + } +} + +void +qa_ccomplex_dotprod_x86::t1_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t1_base (ccomplex_dotprod_3dnowext); +} + +void +qa_ccomplex_dotprod_x86::t2_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t2_base (ccomplex_dotprod_3dnowext); +} + +void +qa_ccomplex_dotprod_x86::t3_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t3_base (ccomplex_dotprod_3dnowext); +} + +void +qa_ccomplex_dotprod_x86::t1_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t1_base (ccomplex_dotprod_3dnow); +} + +void +qa_ccomplex_dotprod_x86::t2_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t2_base (ccomplex_dotprod_3dnow); +} + +void +qa_ccomplex_dotprod_x86::t3_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t3_base (ccomplex_dotprod_3dnow); +} + +void +qa_ccomplex_dotprod_x86::t1_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t1_base (ccomplex_dotprod_sse); +} + +void +qa_ccomplex_dotprod_x86::t2_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t2_base (ccomplex_dotprod_sse); +} + +void +qa_ccomplex_dotprod_x86::t3_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t3_base (ccomplex_dotprod_sse); +} + diff --git a/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h new file mode 100644 index 00000000..f10f0060 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_CCOMPLEX_DOTPROD_X86_H_ +#define _QA_CCOMPLEX_DOTPROD_X86_H_ + +#include +#include + +class qa_ccomplex_dotprod_x86 : public CppUnit::TestCase { + public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_ccomplex_dotprod_x86); + CPPUNIT_TEST (t1_3dnowext); + CPPUNIT_TEST (t2_3dnowext); + CPPUNIT_TEST (t3_3dnowext); + CPPUNIT_TEST (t1_3dnow); + CPPUNIT_TEST (t2_3dnow); + CPPUNIT_TEST (t3_3dnow); + CPPUNIT_TEST (t1_sse); + CPPUNIT_TEST (t2_sse); + CPPUNIT_TEST (t3_sse); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1_3dnowext (); + void t2_3dnowext (); + void t3_3dnowext (); + void t1_3dnow (); + void t2_3dnow (); + void t3_3dnow (); + void t1_sse (); + void t2_sse (); + void t3_sse (); + + + typedef void (*ccomplex_dotprod_t)(const float *input, + const float *taps, + unsigned n_2_ccomplex_blocks, + float *result); + + void t1_base (ccomplex_dotprod_t); + void t2_base (ccomplex_dotprod_t); + void t3_base (ccomplex_dotprod_t); + + void zb (); + + float *taps; // 16-byte aligned + float *input; // 16-byte aligned +}; + + +#endif /* _QA_CCOMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc new file mode 100644 index 00000000..91c8e9e2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc @@ -0,0 +1,347 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cerr; + +/// Macro for primitive value comparisons +#define assertcomplexEqual(expected0,expected1,actual,delta) \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected0, actual[0], delta); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected1, actual[1], delta); + + +#define MAX_BLKS 10 +#define FLOATS_PER_BLK 4 +#define SHORTS_PER_BLK 2 + +#define ERR_DELTA (1e-6) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = rint (uniform () * 32767); +} + +static void +zero_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0.0; +} + +static void +random_shorts (short *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (short) rint (uniform () * 32767); +} + +static void +zero_shorts (short *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0; +} + +void +ref_complex_dotprod (const short *input, + const float *taps, unsigned n_2_complex_blocks, + float *result) +{ + float sum0[2] = {0,0}; + float sum1[2] = {0,0}; + + do { + + sum0[0] += input[0] * taps[0]; + sum0[1] += input[0] * taps[1]; + sum1[0] += input[1] * taps[2]; + sum1[1] += input[1] * taps[3]; + + input += 2; + taps += 4; + + } while (--n_2_complex_blocks != 0); + + + result[0] = sum0[0] + sum1[0]; + result[1] = sum0[1] + sum1[1]; +} + +void +qa_complex_dotprod_x86::setUp () +{ + taps = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + input = (short *) calloc16Align (MAX_BLKS, + sizeof (short) * SHORTS_PER_BLK); + + if (taps == 0 || input == 0) + abort (); +} + +void +qa_complex_dotprod_x86::tearDown () +{ + free16Align (taps); + free16Align (input); + taps = 0; + input = 0; +} + + +void +qa_complex_dotprod_x86::zb () // "zero both" +{ + zero_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + zero_shorts (input, MAX_BLKS * SHORTS_PER_BLK); +} + +// +// t1 +// + +void +qa_complex_dotprod_x86::t1_base (complex_dotprod_t complex_dotprod) +{ + float result[2]; + + // cerr << "Testing dump_xmm_regs\n"; + // dump_xmm_regs (); + + // test basic cases, 1 block + + zb (); + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.0, 0.0, result, ERR_DELTA); + + // vary each input + + zb (); + input[0] = 1; taps[0] = 1.0; taps[1] = -1.0; + complex_dotprod (input, taps, 1, result); + //cerr << result[0] << " " << result[1] << "\n"; + assertcomplexEqual (1.0, -1.0, result, ERR_DELTA); + + zb (); + input[1] = 2; taps[2] = 1.0; taps[3] = -1.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, -2.0, result, ERR_DELTA); + + zb (); + input[2] = 3; taps[4] = 1.0; taps[5] = -1.0; + complex_dotprod (input, taps, 2, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[3] = 4; taps[6] = 1.0; taps[7] = -1.0; + complex_dotprod (input, taps, 2, result); + assertcomplexEqual (4.0, -4.0, result, ERR_DELTA); + + // vary each tap + + zb (); + input[0] = 1; taps[0] = 0.5; taps[1] = -0.5; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.5, -0.5, result, ERR_DELTA); + + zb (); + input[0] = 1; taps[0] = 2.0; taps[1] = -2.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, -2.0, result, ERR_DELTA); + + zb (); + input[0] = 1; taps[0] = 3.0; taps[1] = -3.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[0] = 1; taps[0] = 4.0; taps[1] = -4.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (4.0, -4.0, result, ERR_DELTA); +} + +// +// t2 +// +void +qa_complex_dotprod_x86::t2_base (complex_dotprod_t complex_dotprod) +{ + float result[2]; + + zb (); + input[0] = 1; taps[0] = 2.0; taps[1] = -2.0; + input[1] = 3; taps[2] = 5.0; taps[3] = -5.0; + input[2] = 7; taps[4] = 11.0; taps[5] = -11.0; + input[3] = 13; taps[6] = 17.0; taps[7] = -17.0; + + complex_dotprod (input, taps, 2, result); + assertcomplexEqual (315.0, -315.0, result, ERR_DELTA); + + input[4] = 19; taps[8] = 23.0; taps[9] = -23.0; + complex_dotprod (input, taps, 3, result); + assertcomplexEqual (752.0, -752.0, result, ERR_DELTA); + +} + +// +// t3 +// +void +qa_complex_dotprod_x86::t3_base (complex_dotprod_t complex_dotprod) +{ + srandom (0); // we want reproducibility + + for (unsigned int i = 0; i < 10; i++){ + random_shorts (input, MAX_BLKS * SHORTS_PER_BLK); + random_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + float ref[2]; + ref_complex_dotprod (input, taps, MAX_BLKS, ref); + float calc[2]; + complex_dotprod (input, taps, MAX_BLKS, calc); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[0], + calc[0], + fabs (ref[0]) * 1e-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[1], + calc[1], + fabs (ref[1]) * 1e-4); + } +} + +void +qa_complex_dotprod_x86::t1_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t1_base (complex_dotprod_3dnowext); +} + +void +qa_complex_dotprod_x86::t2_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t2_base (complex_dotprod_3dnowext); +} + +void +qa_complex_dotprod_x86::t3_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t3_base (complex_dotprod_3dnowext); +} + +void +qa_complex_dotprod_x86::t1_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t1_base (complex_dotprod_3dnow); +} + +void +qa_complex_dotprod_x86::t2_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t2_base (complex_dotprod_3dnow); +} + +void +qa_complex_dotprod_x86::t3_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t3_base (complex_dotprod_3dnow); +} + +void +qa_complex_dotprod_x86::t1_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t1_base (complex_dotprod_sse); +} + +void +qa_complex_dotprod_x86::t2_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t2_base (complex_dotprod_sse); +} + +void +qa_complex_dotprod_x86::t3_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t3_base (complex_dotprod_sse); +} + diff --git a/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h new file mode 100644 index 00000000..53509ea6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_COMPLEX_DOTPROD_X86_H_ +#define _QA_COMPLEX_DOTPROD_X86_H_ + +#include +#include + +class qa_complex_dotprod_x86 : public CppUnit::TestCase { + public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_complex_dotprod_x86); + CPPUNIT_TEST (t1_3dnowext); + CPPUNIT_TEST (t2_3dnowext); + CPPUNIT_TEST (t3_3dnowext); + CPPUNIT_TEST (t1_3dnow); + CPPUNIT_TEST (t2_3dnow); + CPPUNIT_TEST (t3_3dnow); + CPPUNIT_TEST (t1_sse); + CPPUNIT_TEST (t2_sse); + CPPUNIT_TEST (t3_sse); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1_3dnowext (); + void t2_3dnowext (); + void t3_3dnowext (); + void t1_3dnow (); + void t2_3dnow (); + void t3_3dnow (); + void t1_sse (); + void t2_sse (); + void t3_sse (); + + + typedef void (*complex_dotprod_t)(const short *input, + const float *taps, + unsigned n_2_complex_blocks, + float *result); + + void t1_base (complex_dotprod_t); + void t2_base (complex_dotprod_t); + void t3_base (complex_dotprod_t); + + void zb (); + + float *taps; // 16-byte aligned + short *input; // 16-byte aligned +}; + + +#endif /* _QA_COMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_dotprod.h b/gnuradio-core/src/lib/filter/qa_dotprod.h new file mode 100644 index 00000000..3fbbdc3d --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod.h @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_DOTPROD_H_ +#define _QA_DOTPROD_H_ + +#include + +CppUnit::TestSuite *qa_dotprod_suite (); + +#endif // _QA_DOTPROD_H_ + diff --git a/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc b/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc new file mode 100644 index 00000000..d0f66cc9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "qa_dotprod.h" + +CppUnit::TestSuite * +qa_dotprod_suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("dotprod"); + + // empty test suite + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_dotprod_x86.cc new file mode 100644 index 00000000..6aeb4932 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod_x86.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "qa_dotprod.h" +#include "qa_float_dotprod_x86.h" +#include "qa_complex_dotprod_x86.h" +#include "qa_ccomplex_dotprod_x86.h" + +CppUnit::TestSuite * +qa_dotprod_suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("dotprod"); + + s->addTest (qa_float_dotprod_x86::suite ()); + s->addTest (qa_complex_dotprod_x86::suite ()); + s->addTest (qa_ccomplex_dotprod_x86::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_filter.cc b/gnuradio-core/src/lib/filter/qa_filter.cc new file mode 100644 index 00000000..75415a79 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_filter.cc @@ -0,0 +1,52 @@ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CppUnit::TestSuite * +qa_filter::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("filter"); + + s->addTest (qa_dotprod_suite ()); + s->addTest (qa_gri_mmse_fir_interpolator::suite ()); + s->addTest (qa_gr_fir_fff::suite ()); + s->addTest (qa_gr_fir_ccc::suite ()); + s->addTest (qa_gr_fir_fcc::suite ()); + s->addTest (qa_gr_fir_scc::suite ()); + s->addTest (qa_gr_fir_ccf::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_filter.h b/gnuradio-core/src/lib/filter/qa_filter.h new file mode 100644 index 00000000..71371ae1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_filter.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_FILTER_H_ +#define _QA_FILTER_H_ + +#include + +//! collect all the tests for the gr directory + +class qa_filter { + public: + //! return suite of tests for all of gr directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_FILTER_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc new file mode 100644 index 00000000..a1697797 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc @@ -0,0 +1,270 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cerr; + + +#define MAX_BLKS 10 +#define FLOATS_PER_BLK 4 + +#define ERR_DELTA (1e-6) + + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = random () - RANDOM_MAX/2; +} + +static void +zero_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0.0; +} + +float +ref_float_dotprod (const float *input, + const float *taps, unsigned n_4_float_blocks) +{ + float sum0 = 0; + float sum1 = 0; + float sum2 = 0; + float sum3 = 0; + + do { + + sum0 += input[0] * taps[0]; + sum1 += input[1] * taps[1]; + sum2 += input[2] * taps[2]; + sum3 += input[3] * taps[3]; + + input += 4; + taps += 4; + + } while (--n_4_float_blocks != 0); + + + return sum0 + sum1 + sum2 + sum3; +} + +void +qa_float_dotprod_x86::setUp () +{ + taps = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + input = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + if (taps == 0 || input == 0) + abort (); +} + +void +qa_float_dotprod_x86::tearDown () +{ + free16Align (taps); + free16Align (input); + taps = 0; + input = 0; +} + + +void +qa_float_dotprod_x86::zb () // "zero both" +{ + zero_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + zero_floats (input, MAX_BLKS * FLOATS_PER_BLK); +} + +// +// t1 +// + +void +qa_float_dotprod_x86::t1_base (float_dotprod_t float_dotprod) +{ + + // cerr << "Testing dump_xmm_regs\n"; + // dump_xmm_regs (); + + // test basic cases, 1 block + + zb (); + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, float_dotprod (input, taps, 1), ERR_DELTA); + + // vary each input + + zb (); + input[0] = 0.5; taps[0] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.5, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[1] = 2.0; taps[1] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (2.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[2] = 3.0; taps[2] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[3] = 4.0; taps[3] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (4.0, float_dotprod (input, taps, 1), ERR_DELTA); + + // vary each tap + + zb (); + input[0] = 1.0; taps[0] = 0.5; + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.5, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 2.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (2.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 3.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 4.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (4.0, float_dotprod (input, taps, 1), ERR_DELTA); +} + +// +// t2 +// +void +qa_float_dotprod_x86::t2_base (float_dotprod_t float_dotprod) +{ + zb (); + input[0] = 1.0; taps[0] = 2.0; + input[1] = 3.0; taps[1] = 5.0; + input[2] = 7.0; taps[2] = 11.0; + input[3] = 13.0; taps[3] = 17.0; + + CPPUNIT_ASSERT_DOUBLES_EQUAL (315.0, float_dotprod (input, taps, 1), ERR_DELTA); + + input[4] = 19.0; taps[4] = 23.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (752.0, float_dotprod (input, taps, 2), ERR_DELTA); + +} + +// +// t3 +// +void +qa_float_dotprod_x86::t3_base (float_dotprod_t float_dotprod) +{ + srandom (0); // we want reproducibility + + for (unsigned int i = 0; i < 10; i++){ + random_floats (input, MAX_BLKS * FLOATS_PER_BLK); + random_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + float ref = ref_float_dotprod (input, taps, MAX_BLKS); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref, + float_dotprod (input, taps, MAX_BLKS), + fabs (ref) * 1e-4); + } +} + +void +qa_float_dotprod_x86::t1_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t1_base (float_dotprod_3dnow); +} + +void +qa_float_dotprod_x86::t2_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t2_base (float_dotprod_3dnow); +} + +void +qa_float_dotprod_x86::t3_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t3_base (float_dotprod_3dnow); +} + +void +qa_float_dotprod_x86::t1_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t1_base (float_dotprod_sse); +} + +void +qa_float_dotprod_x86::t2_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t2_base (float_dotprod_sse); +} + +void +qa_float_dotprod_x86::t3_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t3_base (float_dotprod_sse); +} diff --git a/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h new file mode 100644 index 00000000..00568129 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_FLOAT_DOTPROD_X86_H_ +#define _QA_FLOAT_DOTPROD_X86_H_ + +#include +#include + +class qa_float_dotprod_x86 : public CppUnit::TestCase { + public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_float_dotprod_x86); + CPPUNIT_TEST (t1_3dnow); + CPPUNIT_TEST (t2_3dnow); + CPPUNIT_TEST (t3_3dnow); + CPPUNIT_TEST (t1_sse); + CPPUNIT_TEST (t2_sse); + CPPUNIT_TEST (t3_sse); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1_3dnow (); + void t2_3dnow (); + void t3_3dnow (); + void t1_sse (); + void t2_sse (); + void t3_sse (); + + + typedef float (*float_dotprod_t)(const float *input, + const float *taps, + unsigned n_4_float_blocks); + + void t1_base (float_dotprod_t); + void t2_base (float_dotprod_t); + void t3_base (float_dotprod_t); + + + void zb (); + + float *taps; // 16-byte aligned + float *input; // 16-byte aligned + +}; + + +#endif /* _QA_FLOAT_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc new file mode 100644 index 00000000..9c70a167 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc @@ -0,0 +1,183 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_ccc* (*fir_maker_t)(const std::vector &taps); + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_input (i_type *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (i_type) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Our SIMD ccc kernel requires that the complex input be 64-bit (8-byte) aligned. + // i_type input[INPUT_LEN]; + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_input (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector f1_taps (&taps[0], &taps[n]); + gr_fir_ccc *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + ASSERT_COMPLEXES_EQUAL (expected_output[o], + actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } + free16Align(input); +} + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector info; + gr_fir_util::get_gr_fir_ccc_info (&info); // get all known ccc implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_ccc::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h new file mode 100644 index 00000000..46fa9b0e --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_FIR_CCC_H_ +#define _QA_GR_FIR_CCC_H_ + +#include +#include + +class qa_gr_fir_ccc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_ccc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GR_FIR_CCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc new file mode 100644 index 00000000..c45e0853 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc @@ -0,0 +1,183 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef float tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_ccf* (*fir_maker_t)(const std::vector &taps); + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Our SIMD ccc kernel requires that the complex input be 64-bit (8-byte) aligned. + //i_type input[INPUT_LEN]; + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_complex (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector f1_taps (&taps[0], &taps[n]); + gr_fir_ccf *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + ASSERT_COMPLEXES_EQUAL (expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } + free16Align(input); +} + + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector info; + gr_fir_util::get_gr_fir_ccf_info (&info); // get all known ccf implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + + +void +qa_gr_fir_ccf::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h new file mode 100644 index 00000000..bf87136d --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_FIR_CCF_H_ +#define _QA_GR_FIR_CCF_H_ + +#include +#include + +class qa_gr_fir_ccf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_ccf); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_CCF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc new file mode 100644 index 00000000..0706b585 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc @@ -0,0 +1,180 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +typedef float i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_fcc* (*fir_maker_t)(const std::vector &taps); + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_input (i_type *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (i_type) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + i_type input[INPUT_LEN]; + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_input (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector f1_taps (&taps[0], &taps[n]); + gr_fir_fcc *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + ASSERT_COMPLEXES_EQUAL (expected_output[o], + actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } +} + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector info; + gr_fir_util::get_gr_fir_fcc_info (&info); // get all known fcc implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_fcc::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h new file mode 100644 index 00000000..145f72f0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_FIR_FCC_H_ +#define _QA_GR_FIR_FCC_H_ + +#include +#include + +class qa_gr_fir_fcc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_fcc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); +}; + + +#endif /* _QA_GR_FIR_FCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc new file mode 100644 index 00000000..1ba3bee5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc @@ -0,0 +1,225 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +typedef float i_type; +typedef float o_type; +typedef float tap_type; +typedef float acc_type; + +#define ERR_DELTA (1e-6) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_fff* (*fir_maker_t)(const std::vector &taps); + + +// ---------------------------------------------------------------- + +const static i_type input_1[] = { + 234, -4, 23, -56, 45, 98, -23, -7 +}; + +const static tap_type taps_1a[] = { + -3 +}; + +const static o_type expected_1a[] = { + -702, 12, -69, 168, -135, -294, 69, 21 +}; + +const static tap_type taps_1b[] = { + -4, 5 +}; + +const static o_type expected_1b[] = { + 1186, -112, 339, -460, -167, 582, -87 +}; + +// ---------------------------------------------------------------- + +static void +test_known_io (fir_maker_t maker) +{ + vector t1a (&taps_1a[0], &taps_1a[NELEM (taps_1a)]); + vector t1b (&taps_1b[0], &taps_1b[NELEM (taps_1b)]); + + gr_fir_fff *f1 = maker (t1a); // create filter + CPPUNIT_ASSERT_EQUAL ((unsigned) 1, f1->ntaps ()); // check ntaps + + // check filter output + int n = NELEM (input_1) - f1->ntaps () + 1; + for (int i = 0; i < n; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_1a[i], f1->filter (&input_1[i]), ERR_DELTA); + + f1->set_taps (t1b); // set new taps + CPPUNIT_ASSERT_EQUAL ((unsigned) 2, f1->ntaps ()); // check ntaps + + // check filter output + n = NELEM (input_1) - f1->ntaps () + 1; + for (int i = 0; i < n; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_1b[i], f1->filter (&input_1[i]), ERR_DELTA); + + // test filterN interface + + o_type output[NELEM (expected_1b)]; + memset (output, 0, sizeof (output)); + + f1->filterN (output, input_1, n); + for (int i = 0; i < n; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_1b[i], output[i], ERR_DELTA); + + delete f1; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = rint (uniform () * 32768); +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + i_type input[INPUT_LEN]; + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector f1_taps (&taps[0], &taps[n]); + gr_fir_fff *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_output[o], actual_output[o], + fabs (expected_output[o]) * 1e-4); + } + + delete f1; + } + } +} + + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector info; + gr_fir_util::get_gr_fir_fff_info (&info); // get all known fff implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_fff::t1 () +{ + for_each (test_known_io); +} + +void +qa_gr_fir_fff::t2 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fff.h b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.h new file mode 100644 index 00000000..34d86f9d --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_FIR_FFF_H_ +#define _QA_GR_FIR_FFF_H_ + +#include +#include + +class qa_gr_fir_fff : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_fff); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + void t2 (); + +}; + + +#endif /* _QA_GR_FIR_FFF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc new file mode 100644 index 00000000..38a76924 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc @@ -0,0 +1,179 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +typedef short i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_scc* (*fir_maker_t)(const std::vector &taps); + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_input (i_type *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (i_type) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += (float) input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + i_type input[INPUT_LEN]; + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_input (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector f1_taps (&taps[0], &taps[n]); + gr_fir_scc *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + ASSERT_COMPLEXES_EQUAL (expected_output[o], + actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } +} + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector info; + gr_fir_util::get_gr_fir_scc_info (&info); // get all known scc implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_scc::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_scc.h b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.h new file mode 100644 index 00000000..2662d02b --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_FIR_SCC_H_ +#define _QA_GR_FIR_SCC_H_ + +#include +#include + +class qa_gr_fir_scc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_scc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GR_FIR_SCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc new file mode 100644 index 00000000..a756bbc4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static float +test_fcn (double index) +{ + return (2 * sin (index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * sin (index * 0.077 * 2 * M_PI + 0.3 * M_PI)); +} + + +void +qa_gri_mmse_fir_interpolator::t1 () +{ + static const unsigned N = 100; + float input[N + 10]; + + for (unsigned i = 0; i < NELEM(input); i++) + input[i] = test_fcn ((double) i); + + gri_mmse_fir_interpolator intr; + float inv_nsteps = 1.0 / intr.nsteps (); + + for (unsigned i = 0; i < N; i++){ + for (unsigned imu = 0; imu <= intr.nsteps (); imu += 1){ + float expected = test_fcn ((i + 3) + imu * inv_nsteps); + float actual = intr.interpolate (&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } +} + diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h new file mode 100644 index 00000000..85be45e8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GRI_MMSE_FIR_INTERPOLATOR_H_ +#define _QA_GRI_MMSE_FIR_INTERPOLATOR_H_ + +#include +#include + +class qa_gri_mmse_fir_interpolator : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_mmse_fir_interpolator); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GRI_MMSE_FIR_INTERPOLATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/short_dotprod_generic.c b/gnuradio-core/src/lib/filter/short_dotprod_generic.c new file mode 100644 index 00000000..4fca2e5d --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_generic.c @@ -0,0 +1,49 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "short_dotprod_generic.h" + + +int +short_dotprod_generic (const short *input, + const short *taps, unsigned n_4_short_blocks) +{ + int sum0 = 0; + int sum1 = 0; + int sum2 = 0; + int sum3 = 0; + + do { + + sum0 += input[0] * taps[0]; + sum1 += input[1] * taps[1]; + sum2 += input[2] * taps[2]; + sum3 += input[3] * taps[3]; + + input += 4; + taps += 4; + + } while (--n_4_short_blocks != 0); + + + return (sum0 + sum1 + sum2 + sum3); +} diff --git a/gnuradio-core/src/lib/filter/short_dotprod_generic.h b/gnuradio-core/src/lib/filter/short_dotprod_generic.h new file mode 100644 index 00000000..6e3709ff --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_generic.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _SHORT_DOTPROD_GENERIC_H_ +#define _SHORT_DOTPROD_GENERIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +short_dotprod_generic (const short *input, + const short *taps, unsigned n_4_short_blocks); + + +#ifdef __cplusplus +} +#endif + + + +#endif /* _SHORT_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S new file mode 100644 index 00000000..7c9ae078 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S @@ -0,0 +1,113 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# SIMD MMX dot product +# Equivalent to the following C code: +# long dotprod(signed short *a,signed short *b,int cnt) +# { +# long sum = 0; +# cnt *= 4; +# while(cnt--) +# sum += *a++ + *b++; +# return sum; +# } +# a and b should also be 64-bit aligned, or speed will suffer greatly +# Copyright 1999, Phil Karn KA9Q +# May be used under the terms of the GNU public license + +#include "assembly.h" + + + .file "short_dotprod_mmx.S" + .version "01.01" +.text + .p2align 3 +.globl GLOB_SYMB(short_dotprod_mmx) + DEF_FUNC_HEAD(short_dotprod_mmx) +GLOB_SYMB(short_dotprod_mmx): + pushl %ebp + movl %esp,%ebp + pushl %esi + pushl %edi + pushl %ecx + pushl %ebx + movl 8(%ebp),%esi # a + movl 12(%ebp),%edi # b + movl 16(%ebp),%ecx # cnt + pxor %mm0,%mm0 # clear running sum (in two 32-bit halves) + +# MMX dot product loop unrolled 4 times, crunching 16 terms per loop + .p2align 4 +.Loop1mmx: subl $4,%ecx + jl .Loop1Done + + movq (%esi),%mm1 # mm1 = a[3],a[2],a[1],a[0] + pmaddwd (%edi),%mm1 # mm1 = b[3]*a[3]+b[2]*a[2],b[1]*a[1]+b[0]*a[0] + paddd %mm1,%mm0 + + movq 8(%esi),%mm1 + pmaddwd 8(%edi),%mm1 + paddd %mm1,%mm0 + + movq 16(%esi),%mm1 + pmaddwd 16(%edi),%mm1 + paddd %mm1,%mm0 + + movq 24(%esi),%mm1 + addl $32,%esi + pmaddwd 24(%edi),%mm1 + addl $32,%edi + paddd %mm1,%mm0 + + jmp .Loop1mmx +.Loop1Done: + + addl $4,%ecx + +# MMX dot product loop, not unrolled, crunching 4 terms per loop +# This could be redone as Duff's Device on the unrolled loop above +.Loop2: subl $1,%ecx + jl .Loop2Done + + movq (%esi),%mm1 + addl $8,%esi + pmaddwd (%edi),%mm1 + addl $8,%edi + paddd %mm1,%mm0 + jmp .Loop2 +.Loop2Done: + + movd %mm0,%ebx # right-hand word to ebx + punpckhdq %mm0,%mm0 # left-hand word to right side of %mm0 + movd %mm0,%eax + addl %ebx,%eax # running sum now in %eax + emms # done with MMX + + popl %ebx + popl %ecx + popl %edi + popl %esi + movl %ebp,%esp + popl %ebp + ret + +FUNC_TAIL(short_dotprod_mmx) + .ident "Hand coded x86 MMX assembly" diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S new file mode 100644 index 00000000..4c46e0ea --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S @@ -0,0 +1,101 @@ +# +# Copyright 2002,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# SIMD MMX dot product +# Equivalent to the following C code: +# long dotprod(signed short *a,signed short *b,int cnt) +# { +# long sum = 0; +# cnt *= 4; +# while(cnt--) +# sum += *a++ + *b++; +# return sum; +# } +# a and b should also be 64-bit aligned, or speed will suffer greatly +# Copyright 1999, Phil Karn KA9Q +# May be used under the terms of the GNU public license + +#include "assembly.h" + + + .file "short_dotprod_mmx64.S" + .version "01.01" +.text + .p2align 3 +.globl GLOB_SYMB(short_dotprod_mmx) + DEF_FUNC_HEAD(short_dotprod_mmx) +GLOB_SYMB(short_dotprod_mmx): + + # a: rdi, b: rsi, cnt: rdx + + pxor %mm0,%mm0 # clear running sum (in two 32-bit halves) + +# MMX dot product loop unrolled 4 times, crunching 16 terms per loop + .p2align 4 +.Loop1mmx: sub $4,%rdx + jl .Loop1Done + + movq (%rdi),%mm1 # mm1 = a[3],a[2],a[1],a[0] + pmaddwd (%rsi),%mm1 # mm1 = b[3]*a[3]+b[2]*a[2],b[1]*a[1]+b[0]*a[0] + paddd %mm1,%mm0 + + movq 8(%rdi),%mm1 + pmaddwd 8(%rsi),%mm1 + paddd %mm1,%mm0 + + movq 16(%rdi),%mm1 + pmaddwd 16(%rsi),%mm1 + paddd %mm1,%mm0 + + movq 24(%rdi),%mm1 + add $32,%rdi + pmaddwd 24(%rsi),%mm1 + add $32,%rsi + paddd %mm1,%mm0 + + jmp .Loop1mmx +.Loop1Done: + + add $4,%rdx + +# MMX dot product loop, not unrolled, crunching 4 terms per loop +# This could be redone as Duff's Device on the unrolled loop above +.Loop2: sub $1,%rdx + jl .Loop2Done + + movq (%rdi),%mm1 + add $8,%rdi + pmaddwd (%rsi),%mm1 + add $8,%rsi + paddd %mm1,%mm0 + jmp .Loop2 +.Loop2Done: + + movd %mm0,%edx # right-hand word to edx + punpckhdq %mm0,%mm0 # left-hand word to right side of %mm0 + movd %mm0,%eax + addl %edx,%eax # running sum now in %eax + emms # done with MMX + + retq + +FUNC_TAIL(short_dotprod_mmx) + .ident "Hand coded x86_64 MMX assembly" diff --git a/gnuradio-core/src/lib/filter/short_dotprod_x86.h b/gnuradio-core/src/lib/filter/short_dotprod_x86.h new file mode 100644 index 00000000..03b47489 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_x86.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _SHORT_DOTPROD_X86_H_ +#define _SHORT_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +short_dotprod_mmx (const short *input, + const short *taps, unsigned n_4_short_blocks); + +int +short_dotprod_sse2 (const short *input, + const short *taps, unsigned n_4_short_blocks); + +#ifdef __cplusplus +} +#endif + + + +#endif /* _SHORT_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/sse_debug.c b/gnuradio-core/src/lib/filter/sse_debug.c new file mode 100644 index 00000000..f27d3930 --- /dev/null +++ b/gnuradio-core/src/lib/filter/sse_debug.c @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include +#include +#include + +void +format_xmm_regs (FILE *f, struct xmm_regs *r) +{ + int i; + + for (i = 0; i < 8; i++){ + union xmm_register *x = &r->xmm[i]; + fprintf (f, "xmm%d: %08lx %08lx %08lx %08lx", i, + x->ul[0], x->ul[1], x->ul[2], x->ul[3]); + fprintf (f, " %12g %12g %12g %12g\n", + x->f[0], x->f[1], x->f[2], x->f[3]); + } +} + + +void +get_xmm_regs (struct xmm_regs *x) +{ + asm ("movups %%xmm0,0x00(%0); \n" + "movups %%xmm1,0x10(%0); \n" + "movups %%xmm2,0x20(%0); \n" + "movups %%xmm3,0x30(%0); \n" + "movups %%xmm4,0x40(%0); \n" + "movups %%xmm5,0x50(%0); \n" + "movups %%xmm6,0x60(%0); \n" + "movups %%xmm7,0x70(%0); \n" : : "r" (x)); +} + +void +dump_xmm_regs (void) +{ + struct xmm_regs r; + + get_xmm_regs (&r); + format_xmm_regs (stderr, &r); +} + diff --git a/gnuradio-core/src/lib/filter/sse_debug.h b/gnuradio-core/src/lib/filter/sse_debug.h new file mode 100644 index 00000000..f356a0e0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/sse_debug.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _SSE_DEBUG_H_ +#define _SSE_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + union xmm_register { + unsigned long ul[4]; + float f[4]; + }; + + struct xmm_regs { + union xmm_register xmm[8]; + }; + + // callable from asm, dumps all xmm regs + void dump_xmm_regs (void); + + void get_xmm_regs (struct xmm_regs *x); + +#ifdef __cplusplus +} +#endif + +#endif // _SSE_DEBUG_H_ diff --git a/gnuradio-core/src/lib/filter/sysconfig_generic.cc b/gnuradio-core/src/lib/filter/sysconfig_generic.cc new file mode 100644 index 00000000..1cecf49f --- /dev/null +++ b/gnuradio-core/src/lib/filter/sysconfig_generic.cc @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +gr_fir_sysconfig * +gr_fir_sysconfig_singleton () +{ + static gr_fir_sysconfig *singleton = 0; + + if (singleton) + return singleton; + + singleton = new gr_fir_sysconfig_generic (); + return singleton; +} diff --git a/gnuradio-core/src/lib/filter/sysconfig_x86.cc b/gnuradio-core/src/lib/filter/sysconfig_x86.cc new file mode 100644 index 00000000..d2c31612 --- /dev/null +++ b/gnuradio-core/src/lib/filter/sysconfig_x86.cc @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +gr_fir_sysconfig * +gr_fir_sysconfig_singleton () +{ + static gr_fir_sysconfig *singleton = 0; + + if (singleton) + return singleton; + + singleton = new gr_fir_sysconfig_x86 (); + return singleton; +} diff --git a/gnuradio-core/src/lib/g72x/Makefile.am b/gnuradio-core/src/lib/g72x/Makefile.am new file mode 100644 index 00000000..c8ba3e8d --- /dev/null +++ b/gnuradio-core/src/lib/g72x/Makefile.am @@ -0,0 +1,27 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +noinst_LTLIBRARIES = libccitt.la +libccitt_la_SOURCES = g711.c g72x.c g721.c g723_24.c g723_40.c g72x.h + +EXTRA_DIST = encode.c decode.c diff --git a/gnuradio-core/src/lib/g72x/README b/gnuradio-core/src/lib/g72x/README new file mode 100644 index 00000000..23b0e7dd --- /dev/null +++ b/gnuradio-core/src/lib/g72x/README @@ -0,0 +1,94 @@ +The files in this directory comprise ANSI-C language reference implementations +of the CCITT (International Telegraph and Telephone Consultative Committee) +G.711, G.721 and G.723 voice compressions. They have been tested on Sun +SPARCstations and passed 82 out of 84 test vectors published by CCITT +(Dec. 20, 1988) for G.721 and G.723. [The two remaining test vectors, +which the G.721 decoder implementation for u-law samples did not pass, +may be in error because they are identical to two other vectors for G.723_40.] + +This source code is released by Sun Microsystems, Inc. to the public domain. +Please give your acknowledgement in product literature if this code is used +in your product implementation. + +Sun Microsystems supports some CCITT audio formats in Solaris 2.0 system +software. However, Sun's implementations have been optimized for higher +performance on SPARCstations. + + +The source files for CCITT conversion routines in this directory are: + + g72x.h header file for g721.c, g723_24.c and g723_40.c + g711.c CCITT G.711 u-law and A-law compression + g72x.c common denominator of G.721 and G.723 ADPCM codes + g721.c CCITT G.721 32Kbps ADPCM coder (with g72x.c) + g723_24.c CCITT G.723 24Kbps ADPCM coder (with g72x.c) + g723_40.c CCITT G.723 40Kbps ADPCM coder (with g72x.c) + + +Simple conversions between u-law, A-law, and 16-bit linear PCM are invoked +as follows: + + unsigned char ucode, acode; + short pcm_val; + + ucode = linear2ulaw(pcm_val); + ucode = alaw2ulaw(acode); + + acode = linear2alaw(pcm_val); + acode = ulaw2alaw(ucode); + + pcm_val = ulaw2linear(ucode); + pcm_val = alaw2linear(acode); + + +The other CCITT compression routines are invoked as follows: + + #include "g72x.h" + + struct g72x_state state; + int sample, code; + + g72x_init_state(&state); + code = {g721,g723_24,g723_40}_encoder(sample, coding, &state); + sample = {g721,g723_24,g723_40}_decoder(code, coding, &state); + +where + coding = AUDIO_ENCODING_ULAW for 8-bit u-law samples + AUDIO_ENCODING_ALAW for 8-bit A-law samples + AUDIO_ENCODING_LINEAR for 16-bit linear PCM samples + + + +This directory also includes the following sample programs: + + encode.c CCITT ADPCM encoder + decode.c CCITT ADPCM decoder + Makefile makefile for the sample programs + + +The sample programs contain examples of how to call the various compression +routines and pack/unpack the bits. The sample programs read byte streams from +stdin and write to stdout. The input/output data is raw data (no file header +or other identifying information is embedded). The sample programs are +invoked as follows: + + encode [-3|4|5] [-a|u|l] outfile + decode [-3|4|5] [-a|u|l] outfile +where: + -3 encode to (decode from) G.723 24kbps (3-bit) data + -4 encode to (decode from) G.721 32kbps (4-bit) data [the default] + -5 encode to (decode from) G.723 40kbps (5-bit) data + -a encode from (decode to) A-law data + -u encode from (decode to) u-law data [the default] + -l encode from (decode to) 16-bit linear data + +Examples: + # Read 16-bit linear and output G.721 + encode -4 -l g721file + + # Read 40Kbps G.723 and output A-law + decode -5 -a alawfile + + # Compress and then decompress u-law data using 24Kbps G.723 + encode -3 ulawout + diff --git a/gnuradio-core/src/lib/g72x/decode.c b/gnuradio-core/src/lib/g72x/decode.c new file mode 100644 index 00000000..cf8c739c --- /dev/null +++ b/gnuradio-core/src/lib/g72x/decode.c @@ -0,0 +1,113 @@ +/* + * decode.c + * + * CCITT ADPCM decoder + * + * Usage : decode [-3|4|5] [-a|u|l] < infile > outfile + */ +#include +#include "g72x.h" + + +/* + * Unpack input codes and pass them back as bytes. + * Returns 1 if there is residual input, returns -1 if eof, else returns 0. + */ +int +unpack_input( + unsigned char *code, + int bits) +{ + static unsigned int in_buffer = 0; + static int in_bits = 0; + unsigned char in_byte; + + if (in_bits < bits) { + if (fread(&in_byte, sizeof (char), 1, stdin) != 1) { + *code = 0; + return (-1); + } + in_buffer |= (in_byte << in_bits); + in_bits += 8; + } + *code = in_buffer & ((1 << bits) - 1); + in_buffer >>= bits; + in_bits -= bits; + return (in_bits > 0); +} + + +main( + int argc, + char **argv) +{ + short sample; + unsigned char code; + int n; + struct g72x_state state; + int out_coding; + int out_size; + int (*dec_routine)(); + int dec_bits; + + g72x_init_state(&state); + out_coding = AUDIO_ENCODING_ULAW; + out_size = sizeof (char); + dec_routine = g721_decoder; + dec_bits = 4; + + /* Process encoding argument, if any */ + while ((argc > 1) && (argv[1][0] == '-')) { + switch (argv[1][1]) { + case '3': + dec_routine = g723_24_decoder; + dec_bits = 3; + break; + case '4': + dec_routine = g721_decoder; + dec_bits = 4; + break; + case '5': + dec_routine = g723_40_decoder; + dec_bits = 5; + break; + case 'u': + out_coding = AUDIO_ENCODING_ULAW; + out_size = sizeof (char); + break; + case 'a': + out_coding = AUDIO_ENCODING_ALAW; + out_size = sizeof (char); + break; + case 'l': + out_coding = AUDIO_ENCODING_LINEAR; + out_size = sizeof (short); + break; + default: +fprintf(stderr, "CCITT ADPCM Decoder -- usage:\n"); +fprintf(stderr, "\tdecode [-3|4|5] [-a|u|l] < infile > outfile\n"); +fprintf(stderr, "where:\n"); +fprintf(stderr, "\t-3\tProcess G.723 24kbps (3-bit) input data\n"); +fprintf(stderr, "\t-4\tProcess G.721 32kbps (4-bit) input data [default]\n"); +fprintf(stderr, "\t-5\tProcess G.723 40kbps (5-bit) input data\n"); +fprintf(stderr, "\t-a\tGenerate 8-bit A-law data\n"); +fprintf(stderr, "\t-u\tGenerate 8-bit u-law data [default]\n"); +fprintf(stderr, "\t-l\tGenerate 16-bit linear PCM data\n"); + exit(1); + } + argc--; + argv++; + } + + /* Read and unpack input codes and process them */ + while (unpack_input(&code, dec_bits) >= 0) { + sample = (*dec_routine)(code, out_coding, &state); + if (out_size == 2) { + fwrite(&sample, out_size, 1, stdout); + } else { + code = (unsigned char)sample; + fwrite(&code, out_size, 1, stdout); + } + } + fclose(stdout); +} diff --git a/gnuradio-core/src/lib/g72x/encode.c b/gnuradio-core/src/lib/g72x/encode.c new file mode 100644 index 00000000..e7448286 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/encode.c @@ -0,0 +1,119 @@ +/* + * encode.c + * + * CCITT ADPCM encoder + * + * Usage : encode [-3|4|5] [-a|u|l] < infile > outfile + */ +#include +#include "g72x.h" + + +/* + * Pack output codes into bytes and write them to stdout. + * Returns 1 if there is residual output, else returns 0. + */ +int +pack_output( + unsigned code, + int bits) +{ + static unsigned int out_buffer = 0; + static int out_bits = 0; + unsigned char out_byte; + + out_buffer |= (code << out_bits); + out_bits += bits; + if (out_bits >= 8) { + out_byte = out_buffer & 0xff; + out_bits -= 8; + out_buffer >>= 8; + fwrite(&out_byte, sizeof (char), 1, stdout); + } + return (out_bits > 0); +} + + +main( + int argc, + char **argv) +{ + struct g72x_state state; + unsigned char sample_char; + short sample_short; + unsigned char code; + int resid; + int in_coding; + int in_size; + unsigned *in_buf; + int (*enc_routine)(); + int enc_bits; + + g72x_init_state(&state); + + /* Set defaults to u-law input, G.721 output */ + in_coding = AUDIO_ENCODING_ULAW; + in_size = sizeof (char); + in_buf = (unsigned *)&sample_char; + enc_routine = g721_encoder; + enc_bits = 4; + + /* Process encoding argument, if any */ + while ((argc > 1) && (argv[1][0] == '-')) { + switch (argv[1][1]) { + case '3': + enc_routine = g723_24_encoder; + enc_bits = 3; + break; + case '4': + enc_routine = g721_encoder; + enc_bits = 4; + break; + case '5': + enc_routine = g723_40_encoder; + enc_bits = 5; + break; + case 'u': + in_coding = AUDIO_ENCODING_ULAW; + in_size = sizeof (char); + in_buf = (unsigned *)&sample_char; + break; + case 'a': + in_coding = AUDIO_ENCODING_ALAW; + in_size = sizeof (char); + in_buf = (unsigned *)&sample_char; + break; + case 'l': + in_coding = AUDIO_ENCODING_LINEAR; + in_size = sizeof (short); + in_buf = (unsigned *)&sample_short; + break; + default: +fprintf(stderr, "CCITT ADPCM Encoder -- usage:\n"); +fprintf(stderr, "\tencode [-3|4|5] [-a|u|l] < infile > outfile\n"); +fprintf(stderr, "where:\n"); +fprintf(stderr, "\t-3\tGenerate G.723 24kbps (3-bit) data\n"); +fprintf(stderr, "\t-4\tGenerate G.721 32kbps (4-bit) data [default]\n"); +fprintf(stderr, "\t-5\tGenerate G.723 40kbps (5-bit) data\n"); +fprintf(stderr, "\t-a\tProcess 8-bit A-law input data\n"); +fprintf(stderr, "\t-u\tProcess 8-bit u-law input data [default]\n"); +fprintf(stderr, "\t-l\tProcess 16-bit linear PCM input data\n"); + exit(1); + } + argc--; + argv++; + } + + /* Read input file and process */ + while (fread(in_buf, in_size, 1, stdin) == 1) { + code = (*enc_routine)(in_size == 2 ? sample_short : sample_char, + in_coding, &state); + resid = pack_output(code, enc_bits); + } + + /* Write zero codes until all residual codes are written out */ + while (resid) { + resid = pack_output(0, enc_bits); + } + fclose(stdout); +} diff --git a/gnuradio-core/src/lib/g72x/g711.c b/gnuradio-core/src/lib/g72x/g711.c new file mode 100644 index 00000000..d4d60a5c --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g711.c @@ -0,0 +1,283 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g711.c + * + * u-law, A-law and linear PCM conversions. + */ +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; + +/* copy from CCITT G.711 specifications */ +unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; + +unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +static int +search( + int val, + short *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); +} + +/* + * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law + * + * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char +linear2alaw( + int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char aval; + + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 8; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_end, 8); + + /* Combine the sign, segment, and quantization bits. */ + + if (seg >= 8) /* out of range, return maximum value. */ + return (0x7F ^ mask); + else { + aval = seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 4) & QUANT_MASK; + else + aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; + return (aval ^ mask); + } +} + +/* + * alaw2linear() - Convert an A-law value to 16-bit linear PCM + * + */ +int +alaw2linear( + unsigned char a_val) +{ + int t; + int seg; + + a_val ^= 0x55; + + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); +} + +#define BIAS (0x84) /* Bias for linear code. */ + +/* + * linear2ulaw() - Convert a linear PCM value to u-law + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char +linear2ulaw( + int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char uval; + + /* Get the sign and the magnitude of the value. */ + if (pcm_val < 0) { + pcm_val = BIAS - pcm_val; + mask = 0x7F; + } else { + pcm_val += BIAS; + mask = 0xFF; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_end, 8); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (0x7F ^ mask); + else { + uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); + return (uval ^ mask); + } + +} + +/* + * ulaw2linear() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +int +ulaw2linear( + unsigned char u_val) +{ + int t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); +} + +/* A-law to u-law conversion */ +unsigned char +alaw2ulaw( + unsigned char aval) +{ + aval &= 0xff; + return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); +} + +/* u-law to A-law conversion */ +unsigned char +ulaw2alaw( + unsigned char uval) +{ + uval &= 0xff; + return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (0x55 ^ (_u2a[0x7F ^ uval] - 1))); +} diff --git a/gnuradio-core/src/lib/g72x/g721.c b/gnuradio-core/src/lib/g72x/g721.c new file mode 100644 index 00000000..445f177e --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g721.c @@ -0,0 +1,173 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g721.c + * + * Description: + * + * g721_encoder(), g721_decoder() + * + * These routines comprise an implementation of the CCITT G.721 ADPCM + * coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which + * take advantage of work station attributes, such as hardware 2's + * complement arithmetic and large memory. Specifically, certain time + * consuming operations such as multiplications are replaced + * with lookup tables and software 2's complement operations are + * replaced with hardware 2's complement. + * + * The deviation from the bit level specification (lookup tables) + * preserves the bit level performance specifications. + * + * As outlined in the G.721 Recommendation, the algorithm is broken + * down into modules. Each section of code below is preceded by + * the name of the module which it is implementing. + * + */ +#include "g72x.h" + +static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; +/* + * Maps G.721 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, -2048}; + +/* Maps G.721 code word to log of scale factor multiplier. */ +static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, + 1122, 355, 198, 112, 64, 41, 18, -12}; +/* + * Maps G.721 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, + 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; + +/* + * g721_encoder() + * + * Encodes the input vale of linear PCM, A-law or u-law data sl and returns + * the resulting code. -1 is returned for unknown input coding value. + */ +int +g721_encoder( + int sl, + int in_coding, + struct g72x_state *state_ptr) +{ + short sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short sr; /* ADDB */ + short y; /* MIX */ + short dqsez; /* ADDC */ + short dq, i; + + switch (in_coding) { /* linearize input sample to 14-bit PCM */ + case AUDIO_ENCODING_ALAW: + sl = alaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_ULAW: + sl = ulaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_LINEAR: + sl >>= 2; /* 14-bit dynamic range */ + break; + default: + return (-1); + } + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ + + d = sl - se; /* estimation difference */ + + /* quantize the prediction difference */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */ + + dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g721_decoder() + * + * Description: + * + * Decodes a 4-bit code of G.721 encoded data of i and + * returns the resulting linear PCM, A-law or u-law value. + * return -1 for unknown out_coding value. + */ +int +g721_decoder( + int i, + int out_coding, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x0f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* dynamic quantizer step size */ + + dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + switch (out_coding) { + case AUDIO_ENCODING_ALAW: + return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721)); + case AUDIO_ENCODING_ULAW: + return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721)); + case AUDIO_ENCODING_LINEAR: + return (sr << 2); /* sr was 14-bit dynamic range */ + default: + return (-1); + } +} diff --git a/gnuradio-core/src/lib/g72x/g723_24.c b/gnuradio-core/src/lib/g72x/g723_24.c new file mode 100644 index 00000000..452f4dae --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g723_24.c @@ -0,0 +1,158 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g723_24.c + * + * Description: + * + * g723_24_encoder(), g723_24_decoder() + * + * These routines comprise an implementation of the CCITT G.723 24 Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which take advantage + * of workstation attributes, such as hardware 2's complement arithmetic. + * + */ +#include "g72x.h" + +/* + * Maps G.723_24 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048}; + +/* Maps G.723_24 code word to log of scale factor multiplier. */ +static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128}; + +/* + * Maps G.723_24 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; + +static short qtab_723_24[3] = {8, 218, 331}; + +/* + * g723_24_encoder() + * + * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. + * Returns -1 if invalid input coding value. + */ +int +g723_24_encoder( + int sl, + int in_coding, + struct g72x_state *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + switch (in_coding) { /* linearize input sample to 14-bit PCM */ + case AUDIO_ENCODING_ALAW: + sl = alaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_ULAW: + sl = ulaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_LINEAR: + sl >>= 2; /* sl of 14-bit dynamic range */ + break; + default: + return (-1); + } + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation diff. */ + + /* quantize prediction difference d */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */ + dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_24_decoder() + * + * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int +g723_24_decoder( + int i, + int out_coding, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x07; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + switch (out_coding) { + case AUDIO_ENCODING_ALAW: + return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24)); + case AUDIO_ENCODING_ULAW: + return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24)); + case AUDIO_ENCODING_LINEAR: + return (sr << 2); /* sr was of 14-bit dynamic range */ + default: + return (-1); + } +} diff --git a/gnuradio-core/src/lib/g72x/g723_40.c b/gnuradio-core/src/lib/g72x/g723_40.c new file mode 100644 index 00000000..4858baf4 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g723_40.c @@ -0,0 +1,178 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g723_40.c + * + * Description: + * + * g723_40_encoder(), g723_40_decoder() + * + * These routines comprise an implementation of the CCITT G.723 40Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which + * take advantage of workstation attributes, such as hardware 2's + * complement arithmetic. + * + * The deviation from the bit level specification (lookup tables), + * preserves the bit level performance specifications. + * + * As outlined in the G.723 Recommendation, the algorithm is broken + * down into modules. Each section of code below is preceded by + * the name of the module which it is implementing. + * + */ +#include "g72x.h" + +/* + * Maps G.723_40 code word to ructeconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318, + 358, 395, 429, 459, 488, 514, 539, 566, + 566, 539, 514, 488, 459, 429, 395, 358, + 318, 274, 224, 169, 104, 28, -66, -2048}; + +/* Maps G.723_40 code word to log of scale factor multiplier. */ +static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200, + 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, + 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, + 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; + +/* + * Maps G.723_40 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200, + 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, + 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, + 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; + +static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339, + 378, 413, 445, 475, 502, 528, 553}; + +/* + * g723_40_encoder() + * + * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens + * the resulting 5-bit CCITT G.723 40Kbps code. + * Returns -1 if the input coding value is invalid. + */ +int +g723_40_encoder( + int sl, + int in_coding, + struct g72x_state *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + switch (in_coding) { /* linearize input sample to 14-bit PCM */ + case AUDIO_ENCODING_ALAW: + sl = alaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_ULAW: + sl = ulaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_LINEAR: + sl >>= 2; /* sl of 14-bit dynamic range */ + break; + default: + return (-1); + } + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation difference */ + + /* quantize prediction difference */ + y = step_size(state_ptr); /* adaptive quantizer step size */ + i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */ + + dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */ + + sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* dqsez = pole prediction diff. */ + + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_40_decoder() + * + * Decodes a 5-bit CCITT G.723 40Kbps code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int +g723_40_decoder( + int i, + int out_coding, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x1f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */ + + sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + switch (out_coding) { + case AUDIO_ENCODING_ALAW: + return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40)); + case AUDIO_ENCODING_ULAW: + return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40)); + case AUDIO_ENCODING_LINEAR: + return (sr << 2); /* sr was of 14-bit dynamic range */ + default: + return (-1); + } +} diff --git a/gnuradio-core/src/lib/g72x/g72x.c b/gnuradio-core/src/lib/g72x/g72x.c new file mode 100644 index 00000000..9a823c75 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g72x.c @@ -0,0 +1,576 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#include +/* + * g72x.c + * + * Common routines for G.721 and G.723 conversions. + */ + +#include "g72x.h" + +static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000}; + +/* + * quan() + * + * quantizes the input val against the table of size short integers. + * It returns i if table[i - 1] <= val < table[i]. + * + * Using linear search for simple coding. + */ +static int +quan( + int val, + short *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) + if (val < *table++) + break; + return (i); +} + +/* + * fmult() + * + * returns the integer product of the 14-bit integer "an" and + * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". + */ +static int +fmult( + int an, + int srn) +{ + short anmag, anexp, anmant; + short wanexp, wanmant; + short retval; + + anmag = (an > 0) ? an : ((-an) & 0x1FFF); + anexp = quan(anmag, power2, 15) - 6; + anmant = (anmag == 0) ? 32 : + (anexp >= 0) ? anmag >> anexp : anmag << -anexp; + wanexp = anexp + ((srn >> 6) & 0xF) - 13; + + wanmant = (anmant * (srn & 077) + 0x30) >> 4; + retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : + (wanmant >> -wanexp); + + return (((an ^ srn) < 0) ? -retval : retval); +} + +/* + * g72x_init_state() + * + * This routine initializes and/or resets the g72x_state structure + * pointed to by 'state_ptr'. + * All the initial state values are specified in the CCITT G.721 document. + */ +void +g72x_init_state( + struct g72x_state *state_ptr) +{ + int cnta; + + state_ptr->yl = 34816; + state_ptr->yu = 544; + state_ptr->dms = 0; + state_ptr->dml = 0; + state_ptr->ap = 0; + for (cnta = 0; cnta < 2; cnta++) { + state_ptr->a[cnta] = 0; + state_ptr->pk[cnta] = 0; + state_ptr->sr[cnta] = 32; + } + for (cnta = 0; cnta < 6; cnta++) { + state_ptr->b[cnta] = 0; + state_ptr->dq[cnta] = 32; + } + state_ptr->td = 0; +} + +/* + * predictor_zero() + * + * computes the estimated signal from 6-zero predictor. + * + */ +int +predictor_zero( + struct g72x_state *state_ptr) +{ + int i; + int sezi; + + sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); + for (i = 1; i < 6; i++) /* ACCUM */ + sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); + return (sezi); +} +/* + * predictor_pole() + * + * computes the estimated signal from 2-pole predictor. + * + */ +int +predictor_pole( + struct g72x_state *state_ptr) +{ + return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + + fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); +} +/* + * step_size() + * + * computes the quantization step size of the adaptive quantizer. + * + */ +int +step_size( + struct g72x_state *state_ptr) +{ + int y; + int dif; + int al; + + if (state_ptr->ap >= 256) + return (state_ptr->yu); + else { + y = state_ptr->yl >> 6; + dif = state_ptr->yu - y; + al = state_ptr->ap >> 2; + if (dif > 0) + y += (dif * al) >> 6; + else if (dif < 0) + y += (dif * al + 0x3F) >> 6; + return (y); + } +} + +/* + * quantize() + * + * Given a raw sample, 'd', of the difference signal and a + * quantization step size scale factor, 'y', this routine returns the + * ADPCM codeword to which that sample gets quantized. The step + * size scale factor division operation is done in the log base 2 domain + * as a subtraction. + */ +int +quantize( + int d, /* Raw difference signal sample */ + int y, /* Step size multiplier */ + short *table, /* quantization table */ + int size) /* table size of short integers */ +{ + short dqm; /* Magnitude of 'd' */ + short exp; /* Integer part of base 2 log of 'd' */ + short mant; /* Fractional part of base 2 log */ + short dl; /* Log of magnitude of 'd' */ + short dln; /* Step size scale factor normalized log */ + int i; + + /* + * LOG + * + * Compute base 2 log of 'd', and store in 'dl'. + */ + dqm = abs(d); + exp = quan(dqm >> 1, power2, 15); + mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */ + dl = (exp << 7) + mant; + + /* + * SUBTB + * + * "Divide" by step size multiplier. + */ + dln = dl - (y >> 2); + + /* + * QUAN + * + * Obtain codword i for 'd'. + */ + i = quan(dln, table, size); + if (d < 0) /* take 1's complement of i */ + return ((size << 1) + 1 - i); + else if (i == 0) /* take 1's complement of 0 */ + return ((size << 1) + 1); /* new in 1988 */ + else + return (i); +} +/* + * reconstruct() + * + * Returns reconstructed difference signal 'dq' obtained from + * codeword 'i' and quantization step size scale factor 'y'. + * Multiplication is performed in log base 2 domain as addition. + */ +int +reconstruct( + int sign, /* 0 for non-negative value */ + int dqln, /* G.72x codeword */ + int y) /* Step size multiplier */ +{ + short dql; /* Log of 'dq' magnitude */ + short dex; /* Integer part of log */ + short dqt; + short dq; /* Reconstructed difference signal sample */ + + dql = dqln + (y >> 2); /* ADDA */ + + if (dql < 0) { + return ((sign) ? -0x8000 : 0); + } else { /* ANTILOG */ + dex = (dql >> 7) & 15; + dqt = 128 + (dql & 127); + dq = (dqt << 7) >> (14 - dex); + return ((sign) ? (dq - 0x8000) : dq); + } +} + + +/* + * update() + * + * updates the state variables for each output code + */ +void +update( + int code_size, /* distinguish 723_40 with others */ + int y, /* quantizer step size */ + int wi, /* scale factor multiplier */ + int fi, /* for long/short term energies */ + int dq, /* quantized prediction difference */ + int sr, /* reconstructed signal */ + int dqsez, /* difference from 2-pole predictor */ + struct g72x_state *state_ptr) /* coder state pointer */ +{ + int cnt; + short mag, exp; /* Adaptive predictor, FLOAT A */ + short a2p = 0; /* LIMC */ + short a1ul; /* UPA1 */ + short pks1; /* UPA2 */ + short fa1; + char tr; /* tone/transition detector */ + short ylint, thr2, dqthr; + short ylfrac, thr1; + short pk0; + + pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ + + mag = dq & 0x7FFF; /* prediction difference magnitude */ + /* TRANS */ + ylint = state_ptr->yl >> 15; /* exponent part of yl */ + ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ + thr1 = (32 + ylfrac) << ylint; /* threshold */ + thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ + dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ + if (state_ptr->td == 0) /* signal supposed voice */ + tr = 0; + else if (mag <= dqthr) /* supposed data, but small mag */ + tr = 0; /* treated as voice */ + else /* signal is data (modem) */ + tr = 1; + + /* + * Quantizer scale factor adaptation. + */ + + /* FUNCTW & FILTD & DELAY */ + /* update non-steady state step size multiplier */ + state_ptr->yu = y + ((wi - y) >> 5); + + /* LIMB */ + if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ + state_ptr->yu = 544; + else if (state_ptr->yu > 5120) + state_ptr->yu = 5120; + + /* FILTE & DELAY */ + /* update steady state step size multiplier */ + state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); + + /* + * Adaptive predictor coefficients. + */ + if (tr == 1) { /* reset a's and b's for modem signal */ + state_ptr->a[0] = 0; + state_ptr->a[1] = 0; + state_ptr->b[0] = 0; + state_ptr->b[1] = 0; + state_ptr->b[2] = 0; + state_ptr->b[3] = 0; + state_ptr->b[4] = 0; + state_ptr->b[5] = 0; + } else { /* update a's and b's */ + pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ + + /* update predictor pole a[1] */ + a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); + if (dqsez != 0) { + fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; + if (fa1 < -8191) /* a2p = function of fa1 */ + a2p -= 0x100; + else if (fa1 > 8191) + a2p += 0xFF; + else + a2p += fa1 >> 5; + + if (pk0 ^ state_ptr->pk[1]) + /* LIMC */ + if (a2p <= -12160) + a2p = -12288; + else if (a2p >= 12416) + a2p = 12288; + else + a2p -= 0x80; + else if (a2p <= -12416) + a2p = -12288; + else if (a2p >= 12160) + a2p = 12288; + else + a2p += 0x80; + } + + /* TRIGB & DELAY */ + state_ptr->a[1] = a2p; + + /* UPA1 */ + /* update predictor pole a[0] */ + state_ptr->a[0] -= state_ptr->a[0] >> 8; + if (dqsez != 0){ + if (pks1 == 0) + state_ptr->a[0] += 192; + else + state_ptr->a[0] -= 192; + } + + /* LIMD */ + a1ul = 15360 - a2p; + if (state_ptr->a[0] < -a1ul) + state_ptr->a[0] = -a1ul; + else if (state_ptr->a[0] > a1ul) + state_ptr->a[0] = a1ul; + + /* UPB : update predictor zeros b[6] */ + for (cnt = 0; cnt < 6; cnt++) { + if (code_size == 5) /* for 40Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; + else /* for G.721 and 24Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; + if (dq & 0x7FFF) { /* XOR */ + if ((dq ^ state_ptr->dq[cnt]) >= 0) + state_ptr->b[cnt] += 128; + else + state_ptr->b[cnt] -= 128; + } + } + } + + for (cnt = 5; cnt > 0; cnt--) + state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; + /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ + if (mag == 0) { + state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; + } else { + exp = quan(mag, power2, 15); + state_ptr->dq[0] = (dq >= 0) ? + (exp << 6) + ((mag << 6) >> exp) : + (exp << 6) + ((mag << 6) >> exp) - 0x400; + } + + state_ptr->sr[1] = state_ptr->sr[0]; + /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ + if (sr == 0) { + state_ptr->sr[0] = 0x20; + } else if (sr > 0) { + exp = quan(sr, power2, 15); + state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp); + } else if (sr > -32768) { + mag = -sr; + exp = quan(mag, power2, 15); + state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400; + } else + state_ptr->sr[0] = 0xFC20; + + /* DELAY A */ + state_ptr->pk[1] = state_ptr->pk[0]; + state_ptr->pk[0] = pk0; + + /* TONE */ + if (tr == 1) /* this sample has been treated as data */ + state_ptr->td = 0; /* next one will be treated as voice */ + else if (a2p < -11776) /* small sample-to-sample correlation */ + state_ptr->td = 1; /* signal may be data */ + else /* signal is voice */ + state_ptr->td = 0; + + /* + * Adaptation speed control. + */ + state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ + state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ + + if (tr == 1) + state_ptr->ap = 256; + else if (y < 1536) /* SUBTC */ + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (state_ptr->td == 1) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= + (state_ptr->dml >> 3)) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else + state_ptr->ap += (-state_ptr->ap) >> 4; +} + +/* + * tandem_adjust(sr, se, y, i, sign) + * + * At the end of ADPCM decoding, it simulates an encoder which may be receiving + * the output of this decoder as a tandem process. If the output of the + * simulated encoder differs from the input to this decoder, the decoder output + * is adjusted by one level of A-law or u-law codes. + * + * Input: + * sr decoder output linear PCM sample, + * se predictor estimate sample, + * y quantizer step size, + * i decoder input code, + * sign sign bit of code i + * + * Return: + * adjusted A-law or u-law compressed sample. + */ +int +tandem_adjust_alaw( + int sr, /* decoder output linear PCM sample */ + int se, /* predictor estimate sample */ + int y, /* quantizer step size */ + int i, /* decoder input code */ + int sign, + short *qtab) +{ + unsigned char sp; /* A-law compressed 8-bit code */ + short dx; /* prediction error */ + char id; /* quantized prediction error */ + int sd; /* adjusted A-law decoded sample value */ + int im; /* biased magnitude of i */ + int imx; /* biased magnitude of id */ + + if (sr <= -32768) + sr = -1; + sp = linear2alaw((sr >> 1) << 3); /* short to A-law compression */ + dx = (alaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ + id = quantize(dx, y, qtab, sign - 1); + + if (id == i) { /* no adjustment on sp */ + return (sp); + } else { /* sp adjustment needed */ + /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ + im = i ^ sign; /* 2's complement to biased unsigned */ + imx = id ^ sign; + + if (imx > im) { /* sp adjusted to next lower value */ + if (sp & 0x80) { + sd = (sp == 0xD5) ? 0x55 : + ((sp ^ 0x55) - 1) ^ 0x55; + } else { + sd = (sp == 0x2A) ? 0x2A : + ((sp ^ 0x55) + 1) ^ 0x55; + } + } else { /* sp adjusted to next higher value */ + if (sp & 0x80) + sd = (sp == 0xAA) ? 0xAA : + ((sp ^ 0x55) + 1) ^ 0x55; + else + sd = (sp == 0x55) ? 0xD5 : + ((sp ^ 0x55) - 1) ^ 0x55; + } + return (sd); + } +} + +int +tandem_adjust_ulaw( + int sr, /* decoder output linear PCM sample */ + int se, /* predictor estimate sample */ + int y, /* quantizer step size */ + int i, /* decoder input code */ + int sign, + short *qtab) +{ + unsigned char sp; /* u-law compressed 8-bit code */ + short dx; /* prediction error */ + char id; /* quantized prediction error */ + int sd; /* adjusted u-law decoded sample value */ + int im; /* biased magnitude of i */ + int imx; /* biased magnitude of id */ + + if (sr <= -32768) + sr = 0; + sp = linear2ulaw(sr << 2); /* short to u-law compression */ + dx = (ulaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ + id = quantize(dx, y, qtab, sign - 1); + if (id == i) { + return (sp); + } else { + /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ + im = i ^ sign; /* 2's complement to biased unsigned */ + imx = id ^ sign; + if (imx > im) { /* sp adjusted to next lower value */ + if (sp & 0x80) + sd = (sp == 0xFF) ? 0x7E : sp + 1; + else + sd = (sp == 0) ? 0 : sp - 1; + + } else { /* sp adjusted to next higher value */ + if (sp & 0x80) + sd = (sp == 0x80) ? 0x80 : sp - 1; + else + sd = (sp == 0x7F) ? 0xFE : sp + 1; + } + return (sd); + } +} + + + + + + + + + + + + diff --git a/gnuradio-core/src/lib/g72x/g72x.h b/gnuradio-core/src/lib/g72x/g72x.h new file mode 100644 index 00000000..33807171 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g72x.h @@ -0,0 +1,156 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g72x.h + * + * Header file for CCITT conversion routines. + * + */ +#ifndef _G72X_H +#define _G72X_H + +#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */ +#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */ +#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */ + +/* + * The following is the definition of the state structure + * used by the G.721/G.723 encoder and decoder to preserve their internal + * state between successive calls. The meanings of the majority + * of the state structure fields are explained in detail in the + * CCITT Recommendation G.721. The field names are essentially indentical + * to variable names in the bit level description of the coding algorithm + * included in this Recommendation. + */ +struct g72x_state { + long yl; /* Locked or steady state step size multiplier. */ + short yu; /* Unlocked or non-steady state step size multiplier. */ + short dms; /* Short term energy estimate. */ + short dml; /* Long term energy estimate. */ + short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ + + short a[2]; /* Coefficients of pole portion of prediction filter. */ + short b[6]; /* Coefficients of zero portion of prediction filter. */ + short pk[2]; /* + * Signs of previous two samples of a partially + * reconstructed signal. + */ + short dq[6]; /* + * Previous 6 samples of the quantized difference + * signal represented in an internal floating point + * format. + */ + short sr[2]; /* + * Previous 2 samples of the quantized difference + * signal represented in an internal floating point + * format. + */ + char td; /* delayed tone detect, new in 1988 version */ +}; + +/* External function definitions. */ + +extern void g72x_init_state(struct g72x_state *); +extern int g721_encoder( + int sample, + int in_coding, + struct g72x_state *state_ptr); +extern int g721_decoder( + int code, + int out_coding, + struct g72x_state *state_ptr); +extern int g723_24_encoder( + int sample, + int in_coding, + struct g72x_state *state_ptr); +extern int g723_24_decoder( + int code, + int out_coding, + struct g72x_state *state_ptr); +extern int g723_40_encoder( + int sample, + int in_coding, + struct g72x_state *state_ptr); +extern int g723_40_decoder( + int code, + int out_coding, + struct g72x_state *state_ptr); + + +extern int +quantize( + int d, + int y, + short *table, + int size); +extern int reconstruct(int,int,int);void + +extern update( + int code_size, + int y, + int wi, + int fi, + int dq, + int sr, + int dqsez, + struct g72x_state *state_ptr); +extern int +tandem_adjust_alaw( + int sr, + int se, + int y, + int i, + int sign, + short *qtab); + +extern int +tandem_adjust_ulaw( + int sr, + int se, + int y, + int i, + int sign, + short *qtab); + +extern unsigned char +linear2alaw( + int pcm_val); + +extern int +alaw2linear( + unsigned char a_val); + +extern unsigned char +linear2ulaw(int pcm_val); + +extern int ulaw2linear( unsigned char u_val); + +extern int predictor_zero(struct g72x_state *state_ptr); + +extern int predictor_pole( struct g72x_state *state_ptr); +extern int step_size( struct g72x_state *state_ptr); +#endif /* !_G72X_H */ diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am new file mode 100644 index 00000000..a240cc91 --- /dev/null +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -0,0 +1,440 @@ +# +# Copyright 2001,2002,2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +noinst_LTLIBRARIES = libgeneral.la libgeneral-qa.la + +# ---------------------------------------------------------------- +# these scripts generate code + +CODE_GENERATOR = \ + generate_all.py \ + generate_common.py \ + gr_add_XX.cc.t \ + gr_add_XX.h.t \ + gr_add_XX.i.t \ + gr_add_const_XX.cc.t \ + gr_add_const_XX.h.t \ + gr_add_const_XX.i.t \ + gr_chunks_to_symbols_XX.cc.t \ + gr_chunks_to_symbols_XX.h.t \ + gr_chunks_to_symbols_XX.i.t \ + gr_divide_XX.cc.t \ + gr_divide_XX.h.t \ + gr_divide_XX.i.t \ + gr_multiply_XX.cc.t \ + gr_multiply_XX.h.t \ + gr_multiply_XX.i.t \ + gr_multiply_const_XX.cc.t \ + gr_multiply_const_XX.h.t \ + gr_multiply_const_XX.i.t \ + gr_mute_XX.cc.t \ + gr_mute_XX.h.t \ + gr_mute_XX.i.t \ + gr_noise_source_X.cc.t \ + gr_noise_source_X.h.t \ + gr_noise_source_X.i.t \ + gr_packed_to_unpacked_XX.cc.t \ + gr_packed_to_unpacked_XX.h.t \ + gr_packed_to_unpacked_XX.i.t \ + gr_sig_source_X.cc.t \ + gr_sig_source_X.h.t \ + gr_sig_source_X.i.t \ + gr_sub_XX.cc.t \ + gr_sub_XX.h.t \ + gr_sub_XX.i.t \ + gr_unpacked_to_packed_XX.cc.t \ + gr_unpacked_to_packed_XX.h.t \ + gr_unpacked_to_packed_XX.i.t \ + gr_vector_source_X.cc.t \ + gr_vector_source_X.h.t \ + gr_vector_source_X.i.t \ + gr_vector_sink_X.cc.t \ + gr_vector_sink_X.h.t \ + gr_vector_sink_X.i.t + +# include $(srcdir)/Makefile.gen +include Makefile.gen + + +$(GENERATED_H) $(GENERATED_I) $(GENERATED_CC): $(CODE_GENERATOR) + PYTHONPATH=$(top_srcdir)/gnuradio-core/src/python srcdir=$(srcdir) $(srcdir)/generate_all.py + + +BUILT_SOURCES = $(GENERATED_H) $(GENERATED_I) $(GENERATED_CC) + +# ---------------------------------------------------------------- + +EXTRA_DIST = \ + $(CODE_GENERATOR) \ + gen_sine_table.py \ + gr_prefix.cc.in + +libgeneral_la_SOURCES = \ + $(GENERATED_CC) \ + gr_agc_cc.cc \ + gr_agc_ff.cc \ + gr_align_on_samplenumbers_ss.cc \ + gr_binary_slicer_fb.cc \ + gr_bytes_to_syms.cc \ + gr_char_to_float.cc \ + gr_check_counting_s.cc \ + gr_check_lfsr_32k_s.cc \ + gr_circular_file.cc \ + gr_clock_recovery_mm_cc.cc \ + gr_clock_recovery_mm_ff.cc \ + gr_complex_to_interleaved_short.cc \ + gr_complex_to_xxx.cc \ + gr_conjugate_cc.cc \ + gr_constellation_decoder_cb.cc \ + gr_correlate_access_code_bb.cc \ + gr_costas_loop_cc.cc \ + gr_count_bits.cc \ + gr_crc32.cc \ + gr_ctcss_squelch_ff.cc \ + gr_dd_mpsk_sync_cc.cc \ + gr_deinterleave.cc \ + gr_diff_decoder_bb.cc \ + gr_diff_encoder_bb.cc \ + gr_diff_phasor_cc.cc \ + gr_fake_channel_coder_pp.cc \ + gr_fast_atan2f.cc \ + gr_feval.cc \ + gr_fft_vcc.cc \ + gr_fft_vfc.cc \ + gr_firdes.cc \ + gr_float_to_char.cc \ + gr_float_to_complex.cc \ + gr_float_to_short.cc \ + gr_float_to_uchar.cc \ + gr_frequency_modulator_fc.cc \ + gr_fxpt.cc \ + gr_framer_sink_1.cc \ + gr_head.cc \ + gr_interleave.cc \ + gr_interleaved_short_to_complex.cc \ + gr_keep_one_in_n.cc \ + gr_kludge_copy.cc \ + gr_lfsr_32k_source_s.cc \ + gr_lms_dfe_cc.cc \ + gr_lms_dfe_ff.cc \ + gr_map_bb.cc \ + gr_math.cc \ + gr_misc.cc \ + gr_nlog10_ff.cc \ + gr_nop.cc \ + gr_null_sink.cc \ + gr_null_source.cc \ + gr_pa_2x2_phase_combiner.cc \ + gr_packet_sink.cc \ + gr_phase_modulator_fc.cc \ + gr_pll_carriertracking_cc.cc \ + gr_pll_freqdet_cf.cc \ + gr_pll_refout_cc.cc \ + gr_prefix.cc \ + gr_prefs.cc \ + gr_probe_avg_mag_sqrd_c.cc \ + gr_probe_avg_mag_sqrd_f.cc \ + gr_probe_signal_f.cc \ + gr_pwr_squelch_cc.cc \ + gr_pwr_squelch_ff.cc \ + gr_quadrature_demod_cf.cc \ + gr_random.cc \ + gr_remez.cc \ + gr_reverse.cc \ + gr_rms_cf.cc \ + gr_rms_ff.cc \ + gr_short_to_float.cc \ + gr_simple_correlator.cc \ + gr_simple_framer.cc \ + gr_simple_squelch_cc.cc \ + gr_skiphead.cc \ + gr_squelch_base_cc.cc \ + gr_squelch_base_ff.cc \ + gr_stream_to_streams.cc \ + gr_stream_to_vector.cc \ + gr_streams_to_stream.cc \ + gr_streams_to_vector.cc \ + gr_sync_block.cc \ + gr_sync_decimator.cc \ + gr_sync_interpolator.cc \ + gr_test.cc \ + gr_threshold_ff.cc \ + gr_throttle.cc \ + gr_uchar_to_float.cc \ + gr_vco_f.cc \ + gr_vector_to_stream.cc \ + gr_vector_to_streams.cc \ + gri_add_const_ss_generic.cc \ + gri_char_to_float.cc \ + gri_debugger_hook.cc \ + gri_fft.cc \ + gri_float_to_char.cc \ + gri_float_to_short.cc \ + gri_float_to_uchar.cc \ + gri_interleaved_short_to_complex.cc \ + gri_short_to_float.cc \ + gri_uchar_to_float.cc \ + malloc16.c \ + gr_unpack_k_bits_bb.cc + +libgeneral_qa_la_SOURCES = \ + qa_general.cc \ + qa_gr_circular_file.cc \ + qa_gr_firdes.cc \ + qa_gr_fxpt.cc \ + qa_gr_fxpt_nco.cc \ + qa_gr_fxpt_vco.cc + + + +grinclude_HEADERS = \ + $(GENERATED_H) \ + gr_agc_cc.h \ + gr_agc_ff.h \ + gr_align_on_samplenumbers_ss.h \ + gr_binary_slicer_fb.h \ + gr_bytes_to_syms.h \ + gr_char_to_float.h \ + gr_check_counting_s.h \ + gr_check_lfsr_32k_s.h \ + gr_circular_file.h \ + gr_clock_recovery_mm_cc.h \ + gr_clock_recovery_mm_ff.h \ + gr_complex_to_interleaved_short.h \ + gr_complex_to_xxx.h \ + gr_conjugate_cc.h \ + gr_constellation_decoder_cb.h \ + gr_correlate_access_code_bb.h \ + gr_costas_loop_cc.h \ + gr_count_bits.h \ + gr_crc32.h \ + gr_ctcss_squelch_ff.h \ + gr_dd_mpsk_sync_cc.h \ + gr_diff_decoder_bb.h \ + gr_diff_encoder_bb.h \ + gr_deinterleave.h \ + gr_diff_phasor_cc.h \ + gr_endianness.h \ + gr_expj.h \ + gr_fake_channel_coder_pp.h \ + gr_feval.h \ + gr_fft_vcc.h \ + gr_fft_vfc.h \ + gr_firdes.h \ + gr_float_to_char.h \ + gr_float_to_complex.h \ + gr_float_to_short.h \ + gr_float_to_uchar.h \ + gr_framer_sink_1.h \ + gr_frequency_modulator_fc.h \ + gr_fxpt.h \ + gr_fxpt_nco.h \ + gr_fxpt_vco.h \ + gr_head.h \ + gr_interleave.h \ + gr_interleaved_short_to_complex.h \ + gr_keep_one_in_n.h \ + gr_kludge_copy.h \ + gr_lfsr_32k_source_s.h \ + gr_lms_dfe_cc.h \ + gr_lms_dfe_ff.h \ + gr_log2_const.h \ + gr_map_bb.h \ + gr_math.h \ + gr_misc.h \ + gr_nco.h \ + gr_nlog10_ff.h \ + gr_noise_type.h \ + gr_nop.h \ + gr_null_sink.h \ + gr_null_source.h \ + gr_pa_2x2_phase_combiner.h \ + gr_packet_sink.h \ + gr_phase_modulator_fc.h \ + gr_pll_carriertracking_cc.h \ + gr_pll_freqdet_cf.h \ + gr_pll_refout_cc.h \ + gr_prefix.h \ + gr_prefs.h \ + gr_probe_avg_mag_sqrd_c.h \ + gr_probe_avg_mag_sqrd_f.h \ + gr_probe_signal_f.h \ + gr_pwr_squelch_cc.h \ + gr_pwr_squelch_ff.h \ + gr_quadrature_demod_cf.h \ + gr_random.h \ + gr_remez.h \ + gr_reverse.h \ + gr_rms_cf.h \ + gr_rms_ff.h \ + gr_short_to_float.h \ + gr_sig_source_waveform.h \ + gr_simple_correlator.h \ + gr_simple_framer.h \ + gr_simple_framer_sync.h \ + gr_simple_squelch_cc.h \ + gr_skiphead.h \ + gr_squelch_base_cc.h \ + gr_squelch_base_ff.h \ + gr_stream_to_streams.h \ + gr_stream_to_vector.h \ + gr_streams_to_stream.h \ + gr_streams_to_vector.h \ + gr_sync_block.h \ + gr_sync_decimator.h \ + gr_sync_interpolator.h \ + gr_test_types.h \ + gr_test.h \ + gr_threshold_ff.h \ + gr_throttle.h \ + gr_uchar_to_float.h \ + gr_vco.h \ + gr_vco_f.h \ + gr_vector_to_stream.h \ + gr_vector_to_streams.h \ + gri_add_const_ss.h \ + gri_agc.h \ + gri_agc_cc.h \ + gri_char_to_float.h \ + gri_debugger_hook.h \ + gri_fft.h \ + gri_float_to_char.h \ + gri_float_to_short.h \ + gri_float_to_uchar.h \ + gri_interleaved_short_to_complex.h \ + gri_lfsr_15_1_0.h \ + gri_lfsr_32k.h \ + gri_short_to_float.h \ + gri_uchar_to_float.h \ + malloc16.h \ + random.h \ + gr_unpack_k_bits_bb.h + + +noinst_HEADERS = \ + qa_general.h \ + qa_gr_circular_file.h \ + qa_gr_firdes.h \ + qa_gr_fxpt.h \ + qa_gr_fxpt_nco.h \ + qa_gr_fxpt_vco.h \ + sine_table.h + +swiginclude_HEADERS = \ + $(GENERATED_I) \ + general.i \ + general_generated.i \ + gr_agc_cc.i \ + gr_agc_ff.i \ + gr_align_on_samplenumbers_ss.i \ + gr_binary_slicer_fb.i \ + gr_bytes_to_syms.i \ + gr_char_to_float.i \ + gr_check_counting_s.i \ + gr_check_lfsr_32k_s.i \ + gr_clock_recovery_mm_cc.i \ + gr_clock_recovery_mm_ff.i \ + gr_complex_to_interleaved_short.i \ + gr_complex_to_xxx.i \ + gr_conjugate_cc.i \ + gr_constellation_decoder_cb.i \ + gr_correlate_access_code_bb.i \ + gr_costas_loop_cc.i \ + gr_crc32.i \ + gr_ctcss_squelch_ff.i \ + gr_dd_mpsk_sync_cc.i \ + gr_diff_decoder_bb.i \ + gr_diff_encoder_bb.i \ + gr_diff_phasor_cc.i \ + gr_deinterleave.i \ + gr_endianness.i \ + gr_fake_channel_coder_pp.i \ + gr_feval.i \ + gr_fft_vcc.i \ + gr_fft_vfc.i \ + gr_firdes.i \ + gr_float_to_char.i \ + gr_float_to_complex.i \ + gr_float_to_short.i \ + gr_float_to_uchar.i \ + gr_frequency_modulator_fc.i \ + gr_framer_sink_1.i \ + gr_head.i \ + gr_interleave.i \ + gr_interleaved_short_to_complex.i \ + gr_keep_one_in_n.i \ + gr_kludge_copy.i \ + gr_lfsr_32k_source_s.i \ + gr_lms_dfe_cc.i \ + gr_lms_dfe_ff.i \ + gr_map_bb.i \ + gr_nlog10_ff.i \ + gr_nop.i \ + gr_null_sink.i \ + gr_null_source.i \ + gr_pa_2x2_phase_combiner.i \ + gr_packet_sink.i \ + gr_phase_modulator_fc.i \ + gr_pll_carriertracking_cc.i \ + gr_pll_freqdet_cf.i \ + gr_pll_refout_cc.i \ + gr_prefix.i \ + gr_prefs.i \ + gr_probe_avg_mag_sqrd_c.i \ + gr_probe_avg_mag_sqrd_f.i \ + gr_probe_signal_f.i \ + gr_pwr_squelch_cc.i \ + gr_pwr_squelch_ff.i \ + gr_quadrature_demod_cf.i \ + gr_remez.i \ + gr_rms_cf.i \ + gr_rms_ff.i \ + gr_short_to_float.i \ + gr_simple_correlator.i \ + gr_simple_framer.i \ + gr_simple_squelch_cc.i \ + gr_skiphead.i \ + gr_squelch_base_cc.i \ + gr_squelch_base_ff.i \ + gr_stream_to_streams.i \ + gr_stream_to_vector.i \ + gr_streams_to_stream.i \ + gr_streams_to_vector.i \ + gr_sync_block.i \ + gr_sync_decimator.i \ + gr_sync_interpolator.i \ + gr_test.i \ + gr_threshold_ff.i \ + gr_throttle.i \ + gr_uchar_to_float.i \ + gr_vco_f.i \ + gr_vector_to_stream.i \ + gr_vector_to_streams.i \ + gri_agc.i \ + gri_agc_cc.i \ + gr_unpack_k_bits_bb.i + + +CLEANFILES = $(BUILT_SOURCES) *.pyc diff --git a/gnuradio-core/src/lib/general/Makefile.gen b/gnuradio-core/src/lib/general/Makefile.gen new file mode 100644 index 00000000..f0c477e3 --- /dev/null +++ b/gnuradio-core/src/lib/general/Makefile.gen @@ -0,0 +1,234 @@ +# +# This file is machine generated. All edits will be overwritten +# +GENERATED_H = \ + gr_add_cc.h \ + gr_add_const_cc.h \ + gr_add_const_ff.h \ + gr_add_const_ii.h \ + gr_add_const_sf.h \ + gr_add_const_ss.h \ + gr_add_const_vcc.h \ + gr_add_const_vff.h \ + gr_add_const_vii.h \ + gr_add_const_vss.h \ + gr_add_ff.h \ + gr_add_ii.h \ + gr_add_ss.h \ + gr_add_vcc.h \ + gr_add_vff.h \ + gr_add_vii.h \ + gr_add_vss.h \ + gr_chunks_to_symbols_bc.h \ + gr_chunks_to_symbols_bf.h \ + gr_chunks_to_symbols_ic.h \ + gr_chunks_to_symbols_if.h \ + gr_chunks_to_symbols_sc.h \ + gr_chunks_to_symbols_sf.h \ + gr_divide_cc.h \ + gr_divide_ff.h \ + gr_divide_ii.h \ + gr_divide_ss.h \ + gr_multiply_cc.h \ + gr_multiply_const_cc.h \ + gr_multiply_const_ff.h \ + gr_multiply_const_ii.h \ + gr_multiply_const_ss.h \ + gr_multiply_const_vcc.h \ + gr_multiply_const_vff.h \ + gr_multiply_const_vii.h \ + gr_multiply_const_vss.h \ + gr_multiply_ff.h \ + gr_multiply_ii.h \ + gr_multiply_ss.h \ + gr_multiply_vcc.h \ + gr_multiply_vff.h \ + gr_multiply_vii.h \ + gr_multiply_vss.h \ + gr_mute_cc.h \ + gr_mute_ff.h \ + gr_mute_ii.h \ + gr_mute_ss.h \ + gr_noise_source_c.h \ + gr_noise_source_f.h \ + gr_noise_source_i.h \ + gr_noise_source_s.h \ + gr_packed_to_unpacked_bb.h \ + gr_packed_to_unpacked_ii.h \ + gr_packed_to_unpacked_ss.h \ + gr_sig_source_c.h \ + gr_sig_source_f.h \ + gr_sig_source_i.h \ + gr_sig_source_s.h \ + gr_sub_cc.h \ + gr_sub_ff.h \ + gr_sub_ii.h \ + gr_sub_ss.h \ + gr_unpacked_to_packed_bb.h \ + gr_unpacked_to_packed_ii.h \ + gr_unpacked_to_packed_ss.h \ + gr_vector_sink_b.h \ + gr_vector_sink_c.h \ + gr_vector_sink_f.h \ + gr_vector_sink_i.h \ + gr_vector_sink_s.h \ + gr_vector_source_b.h \ + gr_vector_source_c.h \ + gr_vector_source_f.h \ + gr_vector_source_i.h \ + gr_vector_source_s.h + +GENERATED_I = \ + gr_add_cc.i \ + gr_add_const_cc.i \ + gr_add_const_ff.i \ + gr_add_const_ii.i \ + gr_add_const_sf.i \ + gr_add_const_ss.i \ + gr_add_const_vcc.i \ + gr_add_const_vff.i \ + gr_add_const_vii.i \ + gr_add_const_vss.i \ + gr_add_ff.i \ + gr_add_ii.i \ + gr_add_ss.i \ + gr_add_vcc.i \ + gr_add_vff.i \ + gr_add_vii.i \ + gr_add_vss.i \ + gr_chunks_to_symbols_bc.i \ + gr_chunks_to_symbols_bf.i \ + gr_chunks_to_symbols_ic.i \ + gr_chunks_to_symbols_if.i \ + gr_chunks_to_symbols_sc.i \ + gr_chunks_to_symbols_sf.i \ + gr_divide_cc.i \ + gr_divide_ff.i \ + gr_divide_ii.i \ + gr_divide_ss.i \ + gr_multiply_cc.i \ + gr_multiply_const_cc.i \ + gr_multiply_const_ff.i \ + gr_multiply_const_ii.i \ + gr_multiply_const_ss.i \ + gr_multiply_const_vcc.i \ + gr_multiply_const_vff.i \ + gr_multiply_const_vii.i \ + gr_multiply_const_vss.i \ + gr_multiply_ff.i \ + gr_multiply_ii.i \ + gr_multiply_ss.i \ + gr_multiply_vcc.i \ + gr_multiply_vff.i \ + gr_multiply_vii.i \ + gr_multiply_vss.i \ + gr_mute_cc.i \ + gr_mute_ff.i \ + gr_mute_ii.i \ + gr_mute_ss.i \ + gr_noise_source_c.i \ + gr_noise_source_f.i \ + gr_noise_source_i.i \ + gr_noise_source_s.i \ + gr_packed_to_unpacked_bb.i \ + gr_packed_to_unpacked_ii.i \ + gr_packed_to_unpacked_ss.i \ + gr_sig_source_c.i \ + gr_sig_source_f.i \ + gr_sig_source_i.i \ + gr_sig_source_s.i \ + gr_sub_cc.i \ + gr_sub_ff.i \ + gr_sub_ii.i \ + gr_sub_ss.i \ + gr_unpacked_to_packed_bb.i \ + gr_unpacked_to_packed_ii.i \ + gr_unpacked_to_packed_ss.i \ + gr_vector_sink_b.i \ + gr_vector_sink_c.i \ + gr_vector_sink_f.i \ + gr_vector_sink_i.i \ + gr_vector_sink_s.i \ + gr_vector_source_b.i \ + gr_vector_source_c.i \ + gr_vector_source_f.i \ + gr_vector_source_i.i \ + gr_vector_source_s.i + +GENERATED_CC = \ + gr_add_cc.cc \ + gr_add_const_cc.cc \ + gr_add_const_ff.cc \ + gr_add_const_ii.cc \ + gr_add_const_sf.cc \ + gr_add_const_ss.cc \ + gr_add_const_vcc.cc \ + gr_add_const_vff.cc \ + gr_add_const_vii.cc \ + gr_add_const_vss.cc \ + gr_add_ff.cc \ + gr_add_ii.cc \ + gr_add_ss.cc \ + gr_add_vcc.cc \ + gr_add_vff.cc \ + gr_add_vii.cc \ + gr_add_vss.cc \ + gr_chunks_to_symbols_bc.cc \ + gr_chunks_to_symbols_bf.cc \ + gr_chunks_to_symbols_ic.cc \ + gr_chunks_to_symbols_if.cc \ + gr_chunks_to_symbols_sc.cc \ + gr_chunks_to_symbols_sf.cc \ + gr_divide_cc.cc \ + gr_divide_ff.cc \ + gr_divide_ii.cc \ + gr_divide_ss.cc \ + gr_multiply_cc.cc \ + gr_multiply_const_cc.cc \ + gr_multiply_const_ff.cc \ + gr_multiply_const_ii.cc \ + gr_multiply_const_ss.cc \ + gr_multiply_const_vcc.cc \ + gr_multiply_const_vff.cc \ + gr_multiply_const_vii.cc \ + gr_multiply_const_vss.cc \ + gr_multiply_ff.cc \ + gr_multiply_ii.cc \ + gr_multiply_ss.cc \ + gr_multiply_vcc.cc \ + gr_multiply_vff.cc \ + gr_multiply_vii.cc \ + gr_multiply_vss.cc \ + gr_mute_cc.cc \ + gr_mute_ff.cc \ + gr_mute_ii.cc \ + gr_mute_ss.cc \ + gr_noise_source_c.cc \ + gr_noise_source_f.cc \ + gr_noise_source_i.cc \ + gr_noise_source_s.cc \ + gr_packed_to_unpacked_bb.cc \ + gr_packed_to_unpacked_ii.cc \ + gr_packed_to_unpacked_ss.cc \ + gr_sig_source_c.cc \ + gr_sig_source_f.cc \ + gr_sig_source_i.cc \ + gr_sig_source_s.cc \ + gr_sub_cc.cc \ + gr_sub_ff.cc \ + gr_sub_ii.cc \ + gr_sub_ss.cc \ + gr_unpacked_to_packed_bb.cc \ + gr_unpacked_to_packed_ii.cc \ + gr_unpacked_to_packed_ss.cc \ + gr_vector_sink_b.cc \ + gr_vector_sink_c.cc \ + gr_vector_sink_f.cc \ + gr_vector_sink_i.cc \ + gr_vector_sink_s.cc \ + gr_vector_source_b.cc \ + gr_vector_source_c.cc \ + gr_vector_source_f.cc \ + gr_vector_source_i.cc \ + gr_vector_source_s.cc + diff --git a/gnuradio-core/src/lib/general/README b/gnuradio-core/src/lib/general/README new file mode 100644 index 00000000..26d829f1 --- /dev/null +++ b/gnuradio-core/src/lib/general/README @@ -0,0 +1,98 @@ +Files beginning with Gr* define classes that inherit from VrSigProc. +These are high level signal processing modules that can be glued +together in your signal processing chain. + +All the others are either lower level routines which implement the +functionality of the Gr* modules, but are easier to test (fewer +dependencies), or they are general purpose. + +gr_fir_???.{h,cc}, where ??? are in F, S or C are low level Finite +Impulse Response Filters. These turn out to be where the bulk of the +cycles are burned in many applications. The ??? suffix specifies the +input type, output type and tap type of the arguments. We've +implemented the most frequently used ones. + +[Once upon a time this stuff was done with templates +(gr_fir), but this turned out to be a headache. +The code appeared to trigger a bug in GCC where we were getting +multiple definitions of unrelated stuff when we started subclassing +partially specialized templates. It was also not obvious as to to +what combinations of iType, oType and tapType actually worked. We're +now explicit, and the world is a safer place to live...] + +The top level routines for FIR filtering are: + + GrFIRfilterFFF : Float input, Float output, Float taps + -- general purpose + + GrFIRfilterCCF : Complex input, Complex output, Float taps + -- applying real filter to a complex signal + + GrFIRfilterFCC : Float input, Complex output, Complex taps + -- applying complex filter to float input + + GrFIRfilterSCC : Short input, Complex output, Complex taps + -- applying complex filter to short input. Quantizes complex + coefficients to 16 bits and uses MMX or SSE2 as appropriate + + +The combination of down conversion (frequency translation) and channel +selection (filtering) is performed with: + + GrFreqXlatingFIRfilterSFC : Short input, Float taps, Complex baseband output + -- quantizes complex coefficents to 16 bits and uses MMX or + SSE2 (128-bit MMX) as appropriate [optimization to be done]. + + GrFreqXlatingFIRfilterFFC : Float input, Float taps, Complex baseband output + -- 3dnow or SSE as appropriate. + + +[ The stuff described from here down is used to implement the routines + above. This info is only relevant to those who are hacking the internals ] + + +A bit of indirection is involved in selecting the fastest +implementation for any given platform. The lower level classes +gr_fir_FFF.h, gr_fir_CCF, gr_fir_FCC and gr_fir_SCC have i/o +signatures similar to the high level clases above. These +should be considered the abstract base classes that you +work with. Note that they are not actually abstract (they've got a +default implementation; this might be considered a bug), but they +should not be directly instantiated by user code. + +Instead of directly instantiating a gr_fir_FFF, for example, your code +should actually: + + #include + + // let the system pick the best implementation for you + gr_fir_FFF *filter = gr_fir_util::create_gr_fir_FFF (my_taps); + +Clear? The same for all the other gr_fir_XXX's. + + + +Performance hacking can be done by subclassing the appropriate +base class. For example, on the x86 platform, there are two +additional classes derived from gr_fir_FFF, gr_fir_FFF_sse and +gr_fir_FFF_3dnow. These classes are then made available to the rest +of the system by virtue of being added to gr_fir_sysconfig_x86.cc, +along with any guards (CPUID checks) needed to ensure that only +compatible code is executed on the current hardware. + + +TO DO +------ + +* Move all the machine specific code to a subdirectory, then have +configure symlink to the right directory. This will allow us to build on +any platform without choking. There is generic code for all routines, +only the machine dependent speedup will be lacking. + +* Add an interface to gr_fir_util that will return a vector of all +valid constructors with descriptive names for each i/o signature. +This will allow the test code and benchmarking code to be blissfully +ignorant of what platform they're running on. The actual building of +the vectors should be done bottom up through the gr_fir_sysconfig +hierarchy. + diff --git a/gnuradio-core/src/lib/general/atsc_rrc1x.dat b/gnuradio-core/src/lib/general/atsc_rrc1x.dat new file mode 100644 index 00000000..3466412f --- /dev/null +++ b/gnuradio-core/src/lib/general/atsc_rrc1x.dat @@ -0,0 +1,57 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:ROOT RAISED COSINE 12H + * PASSBAND RIPPLE IN -dB -.0500 + * STOPBAND RIPPLE IN -dB -50.0000 + * SYMBOL RATE .538112E+07 HERTZ + * ROLLOF FACTOR .115200 + * SAMPLING FREQUENCY .107622E+08 HERTZ + * SAMPLING FREQUENCY .107622E+08 HERTZ + */ + .1821269281208515e-02, + -.9323525242507458e-02, + -.8581001311540604e-02, + .2809949219226837e-02, + .9649330750107765e-03, + -.4944681189954281e-02, + .1624439377337694e-02, + .6519509013742209e-02, + -.4803944379091263e-02, + -.8026130497455597e-02, + .8922342676669359e-02, + .9611152112483978e-02, + -.1463735569268465e-01, + -.1107082655653358e-01, + .2262782817706466e-01, + .1240625558421016e-01, + -.3461387194693089e-01, + -.1348070800304413e-01, + .5474480940029025e-01, + .1432673400267959e-01, + -.9872047463431954e-01, + -.1482593175023794e-01, + .3077511447481811e+00, + .5007477863691747e+00, + .3077511447481811e+00, + -.1482593175023794e-01, + -.9872047463431954e-01, + .1432673400267959e-01, + .5474480940029025e-01, + -.1348070800304413e-01, + -.3461387194693089e-01, + .1240625558421016e-01, + .2262782817706466e-01, + -.1107082655653358e-01, + -.1463735569268465e-01, + .9611152112483978e-02, + .8922342676669359e-02, + -.8026130497455597e-02, + -.4803944379091263e-02, + .6519509013742209e-02, + .1624439377337694e-02, + -.4944681189954281e-02, + .9649330750107765e-03, + .2809949219226837e-02, + -.8581001311540604e-02, + -.9323525242507458e-02, + .1821269281208515e-02 diff --git a/gnuradio-core/src/lib/general/atsc_rrc20.dat b/gnuradio-core/src/lib/general/atsc_rrc20.dat new file mode 100644 index 00000000..94445e96 --- /dev/null +++ b/gnuradio-core/src/lib/general/atsc_rrc20.dat @@ -0,0 +1,101 @@ + -.1141865178942680e-01, + .2192483097314835e-01, + -.6814673542976379e-04, + -.5894266534596682e-02, + -.3580642864108086e-02, + .7064016535878182e-03, + .3225978463888168e-02, + .2832664176821709e-02, + .4997388459742069e-03, + -.1796286087483168e-02, + -.2396093215793371e-02, + -.1009003724902868e-02, + .1184449531137943e-02, + .2406611572951078e-02, + .1609810627996922e-02, + -.6790305487811565e-03, + -.2634476870298386e-02, + -.2524725627154112e-02, + -.1492514275014401e-03, + .2789965830743313e-02, + .3848167601972818e-02, + .1755146309733391e-02, + -.2288600429892540e-02, + -.5209952127188444e-02, + -.4314901307225227e-02, + .3885449841618538e-03, + .5747230723500252e-02, + .7460035849362612e-02, + .3387423232197762e-02, + -.4307936877012253e-02, + -.1007711654528976e-01, + -.8849395904690027e-02, + -.1979861408472061e-03, + .1040456583723426e-01, + .1484309835359454e-01, + .8285604882985354e-02, + -.6346960552036762e-02, + -.1915087224915624e-01, + -.1949162455275655e-01, + -.4145141225308180e-02, + .1850909460335970e-01, + .3220130456611514e-01, + .2337836893275380e-01, + -.7863232865929604e-02, + -.4402747144922614e-01, + -.5751598253846169e-01, + -.2598480274900794e-01, + .5246857088059187e-01, + .1544690094888210e+00, + .2405302016995847e+00, + .2741314689628780e+00, + .2405302016995847e+00, + .1544690094888210e+00, + .5246857088059187e-01, + -.2598480274900794e-01, + -.5751598253846169e-01, + -.4402747144922614e-01, + -.7863232865929604e-02, + .2337836893275380e-01, + .3220130456611514e-01, + .1850909460335970e-01, + -.4145141225308180e-02, + -.1949162455275655e-01, + -.1915087224915624e-01, + -.6346960552036762e-02, + .8285604882985354e-02, + .1484309835359454e-01, + .1040456583723426e-01, + -.1979861408472061e-03, + -.8849395904690027e-02, + -.1007711654528976e-01, + -.4307936877012253e-02, + .3387423232197762e-02, + .7460035849362612e-02, + .5747230723500252e-02, + .3885449841618538e-03, + -.4314901307225227e-02, + -.5209952127188444e-02, + -.2288600429892540e-02, + .1755146309733391e-02, + .3848167601972818e-02, + .2789965830743313e-02, + -.1492514275014401e-03, + -.2524725627154112e-02, + -.2634476870298386e-02, + -.6790305487811565e-03, + .1609810627996922e-02, + .2406611572951078e-02, + .1184449531137943e-02, + -.1009003724902868e-02, + -.2396093215793371e-02, + -.1796286087483168e-02, + .4997388459742069e-03, + .2832664176821709e-02, + .3225978463888168e-02, + .7064016535878182e-03, + -.3580642864108086e-02, + -.5894266534596682e-02, + -.6814673542976379e-04, + .2192483097314835e-01, + -.1141865178942680e-01 diff --git a/gnuradio-core/src/lib/general/atsc_rrc2x.dat b/gnuradio-core/src/lib/general/atsc_rrc2x.dat new file mode 100644 index 00000000..ca7812cb --- /dev/null +++ b/gnuradio-core/src/lib/general/atsc_rrc2x.dat @@ -0,0 +1,102 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:ROOT RAISED COSINE 12H + * PASSBAND RIPPLE IN -dB -.0500 + * STOPBAND RIPPLE IN -dB -50.0000 + * SYMBOL RATE .538112E+07 HERTZ + * ROLLOF FACTOR .115200 + * SAMPLING FREQUENCY .215245E+08 HERTZ +*/ + .8186036720871925E-03, + -.1256920862942934E-02, + -.4844595678150654E-02, + -.6055080797523260E-02, + -.4247304052114487E-02, + -.9502284228801727E-03, + .1615938264876604E-02, + .2120061777532101E-02, + .6354246288537979E-03, + -.1464351080358028E-02, + -.2508673351258040E-02, + -.1573510002344847E-02, + .8145328611135483E-03, + .2996938303112984E-02, + .3244197461754084E-02, + .1038576476275921E-02, + -.2401810139417648E-02, + -.4728596191853285E-02, + -.4019895102828741E-02, + -.2215979620814323E-03, + .4481043666601181E-02, + .6867439020425081E-02, + .4793671425431967E-02, + -.1089230179786682E-02, + -.7325290236622095E-02, + -.9580074809491634E-02, + -.5532339215278626E-02, + .3166179172694683E-02, + .1132524851709604E-01, + .1316944882273674E-01, + .6192639470100403E-02, + -.6509334780275822E-02, + -.1730504119768739E-01, + -.1832502009347081E-01, + -.6741075310856104E-02, + .1229691226035357E-01, + .2738198731094599E-01, + .2702147699892521E-01, + .7156732492148876E-02, + -.2432488137856126E-01, + -.4934547096490860E-01, + -.4763523396104574E-01, + -.7410581223666668E-02, + .6681889295578003E-01, + .1538293845951557E+00, + .2236228249967098E+00, + .2502835178747773E+00, + .2236228249967098E+00, + .1538293845951557E+00, + .6681889295578003E-01, + -.7410581223666668E-02, + -.4763523396104574E-01, + -.4934547096490860E-01, + -.2432488137856126E-01, + .7156732492148876E-02, + .2702147699892521E-01, + .2738198731094599E-01, + .1229691226035357E-01, + -.6741075310856104E-02, + -.1832502009347081E-01, + -.1730504119768739E-01, + -.6509334780275822E-02, + .6192639470100403E-02, + .1316944882273674E-01, + .1132524851709604E-01, + .3166179172694683E-02, + -.5532339215278626E-02, + -.9580074809491634E-02, + -.7325290236622095E-02, + -.1089230179786682E-02, + .4793671425431967E-02, + .6867439020425081E-02, + .4481043666601181E-02, + -.2215979620814323E-03, + -.4019895102828741E-02, + -.4728596191853285E-02, + -.2401810139417648E-02, + .1038576476275921E-02, + .3244197461754084E-02, + .2996938303112984E-02, + .8145328611135483E-03, + -.1573510002344847E-02, + -.2508673351258040E-02, + -.1464351080358028E-02, + .6354246288537979E-03, + .2120061777532101E-02, + .1615938264876604E-02, + -.9502284228801727E-03, + -.4247304052114487E-02, + -.6055080797523260E-02, + -.4844595678150654E-02, + -.1256920862942934E-02, + .8186036720871925E-03 diff --git a/gnuradio-core/src/lib/general/gen_sine_table.py b/gnuradio-core/src/lib/general/gen_sine_table.py new file mode 100755 index 00000000..06a5e7c8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gen_sine_table.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +import sys + +def wrap (x): + if x >= 2**31: + return x - 2**32 + return x + +def gen_approx_table (f, nentries, min_x, max_x): + """return a list of nentries containing tuples of the form: + (m, c, abs_error). min_x and max_x specify the domain + of the table. + """ + r = [] + incx = float (max_x - min_x) / nentries + for i in range (nentries): + a = (i * incx) + min_x + b = ((i + 1) * incx) + min_x + m = (f(b)-f(a))/(b-a) + c = (3*a+b)*(f(a)-f(b))/(4*(b-a)) + (f((a+b)/2) + f(a))/2 + abs_error = c+m*a-f(a) + r.append ((m, c, abs_error)) + return r + +def scaled_sine (x): + return math.sin (x * math.pi / 2**31) + +def gen_sine_table (): + nbits = 10 + nentries = 2**nbits + + # min_x = -2**31 + # max_x = 2**31-1 + min_x = 0 + max_x = 2**32-1 + t = gen_approx_table (scaled_sine, nentries, min_x, max_x) + + max_error = 0 + for e in t: + max_error = max (max_error, abs (e[2])) + + # sys.stdout.write ('static const int WORDBITS = 32;\n') + # sys.stdout.write ('static const int NBITS = %d;\n' % (nbits,)) + + sys.stdout.write (' // max_error = %22.15e\n' % (max_error,)) + + # sys.stdout.write ('static const double sine_table[%d][2] = {\n'% (nentries,)) + + for e in t: + sys.stdout.write (' { %22.15e, %22.15e },\n' % (2 * e[0], e[1])) + + # sys.stdout.write ('};\n') + +if __name__ == '__main__': + gen_sine_table () diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i new file mode 100644 index 00000000..3f410a9e --- /dev/null +++ b/gnuradio-core/src/lib/general/general.i @@ -0,0 +1,203 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include "gr_sync_block.i" +%include "gr_sync_decimator.i" +%include "gr_sync_interpolator.i" +%include "gr_nop.i" +%include "gr_null_sink.i" +%include "gr_null_source.i" +%include "gr_head.i" +%include "gr_skiphead.i" +%include "gr_sig_source_waveform.h" +%include "gr_noise_type.h" +%include "gr_quadrature_demod_cf.i" +%include "gr_remez.i" +%include "gr_float_to_complex.i" +%include "gr_check_counting_s.i" +%include "gr_lfsr_32k_source_s.i" +%include "gr_check_lfsr_32k_s.i" +%include "gr_stream_to_vector.i" +%include "gr_vector_to_stream.i" +%include "gr_keep_one_in_n.i" +%include "gr_fft_vcc.i" +%include "gr_fft_vfc.i" +%include "gr_float_to_short.i" +%include "gr_float_to_char.i" +%include "gr_float_to_uchar.i" +%include "gr_short_to_float.i" +%include "gr_char_to_float.i" +%include "gr_uchar_to_float.i" +%include "gr_frequency_modulator_fc.i" +%include "gr_phase_modulator_fc.i" +%include "gr_bytes_to_syms.i" +%include "gr_simple_correlator.i" +%include "gr_simple_framer.i" +%include "gr_align_on_samplenumbers_ss.i" +%include "gr_complex_to_xxx.i" +%include "gr_complex_to_interleaved_short.i" +%include "gr_endianness.i" +%include "gr_interleaved_short_to_complex.i" +%include "gr_firdes.i" +%include "gr_interleave.i" +%include "gr_deinterleave.i" +%include "gr_simple_squelch_cc.i" +%include "gr_agc_ff.i" +%include "gr_agc_cc.i" +%include "gr_rms_cf.i" +%include "gr_rms_ff.i" +%include "gr_nlog10_ff.i" +%include "gr_fake_channel_coder_pp.i" +%include "gr_throttle.i" +%include "gr_stream_to_streams.i" +%include "gr_streams_to_stream.i" +%include "gr_streams_to_vector.i" +%include "gr_vector_to_streams.i" +%include "gr_conjugate_cc.i" +%include "gr_vco_f.i" +%include "gr_crc32.i" +%include "gr_threshold_ff.i" +%include "gr_clock_recovery_mm_ff.i" +%include "gr_clock_recovery_mm_cc.i" +%include "gr_dd_mpsk_sync_cc.i" +%include "gr_packet_sink.i" +%include "gr_lms_dfe_cc.i" +%include "gr_lms_dfe_ff.i" +%include "gr_pll_freqdet_cf.i" +%include "gr_pll_refout_cc.i" +%include "gr_pll_carriertracking_cc.i" +%include "gr_probe_avg_mag_sqrd_c.i" +%include "gr_probe_avg_mag_sqrd_f.i" +%include "gr_probe_signal_f.i" +%include "gr_costas_loop_cc.i" +%include "gr_pa_2x2_phase_combiner.i" +%include "gr_kludge_copy.i" +%include "gr_prefs.i" +%include "gr_prefix.i" +%include "gr_test_types.h" +%include "gr_test.i" +%include "gr_unpack_k_bits_bb.i" +%include "gr_correlate_access_code_bb.i" +%include "gr_diff_phasor_cc.i" +%include "gr_constellation_decoder_cb.i" +%include "gr_binary_slicer_fb.i" +%include "gr_diff_encoder_bb.i" +%include "gr_diff_decoder_bb.i" +%include "gr_framer_sink_1.i" +%include "gr_map_bb.i" +%include "gr_feval.i" +%include "gr_pwr_squelch_cc.i" +%include "gr_pwr_squelch_ff.i" +%include "gr_ctcss_squelch_ff.i" + +%include "general_generated.i" diff --git a/gnuradio-core/src/lib/general/general_generated.i b/gnuradio-core/src/lib/general/general_generated.i new file mode 100644 index 00000000..a41f30a3 --- /dev/null +++ b/gnuradio-core/src/lib/general/general_generated.i @@ -0,0 +1,156 @@ +// +// This file is machine generated. All edits will be overwritten +// +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include diff --git a/gnuradio-core/src/lib/general/generate_all.py b/gnuradio-core/src/lib/general/generate_all.py new file mode 100755 index 00000000..1b33abb9 --- /dev/null +++ b/gnuradio-core/src/lib/general/generate_all.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from build_utils import output_glue + +import generate_common + +def generate_all (): + generate_common.generate () + output_glue ('general') + + +if __name__ == '__main__': + generate_all () diff --git a/gnuradio-core/src/lib/general/generate_common.py b/gnuradio-core/src/lib/general/generate_common.py new file mode 100755 index 00000000..4616f4a9 --- /dev/null +++ b/gnuradio-core/src/lib/general/generate_common.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from build_utils import expand_template, standard_dict +from build_utils_codes import * + +import re + + +# sources and sinks +ss_signatures = ['s', 'i', 'f', 'c'] + +ss_roots = [ + 'gr_vector_source_X', + 'gr_vector_sink_X', + 'gr_noise_source_X', + 'gr_sig_source_X' + ] + +# regular blocks +reg_signatures = ['ss', 'ii', 'ff', 'cc'] + +reg_roots = [ + 'gr_add_const_XX', + 'gr_multiply_const_XX', + 'gr_add_XX', + 'gr_sub_XX', + 'gr_multiply_XX', + 'gr_divide_XX', + 'gr_mute_XX', + 'gr_add_vXX', + 'gr_multiply_vXX', + 'gr_add_const_vXX', + 'gr_multiply_const_vXX' + ] + +# other blocks +others = ( + ('gr_chunks_to_symbols_XX', ('bf', 'bc', 'sf', 'sc', 'if', 'ic')), + ('gr_unpacked_to_packed_XX', ('bb','ss','ii')), + ('gr_packed_to_unpacked_XX', ('bb','ss','ii')) + ) + + +def expand_h_cc_i (root, sig): + # root looks like 'gr_vector_sink_X' + name = re.sub ('X+', sig, root) + d = standard_dict (name, sig) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + + +def generate (): + expand_h_cc_i ('gr_add_const_XX', 'sf') # for MC4020 + expand_h_cc_i ('gr_vector_sink_X', 'b') + expand_h_cc_i ('gr_vector_source_X', 'b') + for r in ss_roots: + for s in ss_signatures: + expand_h_cc_i (r, s) + for r in reg_roots : + for s in reg_signatures: + expand_h_cc_i (r, s) + + for root, sigs in others: + for s in sigs: + expand_h_cc_i (root, s) + + + +if __name__ == '__main__': + generate () + + diff --git a/gnuradio-core/src/lib/general/gr_add_XX.cc.t b/gnuradio-core/src/lib/general/gr_add_XX.cc.t new file mode 100644 index 00000000..f743d873 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return @SPTR_NAME@ (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (int i = 0; i < noutput_items; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc += ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_XX.h.t b/gnuradio-core/src/lib/general/gr_add_XX.h.t new file mode 100644 index 00000000..1fa42e36 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_XX.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = sum (input_0, input_1, ...) + * \ingroup block + * + * Add across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_add_XX.i.t b/gnuradio-core/src/lib/general/gr_add_XX.i.t new file mode 100644 index 00000000..8479aad6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/general/gr_add_const_XX.cc.t b/gnuradio-core/src/lib/general/gr_add_const_XX.cc.t new file mode 100644 index 00000000..1a2cf08d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (@O_TYPE@ k) +{ + return @SPTR_NAME@ (new @NAME@ (k)); +} + +@NAME@::@NAME@ (@O_TYPE@ k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_k (k) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + while (size >= 8){ + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++ + d_k; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_const_XX.h.t b/gnuradio-core/src/lib/general/gr_add_const_XX.h.t new file mode 100644 index 00000000..c965df3a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output = input + constant + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + + @O_TYPE@ d_k; // the constant + @NAME@ (@O_TYPE@ k); + + public: + @O_TYPE@ k () const { return d_k; } + void set_k (@O_TYPE@ k) { d_k = k; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_add_const_XX.i.t b/gnuradio-core/src/lib/general/gr_add_const_XX.i.t new file mode 100644 index 00000000..c2c814b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_XX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (@TYPE@ k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (@TYPE@ k); + + public: + @TYPE@ k () const { return d_k; } + void set_k (@TYPE@ k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/general/gr_add_const_vXX.cc.t b/gnuradio-core/src/lib/general/gr_add_const_vXX.cc.t new file mode 100755 index 00000000..7966331b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_vXX.cc.t @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k) +{ + return @SPTR_NAME@ (new @NAME@ (k)); +} + +@NAME@::@NAME@ (const std::vector<@I_TYPE@> k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof(@I_TYPE@)*k.size()), + gr_make_io_signature (1, 1, sizeof(@O_TYPE@)*k.size())) +{ + d_k = k; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@O_TYPE@ *)input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *)output_items[0]; + + int nitems_per_block = output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@); + + for (int i = 0; i < noutput_items; i++) + for (int j = 0; j < nitems_per_block; j++) + *optr++ = *iptr++ + d_k[j]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_const_vXX.h.t b/gnuradio-core/src/lib/general/gr_add_const_vXX.h.t new file mode 100755 index 00000000..b42bc2d9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_vXX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + +/*! + * \brief output vector = input vector + constant vector + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + + std::vector<@I_TYPE@> d_k; // the constant + @NAME@ (const std::vector<@I_TYPE@> k); + + public: + const std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> k) { d_k = k; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_add_const_vXX.i.t b/gnuradio-core/src/lib/general/gr_add_const_vXX.i.t new file mode 100755 index 00000000..38c39943 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_vXX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (const std::vector<@I_TYPE@> k); + + public: + std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/general/gr_add_vXX.cc.t b/gnuradio-core/src/lib/general/gr_add_vXX.cc.t new file mode 100755 index 00000000..480b4a45 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_vXX.cc.t @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (size_t nitems_per_block) +{ + return @SPTR_NAME@ (new @NAME@ (nitems_per_block)); +} + +@NAME@::@NAME@ (size_t nitems_per_block) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*nitems_per_block), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*nitems_per_block)) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + int nitems_per_block = output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@); + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nitems_per_block; j++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i*nitems_per_block+j]; + for (int k = 1; k < ninputs; k++) + acc += ((@I_TYPE@ *) input_items[k])[i*nitems_per_block+j]; + + *optr++ = (@O_TYPE@) acc; + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_vXX.h.t b/gnuradio-core/src/lib/general/gr_add_vXX.h.t new file mode 100755 index 00000000..29a0b03b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_vXX.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +/*! + * \brief output = sum (input_0, input_1, ...) + * \ingroup block + * + * Add across all input vectors. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + + @NAME@ (size_t nitems_per_block); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_add_vXX.i.t b/gnuradio-core/src/lib/general/gr_add_vXX.i.t new file mode 100755 index 00000000..08109610 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_vXX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t nitems_per_block); +}; diff --git a/gnuradio-core/src/lib/general/gr_agc_cc.cc b/gnuradio-core/src/lib/general/gr_agc_cc.cc new file mode 100644 index 00000000..7249ee15 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.cc @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_agc_cc_sptr +gr_make_agc_cc (float rate, float reference, float gain, float max_gain) +{ + return gr_agc_cc_sptr (new gr_agc_cc (rate, reference, gain, max_gain)); +} + +gr_agc_cc::gr_agc_cc (float rate, float reference, float gain, float max_gain) + : gr_sync_block ("gr_agc_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) + , gri_agc_cc (rate, reference, gain, max_gain) +{ +} + +int +gr_agc_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]; + scaleN (out, in, noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_agc_cc.h b/gnuradio-core/src/lib/general/gr_agc_cc.h new file mode 100644 index 00000000..c7676a51 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_AGC_CC_H +#define INCLUDED_GR_AGC_CC_H + +#include +#include +class gr_agc_cc; +typedef boost::shared_ptr gr_agc_cc_sptr; + +gr_agc_cc_sptr +gr_make_agc_cc (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0); +/*! + * \brief high performance Automatic Gain Control class + * + * For Power the absolute value of the complex number is used. + */ + +class gr_agc_cc : public gr_sync_block, public gri_agc_cc +{ + friend gr_agc_cc_sptr gr_make_agc_cc (float rate, float reference, float gain, float max_gain); + gr_agc_cc (float rate, float reference, float gain, float max_gain); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_AGC_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_agc_cc.i b/gnuradio-core/src/lib/general/gr_agc_cc.i new file mode 100644 index 00000000..79ebf19d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,agc_cc) + +%include + +gr_agc_cc_sptr +gr_make_agc_cc (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0); + +class gr_agc_cc : public gr_sync_block , public gri_agc_cc +{ + gr_agc_cc (float rate, float reference, float gain, float max_gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_agc_ff.cc b/gnuradio-core/src/lib/general/gr_agc_ff.cc new file mode 100644 index 00000000..6b0d01e7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.cc @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_agc_ff_sptr +gr_make_agc_ff (float rate, float reference, float gain, float max_gain) +{ + return gr_agc_ff_sptr (new gr_agc_ff (rate, reference, gain, max_gain)); +} + +gr_agc_ff::gr_agc_ff (float rate, float reference, float gain, float max_gain) + : gr_sync_block ("gr_agc_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))) + , gri_agc (rate, reference, gain, max_gain) +{ +} + +int +gr_agc_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + scaleN (out, in, noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_agc_ff.h b/gnuradio-core/src/lib/general/gr_agc_ff.h new file mode 100644 index 00000000..da7edb7a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_AGC_FF_H +#define INCLUDED_GR_AGC_FF_H + +#include +#include +class gr_agc_ff; +typedef boost::shared_ptr gr_agc_ff_sptr; + +gr_agc_ff_sptr +gr_make_agc_ff (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0); +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + +class gr_agc_ff : public gr_sync_block, public gri_agc +{ + friend gr_agc_ff_sptr gr_make_agc_ff (float rate, float reference, float gain, float max_gain); + gr_agc_ff (float rate, float reference, float gain, float max_gain); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FLOAT_AGC_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_agc_ff.i b/gnuradio-core/src/lib/general/gr_agc_ff.i new file mode 100644 index 00000000..9b631271 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,agc_ff) + +%include + +gr_agc_ff_sptr +gr_make_agc_ff (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0); + +class gr_agc_ff : public gr_sync_block , public gri_agc +{ + gr_agc_ff (float rate, float reference, float gain, float max_gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc new file mode 100644 index 00000000..005b575b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc @@ -0,0 +1,461 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +//define ALIGN_ADVANCED_IMPLEMENTATION to have an alternative implementation of the align algoritm which exactly follows the align_interval spec. +//It is more resource intensive, less tested and probably not needed +//define ALIGN_ADVANCED_IMPLEMENTATION + +//define DEBUG_TOCONSUME to see debug messages about the synchronisation part of this block +//define DEBUG_TOCONSUME +#ifdef DEBUG_TOCONSUME +#define tcPrintf if(dprint) printf +#else +#define tcPrintf //printf +#endif + +#define ePrintf printf + +gr_align_on_samplenumbers_ss_sptr +gr_make_align_on_samplenumbers_ss (int nchan, int align_interval) +{ + return gr_align_on_samplenumbers_ss_sptr (new gr_align_on_samplenumbers_ss (nchan,align_interval)); +} + +gr_align_on_samplenumbers_ss::gr_align_on_samplenumbers_ss (int nchan,int align_interval) + : gr_block ("align_on_samplenumbers_ss", + gr_make_io_signature (2, -1, sizeof (short)), //2, -1 + gr_make_io_signature (2, -1, sizeof (short))), //2,-1 + d_align_interval (align_interval), + d_nchan(nchan), + d_ninputs(0) +{ + if (d_align_interval<0) + set_output_multiple (d_nchan*2); + else + { + set_output_multiple (d_align_interval*d_nchan*2); + } + +} + +gr_align_on_samplenumbers_ss::~gr_align_on_samplenumbers_ss() +{ + +} +void +gr_align_on_samplenumbers_ss::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + //assert (0 == noutput_items % d_align_interval); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = std::max(noutput_items*d_nchan*2+ history() - 1,1024*d_nchan*2+ history() - 1);//TODO include the diffs found in determine input_items_required +} + +bool +gr_align_on_samplenumbers_ss::check_topology (int ninputs, int noutputs) +{ + bool result=true; + if(noutputs!=ninputs) + { + result=false; + ePrintf("gr_align_on_samplenumbers_ss: ERROR noutputs %i != ninputs %i\n",noutputs,ninputs); + } + if(d_nchan<2) + { + result=false; + ePrintf("gr_align_on_samplenumbers_ss: ERROR nchan %i<2 \n",d_nchan); + } + if((int)d_ninputs!=ninputs) + { + //Only resize and reset the status if there really changed something + //Don't reset the status if the user just called stop() and start(), although maybe we should. + d_state.resize(ninputs); + d_ninputs=ninputs; + for(unsigned int i=0;i200) + { + dcount=0; + dprint=true; + } +#endif + const size_t item_size = output_signature()->sizeof_stream_item (0); + const unsigned ninputs = input_items.size(); + const unsigned noutputs = output_items.size(); + + int align_interval=d_align_interval*2*d_nchan; + if(d_align_interval<0) + { + //align once per noutput_items + align_interval=noutput_items; + align_interval=align_interval/(2*d_nchan); + align_interval=align_interval*(2*d_nchan); + } + + int min_ninput_items=noutput_items;//numeric_limits::max(); + int noutput_items_produced=0; + for(unsigned int i=0;i=align_interval) + common_end=align_interval; + else + { + common_end=min_ninput_items/(d_nchan*2); + common_end=common_end*(d_nchan*2); + } + if (common_end<=0) break; + + bool all_diffs_zero=true; + //bool sync_found=false; + int diff_comp_end_max=0; + for(unsigned int i=0;i256000000 || d_state[i].diff_end>256000000 || d_state[i].diff_comp_end>256000000) + { + tcPrintf("diff[%i]=%i diff_end=%i diff_comp_end=%i\n",i,d_state[i].diff,d_state[i].diff_end,d_state[i].diff_comp_end); + } +#endif + all_diffs_zero=all_diffs_zero && (0==d_state[i].diff_end); + if(d_state[i].ucounter_end 0x00000000) + if(!d_in_presync) + { +#ifdef DEBUG_TOCONSUME + printf("presync START with %i\n",i); +#endif + for(unsigned int k=0;k10) + { + tcPrintf("toconsume=%i diff_end[%i]*d_nchan*2=%i diff_comp_end_max*d_nchan*2=%i ninput_items[%i]=%i\n",toconsume,i,d_state[i].diff_end*d_nchan*2,diff_comp_end_max*d_nchan*2,i,ninput_items[i]); + toconsume_counter=0; + } +#endif + //printf("toconsume[%i]=%i\n",i,toconsume); + //consume(i,toconsume);//skip the difference in samplenumber items + } + //return 0; + } + } + for(unsigned int i=0;i2000) + { + dcount=0; + dprint=true; + } +#endif + const size_t item_size = output_signature()->sizeof_stream_item (0); + const unsigned ninputs = input_items.size(); + + int common_end=noutput_items; + //int diff_min=INT_MAX; + //int diff_max=INT_MIN; + for(unsigned int i=0;i 0x00000000) +#ifdef DEBUG_TOCONSUME + tcPrintf("SYNC diff_end[%i]=%i ucounter_end[%i]=%i ucounter_begin[%i]=%i \n",i,d_state[i].diff_end,i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); + tcPrintf("ucounter_end=%i < %i = ucounter_begin+(unsigned)(common_last/(d_nchan*2) \n",d_state[i].ucounter_end,d_state[i].ucounter_begin+(unsigned)(common_last/(d_nchan*2))); + + printf("ucounter_end[%i]=%i ucounter_begin[%i]=%i\n",i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); + int expected_sync_position=common_last - d_state[i].ucounter_end*(d_nchan*2); + if(0==uin[expected_sync_position] && 0==uin[expected_sync_position+1]) + { + printf("sync found on input %i at position %i \n",i,expected_sync_position); + //sync_start[i]=expected_sync_position; + } else + { + printf("sync found on input %i position unclear, expected at %i value there %i\n",i,expected_sync_position,uin[expected_sync_position]<<16 | uin[expected_sync_position+1]); + //sync_start[i]=-1; + } + } else + { + tcPrintf("NOsync diff_end[%i]=%i ucounter_end[%i]=%i ucounter_begin[%i]=%i \n",i,d_state[i].diff_end,i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); +#endif + } + } + bool problem=false; + for(unsigned int i=0;i0x4000000) + { + problem=true; + ePrintf("Warning: counter diff greater as 64 Million\n"); + ePrintf(" You might want to swap master and slave.\n"); + ePrintf(" i=%i,d_state[i].diff_end+diff_comp_end_max=%i,d_state[i].diff_end=%i,diff_comp_end_max=%i,ucounter[i]=%i,ucounter[0]=%i\n", + i,d_state[i].diff_end+diff_comp_end_max,d_state[i].diff_end,diff_comp_end_max,d_state[i].ucounter_end,d_state[0].ucounter_end); + //ePrintf(" toconsume=%i\n",toconsume); + } + if(sync_found || all_diffs_zero || problem) + { +#ifdef DEBUG_TOCONSUME + if(all_diffs_zero) tcPrintf("ZERO\n"); + if(sync_found) tcPrintf("SYNC\n"); +#endif + for(unsigned int i=0;i10) + { + tcPrintf("toconsume=%i diff_end[[%i]*d_nchan*2=%i diff_comp_end_max)*d_nchan*2=%i ninput_items[%i]=%i\n", + toconsume,i,d_state[i].diff_end*d_nchan*2,diff_comp_end_max*d_nchan*2,i,ninput_items[i]); + toconsume_counter=0; + } +#endif + consume(i,toconsume);//skip the difference in samplenumber items + //printf("toconsume%i %i diff_comp_end_max %i diff_end[[%i] %i\n",i,toconsume,diff_comp_end_max,i,d_state[i].diff_end); + } + return 0; + } + return -1;//Should never come here +} +#endif /*ALIGN_ADVANCED_IMPLEMENTATION*/ diff --git a/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h new file mode 100644 index 00000000..69d68b2a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_ALIGN_ON_SAMPLE_NUMBERS_SS_H +#define INCLUDED_GR_ALIGN_ON_SAMPLE_NUMBERS_SS_H + +#include + +class gr_align_on_samplenumbers_ss; +typedef boost::shared_ptr gr_align_on_samplenumbers_ss_sptr; + +gr_align_on_samplenumbers_ss_sptr gr_make_align_on_samplenumbers_ss (int nchan=2, int align_interval=128); + +/*! + * \brief align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values) + * \param number of complex_short input channels (including the 32 bit counting channel) + * \param align_interval is after how much samples (minimally) the sample-alignement is refreshed. Default is 128. + * A bigger value means less processing power but also requests more buffer space, which has a maximum. + * Decrease the align_interval if you get an error like: + * "sched: is requesting more input data than we can provide. + * ninput_items_required = 32768 + * max_possible_items_available = 16383 + * If this is a filter, consider reducing the number of taps." + * \ingroup block + * Pay attention on how you connect this block. + * It expects a minimum of 2 usrp_source_s with nchan number of channels and FPGA_MODE_COUNTING_32BIT enabled. + * This means that the first complex_short channel on every input is an interleaved 32 bit counter. + * The samples are aligned by dropping samples untill the samplenumbers match. + */ + + +class gr_align_on_samplenumbers_ss : public gr_block +{ + int d_align_interval; + int d_sample_counter; + int d_nchan; + bool d_in_presync; + unsigned int d_ninputs; + class align_state { + public: + unsigned int ucounter_end; + unsigned int ucounter_begin; + int diff; + int diff_comp; + int diff_end; + int diff_comp_end; + bool sync_found; + bool sync_end_found; + int ninput_items; + int ninput_items_used; + }; + std::vector d_state; + + friend gr_align_on_samplenumbers_ss_sptr gr_make_align_on_samplenumbers_ss (int nchan,int align_interval); + gr_align_on_samplenumbers_ss (int nchan,int align_interval); + + public: + ~gr_align_on_samplenumbers_ss(); + bool check_topology (int ninputs, int noutputs); + 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_ALIGN_ON_SAMPLE_NUMBERS_SS_H */ diff --git a/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i new file mode 100644 index 00000000..00d31749 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,align_on_samplenumbers_ss); + +gr_align_on_samplenumbers_ss_sptr gr_make_align_on_samplenumbers_ss(int nchan=2, int align_interval=128); + +class gr_align_on_samplenumbers_ss : public gr_block +{ + public: + ~gr_align_on_samplenumbers_ss (); + private: + gr_align_on_samplenumbers_ss (int nchan,int align_interval); +}; diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc new file mode 100644 index 00000000..a74746d3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_binary_slicer_fb_sptr +gr_make_binary_slicer_fb () +{ + return gr_binary_slicer_fb_sptr (new gr_binary_slicer_fb ()); +} + +gr_binary_slicer_fb::gr_binary_slicer_fb () + : gr_sync_block ("binary_slicer_fb", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ +} + +static inline int +slice(float x) +{ + return x < 0 ? 0 : 1; +} + +int +gr_binary_slicer_fb::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]; + unsigned char *out = (unsigned char *) output_items[0]; + + + for (int i = 0; i < noutput_items; i++){ + out[i] = slice(in[i]); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h new file mode 100644 index 00000000..ce755718 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BINARY_SLICER_FB_H +#define INCLUDED_GR_BINARY_SLICER_FB_H + +#include + +class gr_binary_slicer_fb; +typedef boost::shared_ptr gr_binary_slicer_fb_sptr; + +gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); + +/*! + * \brief slice float binary symbol outputting 1 bit output + * \ingroup block + * + * x < 0 --> 0 + * x >= 0 --> 1 + */ +class gr_binary_slicer_fb : public gr_sync_block +{ + friend gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); + gr_binary_slicer_fb (); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i new file mode 100644 index 00000000..0d66429b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,binary_slicer_fb); + +gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); + +class gr_binary_slicer_fb : public gr_sync_block +{ + private: + gr_binary_slicer_fb (); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc new file mode 100644 index 00000000..3b492cdb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +static const int BITS_PER_BYTE = 8; + +gr_bytes_to_syms_sptr +gr_make_bytes_to_syms () +{ + return gr_bytes_to_syms_sptr (new gr_bytes_to_syms ()); +} + +gr_bytes_to_syms::gr_bytes_to_syms () + : gr_sync_interpolator ("bytes_to_syms", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (float)), + BITS_PER_BYTE) +{ +} + +int +gr_bytes_to_syms::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (unsigned char *) input_items[0]; + float *out = (float *) output_items[0]; + + assert (noutput_items % BITS_PER_BYTE == 0); + + for (int i = 0; i < noutput_items / BITS_PER_BYTE; i++){ + int x = in[i]; + + *out++ = (((x >> 7) & 0x1) << 1) - 1; + *out++ = (((x >> 6) & 0x1) << 1) - 1; + *out++ = (((x >> 5) & 0x1) << 1) - 1; + *out++ = (((x >> 4) & 0x1) << 1) - 1; + *out++ = (((x >> 3) & 0x1) << 1) - 1; + *out++ = (((x >> 2) & 0x1) << 1) - 1; + *out++ = (((x >> 1) & 0x1) << 1) - 1; + *out++ = (((x >> 0) & 0x1) << 1) - 1; + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.h b/gnuradio-core/src/lib/general/gr_bytes_to_syms.h new file mode 100644 index 00000000..72f844d4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_BYTES_TO_SYMS_H +#define INCLUDED_GR_BYTES_TO_SYMS_H + +#include + +class gr_bytes_to_syms; +typedef boost::shared_ptr gr_bytes_to_syms_sptr; + +gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); + +/*! + * \brief Convert stream of bytes to stream of +/- 1 symbols + * \ingroup block + * + * input: stream of bytes; output: stream of float + * + * This block is deprecated. + * + * The combination of gr_packed_to_unpacked_bb followed by + * gr_chunks_to_symbols_bf or gr_chunks_to_symbols_bc handles the + * general case of mapping from a stream of bytes into arbitrary float + * or complex symbols. + * + * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, + * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. + */ +class gr_bytes_to_syms : public gr_sync_interpolator +{ + friend gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); + + gr_bytes_to_syms (); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_BYTES_TO_SYMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.i b/gnuradio-core/src/lib/general/gr_bytes_to_syms.i new file mode 100644 index 00000000..33ef089d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,bytes_to_syms); + +gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); + +class gr_bytes_to_syms : public gr_sync_interpolator +{ + gr_bytes_to_syms (); +}; diff --git a/gnuradio-core/src/lib/general/gr_char_to_float.cc b/gnuradio-core/src/lib/general/gr_char_to_float.cc new file mode 100644 index 00000000..c4151eee --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_char_to_float_sptr +gr_make_char_to_float () +{ + return gr_char_to_float_sptr (new gr_char_to_float ()); +} + +gr_char_to_float::gr_char_to_float () + : gr_sync_block ("gr_char_to_float", + gr_make_io_signature (1, 1, sizeof (char)), + gr_make_io_signature (1, 1, sizeof (float))) +{ +} + +int +gr_char_to_float::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]; + float *out = (float *) output_items[0]; + + gri_char_to_float (in, out, noutput_items); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_char_to_float.h b/gnuradio-core/src/lib/general/gr_char_to_float.h new file mode 100644 index 00000000..d2b287ff --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CHAR_TO_FLOAT_H +#define INCLUDED_GR_CHAR_TO_FLOAT_H + +#include + +class gr_char_to_float; +typedef boost::shared_ptr gr_char_to_float_sptr; + +gr_char_to_float_sptr +gr_make_char_to_float (); + +/*! + * \brief Convert stream of chars to a stream of float + * \ingroup converter + */ + +class gr_char_to_float : public gr_sync_block +{ + friend gr_char_to_float_sptr gr_make_char_to_float (); + gr_char_to_float (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_CHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_char_to_float.i b/gnuradio-core/src/lib/general/gr_char_to_float.i new file mode 100644 index 00000000..3f1c7e19 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,char_to_float) + +gr_char_to_float_sptr gr_make_char_to_float (); + +class gr_char_to_float : public gr_sync_block +{ + gr_char_to_float (); +}; diff --git a/gnuradio-core/src/lib/general/gr_check_counting_s.cc b/gnuradio-core/src/lib/general/gr_check_counting_s.cc new file mode 100644 index 00000000..59e740c1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.cc @@ -0,0 +1,190 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_check_counting_s_sptr +gr_make_check_counting_s (bool do_32bit) +{ + return gr_check_counting_s_sptr (new gr_check_counting_s (do_32bit)); +} + +gr_check_counting_s::gr_check_counting_s (bool do_32bit) + : gr_sync_block ("gr_check_counting", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (0, 0, 0)), + d_state(SEARCHING), d_history (0), d_current_count (0), d_current_count_32bit(0), + d_total_errors (0), d_total_shorts (0), + d_do_32bit(do_32bit) +{ + enter_SEARCHING (); +} + +int +gr_check_counting_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned short *in = (unsigned short *) input_items[0]; + if(d_do_32bit) + return check_32bit(noutput_items,in); + else + return check_16bit(noutput_items,in); +} + +int +gr_check_counting_s::check_16bit (int noutput_items, + unsigned short * in) +{ + for (int i = 0; i < noutput_items; i++){ + unsigned short x = in[i]; + + switch (d_state){ + + case SEARCHING: + if (x == d_current_count){ + right (); + log_error (d_current_count, x); + d_current_count = d_current_count + 1; + if (right_three_times ()) + enter_LOCKED (); + } + else { + wrong (); + log_error (d_current_count, x); + d_current_count = x + 1; + } + break; + + case LOCKED: + if (x == d_current_count){ + right (); + d_current_count = d_current_count + 1; + } + else { + wrong (); + log_error (d_current_count, x); + d_current_count = d_current_count + 1; + if (wrong_three_times ()) + enter_SEARCHING (); + } + break; + + default: + abort (); + } + + d_total_shorts++; + } + + return noutput_items; +} + +int +gr_check_counting_s::check_32bit (int noutput_items, + unsigned short * in) +{ + + for (int i = 0; i < noutput_items-1; i+=2){ + unsigned int x_high16bits = in[i]; + unsigned int x_low16bits = in[i+1]; + unsigned int x = x_high16bits<<16 | x_low16bits; + + switch (d_state){ + + case SEARCHING: + if (x == d_current_count_32bit){ + right (); + log_error_32bit (d_current_count_32bit, x); + d_current_count_32bit = d_current_count_32bit + 1; + if (right_three_times ()) + enter_LOCKED (); + } + else { + wrong (); + log_error_32bit (d_current_count_32bit, x); + d_current_count_32bit = x + 1; + } + break; + + case LOCKED: + if (x == d_current_count_32bit){ + right (); + d_current_count_32bit = d_current_count_32bit + 1; + } + else { + wrong (); + log_error_32bit (d_current_count_32bit, x); + d_current_count_32bit = d_current_count_32bit + 1; + if (wrong_three_times ()) + enter_SEARCHING (); + } + break; + + default: + abort (); + } + + d_total_shorts++; + } + + return noutput_items; +} + +void +gr_check_counting_s::enter_SEARCHING () +{ + d_state = SEARCHING; + fprintf (stdout, "gr_check_counting: enter_SEARCHING at offset %8ld (0x%08lx)\n", + d_total_shorts, d_total_shorts); +} + +void +gr_check_counting_s::enter_LOCKED () +{ + d_state = LOCKED; + fprintf (stdout, "gr_check_counting: enter_LOCKED at offset %8ld (0x%08lx)\n", + d_total_shorts, d_total_shorts); +} + +void +gr_check_counting_s::log_error (unsigned short expected, unsigned short actual) +{ + fprintf (stdout, +"gr_check_counting: expected %5d (0x%04x) got %5d (0x%04x) offset %8ld (0x%08lx)\n", + expected, expected, actual, actual, d_total_shorts, d_total_shorts); +} + +void +gr_check_counting_s::log_error_32bit (unsigned int expected, unsigned int actual) +{ + fprintf (stdout, +"gr_check_counting: expected %10d (0x%08x) got %10d (0x%08x) offset %8ld (0x%08lx)\n", + expected, expected, actual, actual, d_total_shorts, d_total_shorts); +} diff --git a/gnuradio-core/src/lib/general/gr_check_counting_s.h b/gnuradio-core/src/lib/general/gr_check_counting_s.h new file mode 100644 index 00000000..3037e9f0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.h @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_CHECK_COUNTING_S_H +#define INCLUDED_GR_CHECK_COUNTING_S_H + +#include + +class gr_check_counting_s; +typedef boost::shared_ptr gr_check_counting_s_sptr; + +gr_check_counting_s_sptr gr_make_check_counting_s (bool do_32bit=false); + +/*! + * \brief sink that checks if its input stream consists of a counting sequence. + * \param do_32bit expect an interleaved 32 bit counter in stead of 16 bit counter (default false) + * \ingroup sink + * + * This sink is typically used to test the USRP "Counting Mode" or "Counting mode 32 bit". + */ +class gr_check_counting_s : public gr_sync_block +{ + friend gr_check_counting_s_sptr gr_make_check_counting_s (bool do_32bit); + + enum state { + SEARCHING, // searching for synchronization + LOCKED // is locked + }; + + state d_state; + unsigned int d_history; // bitmask of decisions + unsigned short d_current_count; + unsigned int d_current_count_32bit; + + long d_total_errors; + long d_total_shorts; + bool d_do_32bit; + + gr_check_counting_s (bool do_32bit); + + void enter_SEARCHING (); + void enter_LOCKED (); + + void right (){ + d_history = (d_history << 1) | 0x1; + } + + void wrong (){ + d_history = (d_history << 1) | 0x0; + d_total_errors++; + } + + bool right_three_times () { return (d_history & 0x7) == 0x7; } + bool wrong_three_times () { return (d_history & 0x7) == 0x0; } + + void log_error (unsigned short expected, unsigned short actual); + void log_error_32bit (unsigned int expected, unsigned int actual); + + int check_32bit (int noutput_items, unsigned short * in); + int check_16bit (int noutput_items, unsigned short * in); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_CHECK_COUNTING_S_H */ diff --git a/gnuradio-core/src/lib/general/gr_check_counting_s.i b/gnuradio-core/src/lib/general/gr_check_counting_s.i new file mode 100644 index 00000000..f52f8724 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,check_counting_s) + +gr_check_counting_s_sptr gr_make_check_counting_s (bool do_32bit=false); + +class gr_check_counting_s : public gr_sync_block +{ + private: + gr_check_counting_s (bool do_32bit); +}; diff --git a/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc new file mode 100644 index 00000000..72051cf5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc @@ -0,0 +1,169 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_check_lfsr_32k_s_sptr +gr_make_check_lfsr_32k_s () +{ + return gr_check_lfsr_32k_s_sptr (new gr_check_lfsr_32k_s ()); +} + +gr_check_lfsr_32k_s::gr_check_lfsr_32k_s () + : gr_sync_block ("gr_check_lfsr_32k", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (0, 0, 0)), + d_state(SEARCHING), d_history (0), d_ntotal (0), d_nright (0), + d_runlength (0), d_index(0) +{ + gri_lfsr_32k lfsr; + + for (int i = 0; i < BUFSIZE; i++) + d_buffer[i] = lfsr.next_short (); + + enter_SEARCHING (); +} + +int +gr_check_lfsr_32k_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned short *in = (unsigned short *) input_items[0]; + + for (int i = 0; i < noutput_items; i++){ + unsigned short x = in[i]; + unsigned short expected; + + switch (d_state){ + + case MATCH0: + if (x == d_buffer[0]) + enter_MATCH1 (); + break; + + case MATCH1: + if (x == d_buffer[1]) + enter_MATCH2 (); + else + enter_MATCH0 (); + break; + + case MATCH2: + if (x == d_buffer[2]) + enter_LOCKED (); + else + enter_MATCH0 (); + break; + + case LOCKED: + expected = d_buffer[d_index]; + d_index = d_index + 1; + if (d_index >= BUFSIZE) + d_index = 0; + + if (x == expected) + right (); + else { + wrong (); + log_error (expected, x); + if (wrong_three_times ()) + enter_SEARCHING (); + } + break; + + default: + abort (); + } + + d_ntotal++; + } + + return noutput_items; +} + +void +gr_check_lfsr_32k_s::enter_SEARCHING () +{ + d_state = SEARCHING; + wrong (); // reset history + wrong (); + wrong (); + + d_runlength = 0; + d_index = 0; // reset LFSR to beginning + + if (0) + fprintf (stdout, "gr_check_lfsr_32k: enter_SEARCHING at offset %8ld (0x%08lx)\n", + d_ntotal, d_ntotal); + + enter_MATCH0 (); +} + +void +gr_check_lfsr_32k_s::enter_MATCH0 () +{ + d_state = MATCH0; +} + +void +gr_check_lfsr_32k_s::enter_MATCH1 () +{ + d_state = MATCH1; +} + +void +gr_check_lfsr_32k_s::enter_MATCH2 () +{ + d_state = MATCH2; +} + +void +gr_check_lfsr_32k_s::enter_LOCKED () +{ + d_state = LOCKED; + right (); // setup history + right (); + right (); + + d_index = 3; // already matched first 3 items + + if (0) + fprintf (stdout, "gr_check_lfsr_32k: enter_LOCKED at offset %8ld (0x%08lx)\n", + d_ntotal, d_ntotal); +} + +void +gr_check_lfsr_32k_s::log_error (unsigned short expected, unsigned short actual) +{ + if (0) + fprintf (stdout, + "gr_check_lfsr_32k: expected %5d (0x%04x) got %5d (0x%04x) offset %8ld (0x%08lx)\n", + expected, expected, actual, actual, d_ntotal, d_ntotal); +} diff --git a/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h new file mode 100644 index 00000000..4b7eb8a1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_CHECK_LFSR_32K_S_H +#define INCLUDED_GR_CHECK_LFSR_32K_S_H + +#include +#include + + +class gr_check_lfsr_32k_s; +typedef boost::shared_ptr gr_check_lfsr_32k_s_sptr; + +gr_check_lfsr_32k_s_sptr gr_make_check_lfsr_32k_s (); + +/*! + * \brief sink that checks if its input stream consists of a lfsr_32k sequence. + * \ingroup sink + * + * This sink is typically used along with gr_lfsr_32k_source_s to test + * the USRP using its digital loopback mode. + */ +class gr_check_lfsr_32k_s : public gr_sync_block +{ + friend gr_check_lfsr_32k_s_sptr gr_make_check_lfsr_32k_s (); + + enum state { + SEARCHING, // searching for synchronization + MATCH0, + MATCH1, + MATCH2, + LOCKED // is locked + }; + + state d_state; + unsigned int d_history; // bitmask of decisions + + long d_ntotal; // total number of shorts + long d_nright; // # of correct shorts + long d_runlength; // # of correct shorts in a row + + static const int BUFSIZE = 2048 - 1; // ensure pattern isn't packet aligned + int d_index; + unsigned short d_buffer[BUFSIZE]; + + + gr_check_lfsr_32k_s (); + + void enter_SEARCHING (); + void enter_MATCH0 (); + void enter_MATCH1 (); + void enter_MATCH2 (); + void enter_LOCKED (); + + void right (){ + d_history = (d_history << 1) | 0x1; + d_nright++; + d_runlength++; + } + + void wrong (){ + d_history = (d_history << 1) | 0x0; + d_runlength = 0; + } + + bool right_three_times () { return (d_history & 0x7) == 0x7; } + bool wrong_three_times () { return (d_history & 0x7) == 0x0; } + + void log_error (unsigned short expected, unsigned short actual); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + long ntotal () const { return d_ntotal; } + long nright () const { return d_nright; } + long runlength () const { return d_runlength; } + +}; + + +#endif /* INCLUDED_GR_CHECK_LFSR_32K_S_H */ diff --git a/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i new file mode 100644 index 00000000..422b7cd2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,check_lfsr_32k_s) + +gr_check_lfsr_32k_s_sptr gr_make_check_lfsr_32k_s (); + +class gr_check_lfsr_32k_s : public gr_sync_block +{ + private: + gr_check_lfsr_32k_s (); + +public: + long ntotal () const; + long nright () const; + long runlength () const; +}; diff --git a/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.cc.t b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.cc.t new file mode 100644 index 00000000..a4887335 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.cc.t @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include +#include +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) +{ + return @SPTR_NAME@ (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 + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); + +/*! + * \brief Map a stream of symbol indexes (unpacked bytes or shorts) to stream of float or complex onstellation points.in \p D dimensions (\p D = 1 by default) + * \ingroup block + * + * input: stream of @I_TYPE@; output: stream of @O_TYPE@ + * + * out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 + * + * The combination of gr_packed_to_unpacked_XX followed by + * gr_chunks_to_symbols_XY handles the general case of mapping + * from a stream of bytes or shorts into arbitrary float + * or complex symbols. + * + * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, + * \sa gr_packed_to_unpacked_ss, gr_unpacked_to_packed_ss, + * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. + * \sa gr_chunks_to_symbols_sf, gr_chunks_to_symbols_sc. + */ + +class @NAME@ : public gr_sync_interpolator +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D); + + int d_D; + std::vector<@O_TYPE@> d_symbol_table; + @NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); + + public: + int D () const { return d_D; } + std::vector<@O_TYPE@> symbol_table () const { return d_symbol_table; } + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.i.t b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.i.t new file mode 100644 index 00000000..e67e4804 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_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/gnuradio-core/src/lib/general/gr_circular_file.cc b/gnuradio-core/src/lib/general/gr_circular_file.cc new file mode 100644 index 00000000..8aa8af08 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_circular_file.cc @@ -0,0 +1,194 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include + +static const int HEADER_SIZE = 4096; +static const int HEADER_MAGIC = 0xEB021026; + +static const int HD_MAGIC = 0; +static const int HD_HEADER_SIZE = 1; // integer offsets into header +static const int HD_BUFFER_SIZE = 2; +static const int HD_BUFFER_BASE = 3; +static const int HD_BUFFER_CURRENT = 4; + +gr_circular_file::gr_circular_file (const char *filename, + bool writable, int size) + : d_fd (-1), d_header (0), d_buffer (0), d_mapped_size (0), d_bytes_read (0) +{ + int mm_prot; + if (writable){ +#ifdef HAVE_MMAP + mm_prot = PROT_READ | PROT_WRITE; +#endif + d_fd = open (filename, O_CREAT | O_RDWR | O_TRUNC, 0664); + if (d_fd < 0){ + perror (filename); + exit (1); + } +#ifdef HAVE_MMAP /* FIXME */ + ftruncate (d_fd, size + HEADER_SIZE); +#endif + } + else { +#ifdef HAVE_MMAP + mm_prot = PROT_READ; +#endif + d_fd = open (filename, O_RDONLY); + if (d_fd < 0){ + perror (filename); + exit (1); + } + } + + struct stat statbuf; + if (fstat (d_fd, &statbuf) < 0){ + perror (filename); + exit (1); + } + + if (statbuf.st_size < HEADER_SIZE){ + fprintf (stderr, "%s: file too small to be circular buffer\n", filename); + exit (1); + } + + d_mapped_size = statbuf.st_size; +#ifdef HAVE_MMAP + void *p = mmap (0, d_mapped_size, mm_prot, MAP_SHARED, d_fd, 0); + if (p == MAP_FAILED){ + perror ("gr_circular_file: mmap failed"); + exit (1); + } + + d_header = (int *) p; +#else + perror ("gr_circular_file: mmap unsupported by this system"); + exit (1); +#endif + + if (writable){ // init header + + if (size < 0){ + fprintf (stderr, "gr_circular_buffer: size must be > 0 when writable\n"); + exit (1); + } + + d_header[HD_MAGIC] = HEADER_MAGIC; + d_header[HD_HEADER_SIZE] = HEADER_SIZE; + d_header[HD_BUFFER_SIZE] = size; + d_header[HD_BUFFER_BASE] = HEADER_SIZE; // right after header + d_header[HD_BUFFER_CURRENT] = 0; + } + + // sanity check (the asserts are a bit unforgiving...) + + assert (d_header[HD_MAGIC] == HEADER_MAGIC); + assert (d_header[HD_HEADER_SIZE] == HEADER_SIZE); + assert (d_header[HD_BUFFER_SIZE] > 0); + assert (d_header[HD_BUFFER_BASE] >= d_header[HD_HEADER_SIZE]); + assert (d_header[HD_BUFFER_BASE] + d_header[HD_BUFFER_SIZE] <= d_mapped_size); + assert (d_header[HD_BUFFER_CURRENT] >= 0 && + d_header[HD_BUFFER_CURRENT] < d_header[HD_BUFFER_SIZE]); + + d_bytes_read = 0; + d_buffer = (unsigned char *) d_header + d_header[HD_BUFFER_BASE]; +} + +gr_circular_file::~gr_circular_file () +{ +#ifdef HAVE_MMAP + if (munmap ((char *) d_header, d_mapped_size) < 0){ + perror ("gr_circular_file: munmap"); + exit (1); + } +#endif + close (d_fd); +} + +bool +gr_circular_file::write (void *vdata, int nbytes) +{ + unsigned char *data = (unsigned char *) vdata; + int buffer_size = d_header[HD_BUFFER_SIZE]; + int buffer_current = d_header[HD_BUFFER_CURRENT]; + + while (nbytes > 0){ + int n = std::min (nbytes, buffer_size - buffer_current); + memcpy (d_buffer + buffer_current, data, n); + + buffer_current += n; + if (buffer_current >= buffer_size) + buffer_current = 0; + + data += n; + nbytes -= n; + } + + d_header[HD_BUFFER_CURRENT] = buffer_current; + return true; +} + +int +gr_circular_file::read (void *vdata, int nbytes) +{ + unsigned char *data = (unsigned char *) vdata; + int buffer_current = d_header[HD_BUFFER_CURRENT]; + int buffer_size = d_header[HD_BUFFER_SIZE]; + int total = 0; + + nbytes = std::min (nbytes, buffer_size - d_bytes_read); + + while (nbytes > 0){ + int offset = (buffer_current + d_bytes_read) % buffer_size; + int n = std::min (nbytes, buffer_size - offset); + memcpy (data, d_buffer + offset, n); + data += n; + d_bytes_read += n; + total += n; + nbytes -= n; + } + return total; +} + +void +gr_circular_file::reset_read_pointer () +{ + d_bytes_read = 0; +} diff --git a/gnuradio-core/src/lib/general/gr_circular_file.h b/gnuradio-core/src/lib/general/gr_circular_file.h new file mode 100644 index 00000000..33407457 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_circular_file.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_CIRCULAR_FILE_H_ +#define _GR_CIRCULAR_FILE_H_ + +/* + * writes input data into a circular buffer on disk. + * + * the file contains a fixed header: + * 0x0000: int32 magic (0xEB021026) + * 0x0004: int32 size in bytes of header (constant 4096) + * 0x0008: int32 size in bytes of circular buffer (not including header) + * 0x000C: int32 file offset to beginning of circular buffer + * 0x0010: int32 byte offset from beginning of circular buffer to + * current start of data + * + */ +class gr_circular_file { + int d_fd; + int *d_header; + unsigned char *d_buffer; + int d_mapped_size; + int d_bytes_read; + +public: + gr_circular_file (const char *filename, bool writable = false, int size = 0); + ~gr_circular_file (); + + bool write (void *data, int nbytes); + + // returns # of bytes actually read or 0 if end of buffer, or -1 on error. + int read (void *data, int nbytes); + + // reset read pointer to beginning of buffer. + void reset_read_pointer (); +}; + +#endif /* _GR_CIRCULAR_FILE_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc new file mode 100644 index 00000000..0d8c7f38 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc @@ -0,0 +1,182 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +// Public constructor + + +gr_clock_recovery_mm_cc_sptr +gr_make_clock_recovery_mm_cc(float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit) +{ + return gr_clock_recovery_mm_cc_sptr (new gr_clock_recovery_mm_cc (omega, + gain_omega, + mu, + gain_mu, + omega_relative_limit)); +} + +gr_clock_recovery_mm_cc::gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, + float gain_mu, float omega_relative_limit) + : gr_block ("clock_recovery_mm_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_mu (mu), d_omega(omega), d_gain_omega(gain_omega), + d_omega_relative_limit(omega_relative_limit), + d_gain_mu(gain_mu), d_last_sample(0), d_interp(new gri_mmse_fir_interpolator_cc()), + d_verbose(gr_prefs::singleton()->get_bool("clock_recovery_mm_cc", "verbose", false)), + d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0) +{ + if (omega <= 0.0) + throw std::out_of_range ("clock rate must be > 0"); + if (gain_mu < 0 || gain_omega < 0) + throw std::out_of_range ("Gains must be non-negative"); + + set_omega(omega); // also sets min and max omega + set_relative_rate (1.0 / omega); + set_history(3); // ensure 2 extra input sample is available +} + +gr_clock_recovery_mm_cc::~gr_clock_recovery_mm_cc () +{ + delete d_interp; +} + +void +gr_clock_recovery_mm_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i=0; i < ninputs; i++) + ninput_items_required[i] = + (int) ceil((noutput_items * d_omega) + d_interp->ntaps()); +} + +gr_complex +gr_clock_recovery_mm_cc::slicer_0deg (gr_complex sample) +{ + float real=0, imag=0; + + if(sample.real() > 0) + real = 1; + if(sample.imag() > 0) + imag = 1; + return gr_complex(real,imag); +} + +gr_complex +gr_clock_recovery_mm_cc::slicer_45deg (gr_complex sample) +{ + float real= -1, imag = -1; + if(sample.real() > 0) + real=1; + if(sample.imag() > 0) + imag = 1; + return gr_complex(real,imag); +} + +/* + Modified Mueller and Muller clock recovery circuit + Based: + 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. +*/ + +static const int FUDGE = 16; + +int +gr_clock_recovery_mm_cc::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int ii = 0; // input index + int oo = 0; // output index + int ni = ninput_items[0] - d_interp->ntaps() - FUDGE; // don't use more input than this + + assert(d_mu >= 0.0); + assert(d_mu <= 1.0); + + float mm_val=0; + gr_complex u, x, y; + + while(oo < noutput_items && ii < ni) { + d_p_2T = d_p_1T; + d_p_1T = d_p_0T; + d_p_0T = d_interp->interpolate (&in[ii], d_mu); + + d_c_2T = d_c_1T; + d_c_1T = d_c_0T; + d_c_0T = slicer_0deg(d_p_0T); + + x = (d_c_0T - d_c_2T) * conj(d_p_1T); + y = (d_p_0T - d_p_2T) * conj(d_c_1T); + u = y - x; + mm_val = u.real(); + out[oo++] = d_p_0T; + + // limit mm_val + if (mm_val > 1.0) + mm_val = 1.0; + else if (mm_val < -1.0) + mm_val = -1.0; + + d_omega = d_omega + d_gain_omega * mm_val; + if (d_omega > d_max_omega) + d_omega = d_max_omega; + else if (d_omega < d_min_omega) + d_omega = d_min_omega; + + d_mu = d_mu + d_omega + d_gain_mu * mm_val; + ii += (int)floor(d_mu); + d_mu -= floor(d_mu); + + if(d_verbose) { + printf("%f\t%f\n", d_omega, d_mu); + } + + if (ii < 0) // clamp it. This should only happen with bogus input + ii = 0; + } + + if (ii > 0){ + if (ii > ninput_items[0]){ + fprintf(stderr, "gr_clock_recovery_mm_cc: ii > ninput_items[0] (%d > %d)\n", + ii, ninput_items[0]); + assert(0); + } + consume_each (ii); + } + + return oo; +} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h new file mode 100644 index 00000000..8a65ae4d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CLOCK_RECOVERY_MM_CC_H +#define INCLUDED_GR_CLOCK_RECOVERY_MM_CC_H + +#include +#include + +class gri_mmse_fir_interpolator_cc; + +class gr_clock_recovery_mm_cc; +typedef boost::shared_ptr gr_clock_recovery_mm_cc_sptr; + +// public constructor +gr_clock_recovery_mm_cc_sptr +gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit=0.001); + +/*! + * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output. + * \ingroup block + * + * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. + * ISBN 0-471-50275-8. + */ +class gr_clock_recovery_mm_cc : public gr_block +{ + public: + ~gr_clock_recovery_mm_cc (); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + float mu() const { return d_mu;} + float omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + void set_verbose (bool verbose) { d_verbose = verbose; } + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float mu) { d_mu = mu; } + void set_omega (float omega) { + d_omega = omega; + d_min_omega = omega*(1.0 - d_omega_relative_limit); + d_max_omega = omega*(1.0 + d_omega_relative_limit); + } + +protected: + gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limi); + + private: + float d_mu; + float d_omega; + float d_gain_omega; + float d_min_omega; // minimum allowed omega + float d_max_omega; // maximum allowed omeg + float d_omega_relative_limit; // used to compute min and max omega + float d_gain_mu; + gr_complex d_last_sample; + gri_mmse_fir_interpolator_cc *d_interp; + bool d_verbose; + + gr_complex d_p_2T; + gr_complex d_p_1T; + gr_complex d_p_0T; + + gr_complex d_c_2T; + gr_complex d_c_1T; + gr_complex d_c_0T; + + gr_complex slicer_0deg (gr_complex sample); + gr_complex slicer_45deg (gr_complex sample); + + friend gr_clock_recovery_mm_cc_sptr + gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i new file mode 100644 index 00000000..4db01aff --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,clock_recovery_mm_cc); + +gr_clock_recovery_mm_cc_sptr gr_make_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit); + +class gr_clock_recovery_mm_cc : public gr_sync_block +{ + private: + gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, + float gain_mu, float omega_relative_limit); + +public: + float mu() const { return d_mu;} + float omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float omega) { d_mu = mu; } + void set_omega (float omega) { d_omega = omega; + d_min_omega = omega*(1.0 - d_omega_relative_limit); + d_max_omega = omega*(1.0 + d_omega_relative_limit); + } + void set_verbose (bool verbose) { d_verbose = verbose; } +}; diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc new file mode 100644 index 00000000..1219df7b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define DEBUG_CR_MM_FF 0 // must be defined as 0 or 1 + +// Public constructor + +gr_clock_recovery_mm_ff_sptr +gr_make_clock_recovery_mm_ff(float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit) +{ + return gr_clock_recovery_mm_ff_sptr (new gr_clock_recovery_mm_ff (omega, + gain_omega, + mu, + gain_mu, + omega_relative_limit)); +} + +gr_clock_recovery_mm_ff::gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit) + : gr_block ("clock_recovery_mm_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_mu (mu), d_gain_omega(gain_omega), d_gain_mu(gain_mu), + d_last_sample(0), d_interp(new gri_mmse_fir_interpolator()), + d_logfile(0), d_omega_relative_limit(omega_relative_limit) +{ + if (omega < 1) + throw std::out_of_range ("clock rate must be > 0"); + if (gain_mu < 0 || gain_omega < 0) + throw std::out_of_range ("Gains must be non-negative"); + + set_omega(omega); // also sets min and max omega + set_relative_rate (1.0 / omega); + + if (DEBUG_CR_MM_FF) + d_logfile = fopen("cr_mm_ff.dat", "wb"); +} + +gr_clock_recovery_mm_ff::~gr_clock_recovery_mm_ff () +{ + delete d_interp; + + if (DEBUG_CR_MM_FF && d_logfile){ + fclose(d_logfile); + d_logfile = 0; + } +} + +void +gr_clock_recovery_mm_ff::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i=0; i < ninputs; i++) + ninput_items_required[i] = + (int) ceil((noutput_items * d_omega) + d_interp->ntaps()); +} + +static inline float +slice(float x) +{ + return x < 0 ? -1.0F : 1.0F; +} + +/* + * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. + * ISBN 0-471-50275-8. + */ +int +gr_clock_recovery_mm_ff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + int ii = 0; // input index + int oo = 0; // output index + float mm_val; + + while (oo < noutput_items){ + + // produce output sample + out[oo] = d_interp->interpolate (&in[ii], d_mu); + mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample; + d_last_sample = out[oo]; + + d_omega = d_omega + d_gain_omega * mm_val; + if (d_omega > d_max_omega) + d_omega = d_max_omega; + else if (d_omega < d_min_omega) + d_omega = d_min_omega; + + d_mu = d_mu + d_omega + d_gain_mu * mm_val; + + ii += (int) floor(d_mu); + d_mu = d_mu - floor(d_mu); + oo++; + + if (DEBUG_CR_MM_FF && d_logfile){ + fwrite(&d_omega, sizeof(d_omega), 1, d_logfile); + } + } + + consume_each (ii); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h new file mode 100644 index 00000000..e970bcce --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CLOCK_RECOVERY_MM_FF_H +#define INCLUDED_GR_CLOCK_RECOVERY_MM_FF_H + +#include +#include + +class gri_mmse_fir_interpolator; + +class gr_clock_recovery_mm_ff; +typedef boost::shared_ptr gr_clock_recovery_mm_ff_sptr; + +// public constructor +gr_clock_recovery_mm_ff_sptr +gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit=0.001); + +/*! + * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output. + * \ingroup block + * + * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. + * ISBN 0-471-50275-8. + */ +class gr_clock_recovery_mm_ff : public gr_block +{ + public: + ~gr_clock_recovery_mm_ff (); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + float mu() const { return d_mu;} + float omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float mu) { d_mu = mu; } + void set_omega (float omega){ + d_omega = omega; + d_min_omega = omega*(1.0 - d_omega_relative_limit); + d_max_omega = omega*(1.0 + d_omega_relative_limit); + } + +protected: + gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); + + private: + float d_mu; // fractional sample position [0.0, 1.0] + float d_omega; // nominal frequency + float d_min_omega; // minimum allowed omega + float d_max_omega; // maximum allowed omega + float d_gain_omega; // gain for adjusting omega + float d_gain_mu; // gain for adjusting mu + float d_last_sample; + gri_mmse_fir_interpolator *d_interp; + FILE *d_logfile; + float d_omega_relative_limit; // used to compute min and max omega + + friend gr_clock_recovery_mm_ff_sptr + gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i new file mode 100644 index 00000000..5b7bd45d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,clock_recovery_mm_ff); + +gr_clock_recovery_mm_ff_sptr gr_make_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit=0.001); + +class gr_clock_recovery_mm_ff : public gr_sync_block +{ + private: + gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); + +public: + float mu() const; + float omega() const; + float gain_mu() const; + float gain_omega() const; + + void set_gain_mu (float gain_mu); + void set_gain_omega (float gain_omega); + void set_mu (float omega); + void set_omega (float omega); +}; diff --git a/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc new file mode 100644 index 00000000..65fbbe93 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_complex_to_interleaved_short_sptr +gr_make_complex_to_interleaved_short () +{ + return gr_complex_to_interleaved_short_sptr (new gr_complex_to_interleaved_short ()); +} + +gr_complex_to_interleaved_short::gr_complex_to_interleaved_short () + : gr_sync_interpolator ("gr_complex_to_interleaved_short", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (short)), + 2) +{ +} + +int +gr_complex_to_interleaved_short::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]; + short *out = (short *) output_items[0]; + + for (int i = 0; i < noutput_items/2; i++){ + *out++ = (short) lrintf(in[i].real()); // FIXME saturate? + *out++ = (short) lrintf(in[i].imag()); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h new file mode 100644 index 00000000..1afca560 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_H +#define INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_H + +#include + +class gr_complex_to_interleaved_short; +typedef boost::shared_ptr + gr_complex_to_interleaved_short_sptr; + +gr_complex_to_interleaved_short_sptr +gr_make_complex_to_interleaved_short (); + +/*! + * \brief Convert stream of complex to a stream of interleaved shorts + * \ingroup converter + */ + +class gr_complex_to_interleaved_short : public gr_sync_interpolator +{ + friend gr_complex_to_interleaved_short_sptr gr_make_complex_to_interleaved_short (); + gr_complex_to_interleaved_short (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_H */ diff --git a/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i new file mode 100644 index 00000000..1b4b6baa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_interleaved_short) + +gr_complex_to_interleaved_short_sptr gr_make_complex_to_interleaved_short (); + +class gr_complex_to_interleaved_short : public gr_sync_interpolator +{ + gr_complex_to_interleaved_short (); +}; diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc new file mode 100644 index 00000000..727f44f0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc @@ -0,0 +1,199 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +// ---------------------------------------------------------------- + +gr_complex_to_float_sptr +gr_make_complex_to_float (unsigned int vlen) +{ + return gr_complex_to_float_sptr (new gr_complex_to_float (vlen)); +} + +gr_complex_to_float::gr_complex_to_float (unsigned int vlen) + : gr_sync_block ("complex_to_float", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 2, sizeof (float) * vlen)), + d_vlen(vlen) +{ +} + +int +gr_complex_to_float::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]; + float *out0 = (float *) output_items[0]; + float *out1 = (float *) output_items[1]; + int noi = noutput_items * d_vlen; + + switch (output_items.size ()){ + case 1: + for (int i = 0; i < noi; i++){ + out0[i] = in[i].real (); + } + break; + + case 2: + for (int i = 0; i < noi; i++){ + out0[i] = in[i].real (); + out1[i] = in[i].imag (); + } + break; + + default: + abort (); + } + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_real_sptr +gr_make_complex_to_real (unsigned int vlen) +{ + return gr_complex_to_real_sptr (new gr_complex_to_real (vlen)); +} + +gr_complex_to_real::gr_complex_to_real (unsigned int vlen) + : gr_sync_block ("complex_to_real", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ +} + +int +gr_complex_to_real::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + for (int i = 0; i < noi; i++){ + out[i] = in[i].real (); + } + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_imag_sptr +gr_make_complex_to_imag (unsigned int vlen) +{ + return gr_complex_to_imag_sptr (new gr_complex_to_imag (vlen)); +} + +gr_complex_to_imag::gr_complex_to_imag (unsigned int vlen) + : gr_sync_block ("complex_to_imag", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ +} + +int +gr_complex_to_imag::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + for (int i = 0; i < noi; i++){ + out[i] = in[i].imag (); + } + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_mag_sptr +gr_make_complex_to_mag (unsigned int vlen) +{ + return gr_complex_to_mag_sptr (new gr_complex_to_mag (vlen)); +} + +gr_complex_to_mag::gr_complex_to_mag (unsigned int vlen) + : gr_sync_block ("complex_to_mag", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ +} + +int +gr_complex_to_mag::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + for (int i = 0; i < noi; i++){ + out[i] = std::abs (in[i]); + } + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_arg_sptr +gr_make_complex_to_arg (unsigned int vlen) +{ + return gr_complex_to_arg_sptr (new gr_complex_to_arg (vlen)); +} + +gr_complex_to_arg::gr_complex_to_arg (unsigned int vlen) + : gr_sync_block ("complex_to_arg", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ +} + +int +gr_complex_to_arg::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + for (int i = 0; i < noi; i++){ + out[i] = std::arg (in[i]); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.h b/gnuradio-core/src/lib/general/gr_complex_to_xxx.h new file mode 100644 index 00000000..02a9fc8f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.h @@ -0,0 +1,137 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_COMPLEX_TO_XXX_H +#define INCLUDED_GR_COMPLEX_TO_XXX_H + +#include +#include + +class gr_complex_to_float; +class gr_complex_to_real; +class gr_complex_to_imag; +class gr_complex_to_mag; +class gr_complex_to_arg; + +typedef boost::shared_ptr gr_complex_to_float_sptr; +typedef boost::shared_ptr gr_complex_to_real_sptr; +typedef boost::shared_ptr gr_complex_to_imag_sptr; +typedef boost::shared_ptr gr_complex_to_mag_sptr; +typedef boost::shared_ptr gr_complex_to_arg_sptr; + +gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen=1); +gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen=1); +gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen=1); +gr_complex_to_mag_sptr gr_make_complex_to_mag (unsigned int vlen=1); +gr_complex_to_arg_sptr gr_make_complex_to_arg (unsigned int vlen=1); + +/*! + * \brief convert a stream of gr_complex to 1 or 2 streams of float + * \ingroup converter + * \param vlen vector len (default 1) + */ +class gr_complex_to_float : public gr_sync_block +{ + friend gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen); + gr_complex_to_float (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, real out (float) + * \ingroup converter + * \param vlen vector len (default 1) + */ +class gr_complex_to_real : public gr_sync_block +{ + friend gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen); + gr_complex_to_real (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, imaginary out (float) + * \ingroup converter + * \param vlen vector len (default 1) + */ +class gr_complex_to_imag : public gr_sync_block +{ + friend gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen); + gr_complex_to_imag (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, magnitude out (float) + * \ingroup converter + * \param vlen vector len (default 1) + */ +class gr_complex_to_mag : public gr_sync_block +{ + friend gr_complex_to_mag_sptr gr_make_complex_to_mag (unsigned int vlen); + gr_complex_to_mag (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, angle out (float) + * \ingroup converter + * \param vlen vector len (default 1) + */ +class gr_complex_to_arg : public gr_sync_block +{ + friend gr_complex_to_arg_sptr gr_make_complex_to_arg (unsigned int vlen); + gr_complex_to_arg (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_COMPLEX_TO_XXX_H */ diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.i b/gnuradio-core/src/lib/general/gr_complex_to_xxx.i new file mode 100644 index 00000000..06f1020a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.i @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_float); +gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen=1); +class gr_complex_to_float : public gr_sync_block +{ + gr_complex_to_float (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_real); +gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen=1); +class gr_complex_to_real : public gr_sync_block +{ + gr_complex_to_real (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_imag); +gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen=1); +class gr_complex_to_imag : public gr_sync_block +{ + gr_complex_to_imag (unsigned int vlen); +} + ; +GR_SWIG_BLOCK_MAGIC(gr,complex_to_mag); +gr_complex_to_mag_sptr gr_make_complex_to_mag (unsigned int vlen=1); +class gr_complex_to_mag : public gr_sync_block +{ + gr_complex_to_mag (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_arg); +gr_complex_to_arg_sptr gr_make_complex_to_arg (unsigned int vlen=1); +class gr_complex_to_arg : public gr_sync_block +{ + gr_complex_to_arg (unsigned int vlen); +}; + diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.cc b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc new file mode 100644 index 00000000..50e25efa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_conjugate_cc_sptr +gr_make_conjugate_cc () +{ + return gr_conjugate_cc_sptr (new gr_conjugate_cc ()); +} + +gr_conjugate_cc::gr_conjugate_cc () + : gr_sync_block ("conjugate_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ +} + +int +gr_conjugate_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + int size = noutput_items; + + while (size >= 8){ + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + size -= 8; + } + + while (size-- > 0) + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.h b/gnuradio-core/src/lib/general/gr_conjugate_cc.h new file mode 100644 index 00000000..f1551b86 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifndef INCLUDED_GR_CONJUGATE_CC_H +#define INCLUDED_GR_CONJUGATE_CC_H + +#include + +class gr_conjugate_cc; +typedef boost::shared_ptr gr_conjugate_cc_sptr; + +gr_conjugate_cc_sptr gr_make_conjugate_cc (); + +/*! + * \brief output = complex conjugate of input + * \ingroup block + */ +class gr_conjugate_cc : public gr_sync_block +{ + friend gr_conjugate_cc_sptr gr_make_conjugate_cc (); + + gr_conjugate_cc (); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.i b/gnuradio-core/src/lib/general/gr_conjugate_cc.i new file mode 100644 index 00000000..efafa84c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +GR_SWIG_BLOCK_MAGIC(gr,conjugate_cc) + +gr_conjugate_cc_sptr gr_make_conjugate_cc (); + +class gr_conjugate_cc : public gr_sync_block +{ + private: + gr_conjugate_cc (); +}; diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc new file mode 100644 index 00000000..5b4f719d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +using std::cout; +using std::endl; + +static const bool compute_EVM = false; + +gr_constellation_decoder_cb_sptr +gr_make_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out) +{ + return gr_constellation_decoder_cb_sptr + (new gr_constellation_decoder_cb(sym_position, sym_value_out)); +} + +gr_constellation_decoder_cb:: +gr_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out) + : gr_sync_block ("constellation_decoder_cb", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ + if (!set_constellation(sym_position,sym_value_out)) + throw std::invalid_argument("constellation_decoder_cb"); +} + + +gr_constellation_decoder_cb::~gr_constellation_decoder_cb(){} + + +bool +gr_constellation_decoder_cb::set_constellation(const std::vector &sym_position, + const std::vector &sym_value_out) +{ + if (sym_position.size() != sym_value_out.size()) + return false; + + if (sym_position.size()<1) + return false; + + d_sym_position = sym_position; + d_sym_value_out = sym_value_out; + return true; +} + + +int +gr_constellation_decoder_cb::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]; + unsigned char *out = (unsigned char *) output_items[0]; + unsigned int table_size = d_sym_value_out.size(); + unsigned int min_index = 0; + float min_euclid_dist = 0; + float euclid_dist = 0; + double total_error = 0; + + for(int i = 0; i < noutput_items; i++){ + min_euclid_dist = norm(in[i] - d_sym_position[0]); + min_index = 0; + for (unsigned int j = 1; j < table_size; j++){ + euclid_dist = norm(in[i] - d_sym_position[j]); + if (euclid_dist < min_euclid_dist){ + min_euclid_dist = euclid_dist; + min_index = j; + } + } + + out[i] = d_sym_value_out[min_index]; + + if (compute_EVM) + total_error += sqrtf(min_euclid_dist); + } + + if (compute_EVM){ + double mean = total_error / noutput_items; + double rms = sqrt(mean * mean); + fprintf(stderr, "EVM = %8.4f\n", rms); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h new file mode 100644 index 00000000..2cc16c57 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CONSTELLATION_DECODER_CB_H +#define INCLUDED_GR_CONSTELLATION_DECODER_CB_H + +#include +#include + +class gr_constellation_decoder_cb; +typedef boost::shared_ptr gr_constellation_decoder_cb_sptr; + +gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + + +class gr_constellation_decoder_cb : public gr_sync_block +{ + + private: + std::vector d_sym_position; + std::vector d_sym_value_out; + + friend gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, const std::vector &sym_value_out); + + gr_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); //constructor + + public: + bool set_constellation(const std::vector &sym_position, + const std::vector &sym_value_out); + + ~gr_constellation_decoder_cb(); //destructor + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i new file mode 100644 index 00000000..ba1e38f6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,constellation_decoder_cb) + +gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + +class gr_constellation_decoder_cb : public gr_sync_block +{ + private: + gr_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + + friend gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + + public: + int set_constellation(const std::vector &sym_position, + const std::vector &sym_value_out); + ~gr_constellation_decoder_cb(); +}; diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc new file mode 100644 index 00000000..0f259860 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc @@ -0,0 +1,129 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define VERBOSE 0 + + +gr_correlate_access_code_bb_sptr +gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) +{ + return gr_correlate_access_code_bb_sptr (new gr_correlate_access_code_bb (access_code, threshold)); +} + + +gr_correlate_access_code_bb::gr_correlate_access_code_bb ( + const std::string &access_code, int threshold) + : gr_sync_block ("correlate_access_code_bb", + gr_make_io_signature (1, 1, sizeof(char)), + gr_make_io_signature (1, 1, sizeof(char))), + d_data_reg(0), d_flag_reg(0), d_flag_bit(0), d_mask(0), + d_threshold(threshold), d_flip(0) + +{ + if (!set_access_code(access_code)){ + fprintf(stderr, "gr_correlate_access_code_bb: access_code is > 64 bits\n"); + throw std::out_of_range ("access_code is > 64 bits"); + } +} + +gr_correlate_access_code_bb::~gr_correlate_access_code_bb () +{ +} + +bool +gr_correlate_access_code_bb::set_access_code( + const std::string &access_code) +{ + unsigned len = access_code.length(); // # of bytes in string + if (len > 64) + return false; + + // set len top bits to 1. + d_mask = ((~0ULL) >> (64 - len)) << (64 - len); + + d_flag_bit = 1LL << (64 - len); // Where we or-in new flag values. + // new data always goes in 0x0000000000000001 + d_access_code = 0; + for (unsigned i=0; i < 64; i++){ + d_access_code <<= 1; + if (i < len) + d_access_code |= access_code[i] & 1; // look at LSB only + } + + return true; +} + +int +gr_correlate_access_code_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++){ + + // compute output value + unsigned int t = 0; + + t |= d_flip ^ (((d_data_reg >> 63) & 0x1) << 0); + t |= ((d_flag_reg >> 63) & 0x1) << 1; // flag bit + out[i] = t; + + // 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 or its compelement + new_flag = (nwrong <= d_threshold) || (nwrong >= (64-d_threshold)); + +#if 0 + if(new_flag) { + printf("%llx ==> %llx : d_flip=%u\n", d_access_code, d_data_reg, d_flip); + } +#endif + + // shift in new data and new flag + d_data_reg = (d_data_reg << 1) | (in[i] & 0x1); + d_flag_reg = (d_flag_reg << 1); + if (new_flag) { + d_flag_reg |= d_flag_bit; + d_flip = nwrong >= (64-d_threshold); // flip bits if this is true + } + } + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h new file mode 100644 index 00000000..519258ca --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H +#define INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H + +#include +#include + +class gr_correlate_access_code_bb; +typedef boost::shared_ptr gr_correlate_access_code_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 + */ +gr_correlate_access_code_bb_sptr +gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup block + * + * input: stream of bits, 1 bit per input byte (data in LSB) + * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) + * + * Each output byte contains two valid bits, the data bit, and the + * flag bit. The LSB (bit 0) is the data bit, and is the original + * input data, delayed 64 bits. Bit 1 is the + * flag bit and is 1 if the corresponding data bit is the first data + * bit following the access code. Otherwise the flag bit is 0. + */ +class gr_correlate_access_code_bb : public gr_sync_block +{ + friend gr_correlate_access_code_bb_sptr + gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + 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_flag_reg; // keep track of decisions + unsigned long long d_flag_bit; // mask containing 1 bit which is location of new flag + 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_flip; // flip bits if 180 degress out of sync + + + protected: + gr_correlate_access_code_bb(const std::string &access_code, int threshold); + + public: + ~gr_correlate_access_code_bb(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + + /*! + * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" + */ + bool set_access_code (const std::string &access_code); +}; + +#endif /* INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i new file mode 100644 index 00000000..688f3f69 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,correlate_access_code_bb); + +/*! + * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" + * \param threshold maximum number of bits that may be wrong + */ +gr_correlate_access_code_bb_sptr +gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) + throw(std::out_of_range); + +/*! + * \brief Examine input for specified access code, one bit at a time. + * \ingroup block + * + * input: stream of bits, 1 bit per input byte (data in LSB) + * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) + * + * Each output byte contains two valid bits, the data bit, and the + * flag bit. The LSB (bit 0) is the data bit, and is the original + * input data, delayed 64 bits. Bit 1 is the + * flag bit and is 1 if the corresponding data bit is the first data + * bit following the access code. Otherwise the flag bit is 0. + */ +class gr_correlate_access_code_bb : public gr_sync_block +{ + friend gr_correlate_access_code_bb_sptr + gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + protected: + gr_correlate_access_code_bb(const std::string &access_code, int threshold); + + public: + ~gr_correlate_access_code_bb(); + + /*! + * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" + */ + bool set_access_code (const std::string &access_code); +}; diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc b/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc new file mode 100644 index 00000000..4ad627f0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#define M_TWOPI (2*M_PI) + +gr_costas_loop_cc_sptr +gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument) +{ + return gr_costas_loop_cc_sptr (new gr_costas_loop_cc (alpha, beta, + max_freq, min_freq, + order)); +} + +gr_costas_loop_cc::gr_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument) + : gr_sync_block ("costas_loop_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2), + d_order(order), d_phase_detector(0) +{ + switch(d_order) { + case 2: + d_phase_detector = &gr_costas_loop_cc::phase_detector_2; + break; + + case 4: + d_phase_detector = &gr_costas_loop_cc::phase_detector_4; + break; + + default: + throw std::invalid_argument("order must be 2 or 4"); + break; + } +} + + +float +gr_costas_loop_cc::phase_detector_4(gr_complex sample) const +{ + + return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - + (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); +} + +float +gr_costas_loop_cc::phase_detector_2(gr_complex sample) const +{ + return (sample.real()*sample.imag()); +} + +int +gr_costas_loop_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + float error; + gr_complex nco_out; + + for (int i = 0; i < noutput_items; i++){ + nco_out = gr_expj(-d_phase); + optr[i] = iptr[i] * nco_out; + + error = (*this.*d_phase_detector)(optr[i]); + + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_freq + d_alpha * error; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.h b/gnuradio-core/src/lib/general/gr_costas_loop_cc.h new file mode 100644 index 00000000..4672c094 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_costas_loop_cc.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef INCLUDED_GR_COSTAS_LOOP_CC_H +#define INCLUDED_GR_COSTAS_LOOP_CC_H + +#include +#include + +class gr_costas_loop_cc; +typedef boost::shared_ptr gr_costas_loop_cc_sptr; + +gr_costas_loop_cc_sptr +gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + +/*! + * \brief Carrier tracking PLL for QPSK + * input: complex; output: complex + * + * \p order must be 2 or 4. + */ +class gr_costas_loop_cc : public gr_sync_block +{ + friend gr_costas_loop_cc_sptr gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + float d_alpha, d_beta, d_max_freq, d_min_freq, d_phase, d_freq; + int d_order; + + gr_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + float phase_detector_4(gr_complex sample) const; // for QPSK + float phase_detector_2(gr_complex sample) const; // for BPSK + float (gr_costas_loop_cc::*d_phase_detector)(gr_complex sample) const; + +public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.i b/gnuradio-core/src/lib/general/gr_costas_loop_cc.i new file mode 100644 index 00000000..85d2ada5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_costas_loop_cc.i @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,costas_loop_cc); + +gr_costas_loop_cc_sptr +gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + +class gr_costas_loop_cc : public gr_sync_block +{ + private: + gr_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, int order); +}; diff --git a/gnuradio-core/src/lib/general/gr_count_bits.cc b/gnuradio-core/src/lib/general/gr_count_bits.cc new file mode 100644 index 00000000..cd51ce8a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_count_bits.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +/* + * these are slow and obvious. If you need something faster, fix these + */ + +// return number of set bits in the low 8 bits of x +unsigned int +gr_count_bits8 (unsigned int x) +{ + int count = 0; + + for (int i = 0; i < 8; i++) + if (x & (1 << i)) + count++; + + return count; +} + +// return number of set bits in the low 16 bits of x +unsigned int +gr_count_bits16 (unsigned int x) +{ + int count = 0; + + for (int i = 0; i < 16; i++) + if (x & (1 << i)) + count++; + + return count; + +} + + +#if 0 // slow and obvious + +// return number of set bits in the low 32 bits of x +unsigned int +gr_count_bits32 (unsigned int x) +{ + int count = 0; + + for (int i = 0; i < 32; i++) + if (x & (1 << i)) + count++; + + return count; +} + +#else // fast and not so obvious + +// return number of set bits in the low 32 bits of x +unsigned int +gr_count_bits32 (unsigned int x) +{ + unsigned res = (x & 0x55555555) + ((x >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +#endif + + +// return number of set bits in the low 64 bits of x +unsigned int +gr_count_bits64 (unsigned long long x) +{ + return gr_count_bits32((x >> 32) & 0xffffffff) + gr_count_bits32(x & 0xffffffff); +} diff --git a/gnuradio-core/src/lib/general/gr_count_bits.h b/gnuradio-core/src/lib/general/gr_count_bits.h new file mode 100644 index 00000000..b0e83c83 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_count_bits.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_COUNT_BITS_H_ +#define _GR_COUNT_BITS_H_ + +unsigned int gr_count_bits8(unsigned int x); // return number of set bits in the low 8 bits of x +unsigned int gr_count_bits16(unsigned int x); // return number of set bits in the low 16 bits of x +unsigned int gr_count_bits32(unsigned int x); // return number of set bits in the low 32 bits of x +unsigned int gr_count_bits64(unsigned long long int x); + +#endif /* _GR_COUNT_BITS_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_crc32.cc b/gnuradio-core/src/lib/general/gr_crc32.cc new file mode 100644 index 00000000..3b0ebd40 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_crc32.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * See also ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-V42] for a formal specification. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + + +// Automatically generated CRC function +// polynomial: 0x104C11DB7 +unsigned int +gr_update_crc32(unsigned int crc, const unsigned char *data, size_t len) +{ + static const unsigned int table[256] = { + 0x00000000U,0x04C11DB7U,0x09823B6EU,0x0D4326D9U, + 0x130476DCU,0x17C56B6BU,0x1A864DB2U,0x1E475005U, + 0x2608EDB8U,0x22C9F00FU,0x2F8AD6D6U,0x2B4BCB61U, + 0x350C9B64U,0x31CD86D3U,0x3C8EA00AU,0x384FBDBDU, + 0x4C11DB70U,0x48D0C6C7U,0x4593E01EU,0x4152FDA9U, + 0x5F15ADACU,0x5BD4B01BU,0x569796C2U,0x52568B75U, + 0x6A1936C8U,0x6ED82B7FU,0x639B0DA6U,0x675A1011U, + 0x791D4014U,0x7DDC5DA3U,0x709F7B7AU,0x745E66CDU, + 0x9823B6E0U,0x9CE2AB57U,0x91A18D8EU,0x95609039U, + 0x8B27C03CU,0x8FE6DD8BU,0x82A5FB52U,0x8664E6E5U, + 0xBE2B5B58U,0xBAEA46EFU,0xB7A96036U,0xB3687D81U, + 0xAD2F2D84U,0xA9EE3033U,0xA4AD16EAU,0xA06C0B5DU, + 0xD4326D90U,0xD0F37027U,0xDDB056FEU,0xD9714B49U, + 0xC7361B4CU,0xC3F706FBU,0xCEB42022U,0xCA753D95U, + 0xF23A8028U,0xF6FB9D9FU,0xFBB8BB46U,0xFF79A6F1U, + 0xE13EF6F4U,0xE5FFEB43U,0xE8BCCD9AU,0xEC7DD02DU, + 0x34867077U,0x30476DC0U,0x3D044B19U,0x39C556AEU, + 0x278206ABU,0x23431B1CU,0x2E003DC5U,0x2AC12072U, + 0x128E9DCFU,0x164F8078U,0x1B0CA6A1U,0x1FCDBB16U, + 0x018AEB13U,0x054BF6A4U,0x0808D07DU,0x0CC9CDCAU, + 0x7897AB07U,0x7C56B6B0U,0x71159069U,0x75D48DDEU, + 0x6B93DDDBU,0x6F52C06CU,0x6211E6B5U,0x66D0FB02U, + 0x5E9F46BFU,0x5A5E5B08U,0x571D7DD1U,0x53DC6066U, + 0x4D9B3063U,0x495A2DD4U,0x44190B0DU,0x40D816BAU, + 0xACA5C697U,0xA864DB20U,0xA527FDF9U,0xA1E6E04EU, + 0xBFA1B04BU,0xBB60ADFCU,0xB6238B25U,0xB2E29692U, + 0x8AAD2B2FU,0x8E6C3698U,0x832F1041U,0x87EE0DF6U, + 0x99A95DF3U,0x9D684044U,0x902B669DU,0x94EA7B2AU, + 0xE0B41DE7U,0xE4750050U,0xE9362689U,0xEDF73B3EU, + 0xF3B06B3BU,0xF771768CU,0xFA325055U,0xFEF34DE2U, + 0xC6BCF05FU,0xC27DEDE8U,0xCF3ECB31U,0xCBFFD686U, + 0xD5B88683U,0xD1799B34U,0xDC3ABDEDU,0xD8FBA05AU, + 0x690CE0EEU,0x6DCDFD59U,0x608EDB80U,0x644FC637U, + 0x7A089632U,0x7EC98B85U,0x738AAD5CU,0x774BB0EBU, + 0x4F040D56U,0x4BC510E1U,0x46863638U,0x42472B8FU, + 0x5C007B8AU,0x58C1663DU,0x558240E4U,0x51435D53U, + 0x251D3B9EU,0x21DC2629U,0x2C9F00F0U,0x285E1D47U, + 0x36194D42U,0x32D850F5U,0x3F9B762CU,0x3B5A6B9BU, + 0x0315D626U,0x07D4CB91U,0x0A97ED48U,0x0E56F0FFU, + 0x1011A0FAU,0x14D0BD4DU,0x19939B94U,0x1D528623U, + 0xF12F560EU,0xF5EE4BB9U,0xF8AD6D60U,0xFC6C70D7U, + 0xE22B20D2U,0xE6EA3D65U,0xEBA91BBCU,0xEF68060BU, + 0xD727BBB6U,0xD3E6A601U,0xDEA580D8U,0xDA649D6FU, + 0xC423CD6AU,0xC0E2D0DDU,0xCDA1F604U,0xC960EBB3U, + 0xBD3E8D7EU,0xB9FF90C9U,0xB4BCB610U,0xB07DABA7U, + 0xAE3AFBA2U,0xAAFBE615U,0xA7B8C0CCU,0xA379DD7BU, + 0x9B3660C6U,0x9FF77D71U,0x92B45BA8U,0x9675461FU, + 0x8832161AU,0x8CF30BADU,0x81B02D74U,0x857130C3U, + 0x5D8A9099U,0x594B8D2EU,0x5408ABF7U,0x50C9B640U, + 0x4E8EE645U,0x4A4FFBF2U,0x470CDD2BU,0x43CDC09CU, + 0x7B827D21U,0x7F436096U,0x7200464FU,0x76C15BF8U, + 0x68860BFDU,0x6C47164AU,0x61043093U,0x65C52D24U, + 0x119B4BE9U,0x155A565EU,0x18197087U,0x1CD86D30U, + 0x029F3D35U,0x065E2082U,0x0B1D065BU,0x0FDC1BECU, + 0x3793A651U,0x3352BBE6U,0x3E119D3FU,0x3AD08088U, + 0x2497D08DU,0x2056CD3AU,0x2D15EBE3U,0x29D4F654U, + 0xC5A92679U,0xC1683BCEU,0xCC2B1D17U,0xC8EA00A0U, + 0xD6AD50A5U,0xD26C4D12U,0xDF2F6BCBU,0xDBEE767CU, + 0xE3A1CBC1U,0xE760D676U,0xEA23F0AFU,0xEEE2ED18U, + 0xF0A5BD1DU,0xF464A0AAU,0xF9278673U,0xFDE69BC4U, + 0x89B8FD09U,0x8D79E0BEU,0x803AC667U,0x84FBDBD0U, + 0x9ABC8BD5U,0x9E7D9662U,0x933EB0BBU,0x97FFAD0CU, + 0xAFB010B1U,0xAB710D06U,0xA6322BDFU,0xA2F33668U, + 0xBCB4666DU,0xB8757BDAU,0xB5365D03U,0xB1F740B4U, + }; + + while (len > 0) + { + crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8); + data++; + len--; + } + return crc; +} + +unsigned int +gr_update_crc32(unsigned int crc, const std::string s) +{ + return gr_update_crc32(crc, (const unsigned char *) s.data(), s.size()); +} + +unsigned int +gr_crc32(const unsigned char *buf, size_t len) +{ + return gr_update_crc32(0xffffffff, buf, len) ^ 0xffffffff; +} + +unsigned int +gr_crc32(const std::string s) +{ + return gr_crc32((const unsigned char *) s.data(), s.size()); +} diff --git a/gnuradio-core/src/lib/general/gr_crc32.h b/gnuradio-core/src/lib/general/gr_crc32.h new file mode 100644 index 00000000..2d6fdc85 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_crc32.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CRC32_H +#define INCLUDED_GR_CRC32_H + +#include +#include + +/*! + * \brief update running CRC-32 + * + * Update a running CRC with the bytes buf[0..len-1] The CRC should be + * initialized to all 1's, and the transmitted value is the 1's + * complement of the final running CRC. The resulting CRC should be + * transmitted in big endian order. + */ +unsigned int gr_update_crc32(unsigned int crc, const unsigned char *buf, int len); +unsigned int gr_update_crc32(unsigned int crc, const std::string buf); + +unsigned int gr_crc32(const unsigned char *buf, int len); +unsigned int gr_crc32(const std::string buf); + +#endif /* INCLUDED_CRC32_H */ diff --git a/gnuradio-core/src/lib/general/gr_crc32.i b/gnuradio-core/src/lib/general/gr_crc32.i new file mode 100644 index 00000000..79e1d086 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_crc32.i @@ -0,0 +1,27 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%rename(update_crc32) gr_update_crc32; +%rename(crc32) gr_crc32; + +unsigned int gr_update_crc32(unsigned int crc, const std::string buf); +unsigned int gr_crc32(const std::string buf); diff --git a/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc new file mode 100644 index 00000000..7ad31cbd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static float ctcss_tones[] = { + 67.0, 71.9, 74.4, 77.0, 79.7, 82.5, 85.4, 88.5, 91.5, 94.8, + 97.4, 100.0, 103.5, 107.2, 110.9, 114.8, 118.8, 123.0, 127.3, 131.8, + 136.5, 141.3, 146.2, 151.4, 156.7, 162.2, 167.9, 173.8, 179.9, 186.2, + 192.8, 203.5, 210.7, 218.1, 225.7, 233.6, 241.8, 250.3 +}; + +static int max_tone_index = 37; + +gr_ctcss_squelch_ff_sptr +gr_make_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate) +{ + return gr_ctcss_squelch_ff_sptr(new gr_ctcss_squelch_ff(rate, freq, level, len, ramp, gate)); +} + +int gr_ctcss_squelch_ff::find_tone(float freq) +{ + for (int i = 0; i <= max_tone_index; i++) + if (ctcss_tones[i] == freq) // FIXME: make almost equal + return i; + + return -1; +} + +gr_ctcss_squelch_ff::gr_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate) : + gr_squelch_base_ff("ctcss_squelch_ff", ramp, gate) +{ + d_freq = freq; + d_level = level; + + // Default is 100 ms detection time + if (len == 0) + d_len = (int)(rate/10.0); + else + d_len = len; + + int i = find_tone(freq); + + // Non-standard tones or edge tones get 2% guard band, otherwise + // guards are set at adjacent ctcss tone frequencies + float f_l, f_r; + if (i == -1 || i == 0) + f_l = freq*0.98; + else + f_l = ctcss_tones[i-1]; + + if (i == -1 || i == max_tone_index) + f_r = freq*1.02; + else + f_r = ctcss_tones[i+1]; + + d_goertzel_l = gri_goertzel(rate, d_len, f_l); + d_goertzel_c = gri_goertzel(rate, d_len, freq); + d_goertzel_r = gri_goertzel(rate, d_len, f_r); + + d_mute = true; +} + +std::vector gr_ctcss_squelch_ff::squelch_range() const +{ + std::vector r(3); + r[0] = 0.0; + r[1] = 1.0; + r[2] = (r[1]-r[0])/100; // step size + + return r; +} + +void gr_ctcss_squelch_ff::update_state(const float &in) +{ + d_goertzel_l.input(in); + d_goertzel_c.input(in); + d_goertzel_r.input(in); + + float d_out_l, d_out_c, d_out_r; + if (d_goertzel_c.ready()) { + d_out_l = abs(d_goertzel_l.output()); + d_out_c = abs(d_goertzel_c.output()); + d_out_r = abs(d_goertzel_r.output()); + + //printf("d_out_l=%f d_out_c=%f d_out_r=%f\n", d_out_l, d_out_c, d_out_r); + d_mute = (d_out_c < d_level || d_out_c < d_out_l || d_out_c < d_out_r); + } +} diff --git a/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h new file mode 100644 index 00000000..337e5cab --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CTCSS_SQUELCH_FF_H +#define INCLUDED_GR_CTCSS_SQUELCH_FF_H + +#include +#include + +class gr_ctcss_squelch_ff; +typedef boost::shared_ptr gr_ctcss_squelch_ff_sptr; + +gr_ctcss_squelch_ff_sptr +gr_make_ctcss_squelch_ff(int rate, float freq, float level=0.01, int len=0, int ramp=0, bool gate=false); + +/*! + * \brief gate or zero output if ctcss tone not present + * \ingroup block + */ +class gr_ctcss_squelch_ff : public gr_squelch_base_ff +{ +private: + float d_freq; + float d_level; + int d_len; + bool d_mute; + + gri_goertzel d_goertzel_l; + gri_goertzel d_goertzel_c; + gri_goertzel d_goertzel_r; + + friend gr_ctcss_squelch_ff_sptr gr_make_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate); + gr_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate); + + int find_tone(float freq); + +protected: + virtual void update_state(const float &in); + virtual bool mute() const { return d_mute; } + +public: + std::vector squelch_range() const; + float level() const { return d_level; } + void set_level(float level) { d_level = level; } + int len() const { return d_len; } +}; + +#endif /* INCLUDED_GR_CTCSS_SQUELCH_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i new file mode 100644 index 00000000..6d32c7d0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,ctcss_squelch_ff); + +%include gr_squelch_base_ff.i + +gr_ctcss_squelch_ff_sptr +gr_make_ctcss_squelch_ff(int rate, float freq, float level=0.01, int len=0, int ramp=0, bool gate=false); + +class gr_ctcss_squelch_ff : public gr_squelch_base_ff +{ + gr_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate); + +public: + std::vector squelch_range() const; + float level() const { return d_level; } + void set_level(float level) { d_level = level; } + int len() const { return d_len; } +}; diff --git a/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.cc b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.cc new file mode 100644 index 00000000..1f0bc015 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.cc @@ -0,0 +1,195 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#define M_TWOPI (2*M_PI) + +gr_dd_mpsk_sync_cc_sptr +gr_make_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu) +{ + return gr_dd_mpsk_sync_cc_sptr (new gr_dd_mpsk_sync_cc (alpha, beta, max_freq, min_freq,ref_phase, + omega,gain_omega,mu,gain_mu)); +} + +gr_dd_mpsk_sync_cc::gr_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, + float ref_phase, + float omega, float gain_omega, float mu, float gain_mu) + : gr_block ("dd_mpsk_sync_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_ref_phase(ref_phase),d_omega(omega), d_gain_omega(gain_omega), + d_mu(mu), d_gain_mu(gain_mu), + d_phase(0), d_freq((max_freq+min_freq)/2), d_last_sample(0), + d_interp(new gri_mmse_fir_interpolator_cc()), + d_dl_idx(0) +{ + if (omega <= 0.0) + throw std::out_of_range ("clock rate must be > 0"); + if (gain_mu < 0 || gain_omega < 0) + throw std::out_of_range ("Gains must be non-negative"); + + assert(d_interp->ntaps() <= DLLEN); + + // zero double length delay line. + for (unsigned int i = 0; i < 2 * DLLEN; i++) + d_dl[i] = gr_complex(0.0,0.0); +} + +gr_dd_mpsk_sync_cc::~gr_dd_mpsk_sync_cc() +{ + delete d_interp; +} + +float +gr_dd_mpsk_sync_cc::phase_detector(gr_complex sample,float ref_phase) +{ + return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - + (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); +} + +void +gr_dd_mpsk_sync_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i=0; i < ninputs; i++) + ninput_items_required[i] = + (int) ceil((noutput_items * d_omega) + d_interp->ntaps()); +} +gr_complex +gr_dd_mpsk_sync_cc::slicer_45deg (gr_complex sample) +{ + float real,imag; + if(sample.real() > 0) + real=1; + else + real=-1; + if(sample.imag() > 0) + imag = 1; + else + imag = -1; + return gr_complex(real,imag); +} + +gr_complex +gr_dd_mpsk_sync_cc::slicer_0deg (gr_complex sample) +{ + gr_complex out; + if( fabs(sample.real()) > fabs(sample.imag()) ) { + if(sample.real() > 0) + return gr_complex(1.0,0.0); + else + return gr_complex(-1.0,0.0); + } + else { + if(sample.imag() > 0) + return gr_complex(0.0, 1.0); + else + return gr_complex(0.0, -1.0); + } +} + +int +gr_dd_mpsk_sync_cc::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int ii, oo; + ii = 0; oo = 0; + + float error; + float t_imag, t_real; + gr_complex nco_out; + float mm_val; + + while (oo < noutput_items) { + // + // generate an output sample by interpolating between the carrier + // tracked samples in the delay line. d_mu, the fractional + // interpolation amount (in [0.0, 1.0]) is controlled by the + // symbol timing loop below. + // + out[oo] = d_interp->interpolate (&d_dl[d_dl_idx], d_mu); + + error = phase_detector(out[oo], d_ref_phase); + + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_alpha * error; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + + mm_val = real(d_last_sample * slicer_0deg(out[oo]) - out[oo] * slicer_0deg(d_last_sample)); + d_last_sample = out[oo]; + + d_omega = d_omega + d_gain_omega * mm_val; + d_mu = d_mu + d_omega + d_gain_mu * mm_val; + + while(d_mu >= 1.0) { + // + // Generate more carrier tracked samples for the delay line + // + d_mu -= 1.0; + gr_sincosf(d_phase, &t_imag, &t_real); + nco_out = gr_complex(t_real, -t_imag); + gr_complex new_sample = in[ii] * nco_out; + + d_dl[d_dl_idx] = new_sample; // overwrite oldest sample + d_dl[(d_dl_idx + DLLEN)] = new_sample; // and second copy + d_dl_idx = (d_dl_idx+1) % DLLEN; // point to the new oldest sample + d_phase = d_phase + d_freq; + ii++; + } + oo++; + printf("%f\t%f\t%f\t%f\t%f\n",d_mu,d_omega,mm_val,d_freq,d_phase); + //printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\n",mple).real(),slicer_0deg(d_last_sample).imag(),mm_val,d_omega,d_mu); + } + + assert(ii <= ninput_items[0]); + + consume_each (ii); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h new file mode 100644 index 00000000..fdc25614 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DD_MPSK_SYNC_CC_H +#define INCLUDED_GR_DD_MPSK_SYNC_CC_H + +#include + +class gri_mmse_fir_interpolator_cc; + +class gr_dd_mpsk_sync_cc; +typedef boost::shared_ptr gr_dd_mpsk_sync_cc_sptr; + +gr_dd_mpsk_sync_cc_sptr +gr_make_dd_mpsk_sync_cc (float alpha, float beta, + float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); + +/*! + * \brief Decision directed M-PSK synchronous demod + * This block performs joint carrier tracking and symbol timing recovery. + * + * input: complex baseband; output: properly timed complex samples ready for slicing. + * + * N.B, at this point, it handles only QPSK. + */ + +class gr_dd_mpsk_sync_cc : public gr_block +{ + friend gr_dd_mpsk_sync_cc_sptr gr_make_dd_mpsk_sync_cc (float alpha, float beta, + float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); +public: + ~gr_dd_mpsk_sync_cc (); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + float mu() const { return d_mu;} + float omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float mu) { d_mu = mu; } + void set_omega (float omega) { d_omega = omega; } + +protected: + gr_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +private: + static const unsigned int DLLEN = 8; // delay line length. + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_ref_phase; + float d_omega, d_gain_omega, d_mu, d_gain_mu; + float d_phase, d_freq; + gr_complex slicer_45deg (gr_complex sample); + gr_complex slicer_0deg (gr_complex sample); + gr_complex d_last_sample; + gri_mmse_fir_interpolator_cc *d_interp; + + gr_complex d_dl[2 * DLLEN]; // Holds post carrier tracking samples. + // double length delay line to avoid wraps. + unsigned int d_dl_idx; // indexes oldest sample in delay line. + + float phase_detector(gr_complex sample,float ref_phase); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.i b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.i new file mode 100644 index 00000000..3bab9e2f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,dd_mpsk_sync_cc) + + gr_dd_mpsk_sync_cc_sptr gr_make_dd_mpsk_sync_cc (float alpha, float beta, + float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); + +class gr_dd_mpsk_sync_cc : public gr_block +{ + private: + gr_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); +}; diff --git a/gnuradio-core/src/lib/general/gr_deinterleave.cc b/gnuradio-core/src/lib/general/gr_deinterleave.cc new file mode 100644 index 00000000..375a40d2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_deinterleave_sptr +gr_make_deinterleave (size_t itemsize) +{ + return gr_deinterleave_sptr (new gr_deinterleave (itemsize)); +} + +gr_deinterleave::gr_deinterleave (size_t itemsize) + : gr_sync_decimator ("deinterleave", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (1, gr_io_signature::IO_INFINITE, itemsize), + 1), + d_itemsize (itemsize) +{ +} + +gr_deinterleave::~gr_deinterleave () +{ + // NOP +} + +bool +gr_deinterleave::check_topology (int ninputs, int noutputs) +{ + set_decimation (noutputs); + return true; +} + +int +gr_deinterleave::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t nchan = output_items.size (); + size_t itemsize = d_itemsize; + const char *in = (const char *) input_items[0]; + char **out = (char **) &output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + for (unsigned int n = 0; n < nchan; n++){ + memcpy (out[n], in, itemsize); + out[n] += itemsize; + in += itemsize; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_deinterleave.h b/gnuradio-core/src/lib/general/gr_deinterleave.h new file mode 100644 index 00000000..0eb9874e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DEINTERLEAVE_H +#define INCLUDED_GR_DEINTERLEAVE_H + +#include + +class gr_deinterleave; +typedef boost::shared_ptr gr_deinterleave_sptr; + +gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + +/*! + * \brief deinterleave a single input into N outputs + * \ingroup block + */ +class gr_deinterleave : public gr_sync_decimator +{ + friend gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + + size_t d_itemsize; + + gr_deinterleave (size_t itemsize); + +public: + ~gr_deinterleave (); + + 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); + +}; + +#endif /* INCLUDED_GR_DEINTERLEAVE_H */ diff --git a/gnuradio-core/src/lib/general/gr_deinterleave.i b/gnuradio-core/src/lib/general/gr_deinterleave.i new file mode 100644 index 00000000..f1eac5ca --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,deinterleave) + +gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + +class gr_deinterleave : public gr_sync_decimator +{ + gr_deinterleave (size_t itemsize); +}; diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc new file mode 100644 index 00000000..5ab88a9c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_diff_decoder_bb_sptr +gr_make_diff_decoder_bb (unsigned int modulus) +{ + return gr_diff_decoder_bb_sptr (new gr_diff_decoder_bb(modulus)); +} + +gr_diff_decoder_bb::gr_diff_decoder_bb (unsigned int modulus) + : gr_sync_block ("diff_decoder_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_modulus(modulus) +{ + set_history(2); // need to look at two inputs +} + +int +gr_diff_decoder_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + in += 1; // ensure that in[-1] is valid + + unsigned modulus = d_modulus; + + for (int i = 0; i < noutput_items; i++){ + out[i] = (in[i] - in[i-1]) % modulus; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h new file mode 100644 index 00000000..c88e0e25 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DIFF_DECODER_BB_H +#define INCLUDED_GR_DIFF_DECODER_BB_H + +#include + +class gr_diff_decoder_bb; +typedef boost::shared_ptr gr_diff_decoder_bb_sptr; + +gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); + +/*! + * \brief y[0] = (x[0] - x[-1]) % M + * \ingroup block + * + * Differential decoder + */ +class gr_diff_decoder_bb : public gr_sync_block +{ + friend gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); + gr_diff_decoder_bb(unsigned int modulus); + + unsigned int d_modulus; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i new file mode 100644 index 00000000..b4ad5f6a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,diff_decoder_bb) + +gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); + +class gr_diff_decoder_bb : public gr_sync_block +{ + private: + gr_diff_decoder_bb (unsigned int modulus); +}; diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc new file mode 100644 index 00000000..bd4135c4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_diff_encoder_bb_sptr +gr_make_diff_encoder_bb (unsigned int modulus) +{ + return gr_diff_encoder_bb_sptr (new gr_diff_encoder_bb(modulus)); +} + +gr_diff_encoder_bb::gr_diff_encoder_bb (unsigned int modulus) + : gr_sync_block ("diff_encoder_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_last_out(0), d_modulus(modulus) +{ +} + +int +gr_diff_encoder_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + unsigned last_out = d_last_out; + unsigned modulus = d_modulus; + + for (int i = 0; i < noutput_items; i++){ + out[i] = (in[i] + last_out) % modulus; + last_out = out[i]; + } + + d_last_out = last_out; + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h new file mode 100644 index 00000000..c839d399 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DIFF_ENCODER_BB_H +#define INCLUDED_GR_DIFF_ENCODER_BB_H + +#include + +class gr_diff_encoder_bb; +typedef boost::shared_ptr gr_diff_encoder_bb_sptr; + +gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); + +/*! + * \brief y[0] = (x[0] + y[-1]) % M + * \ingroup block + * + * Differential encoder + */ +class gr_diff_encoder_bb : public gr_sync_block +{ + friend gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); + gr_diff_encoder_bb(unsigned int modulus); + + unsigned int d_last_out; + unsigned int d_modulus; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i new file mode 100644 index 00000000..890779c4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,diff_encoder_bb) + +gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); + +class gr_diff_encoder_bb : public gr_sync_block +{ + private: + gr_diff_encoder_bb (unsigned int modulus); +}; diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc new file mode 100644 index 00000000..c5eae5f3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_diff_phasor_cc_sptr +gr_make_diff_phasor_cc () +{ + return gr_diff_phasor_cc_sptr (new gr_diff_phasor_cc()); +} + +gr_diff_phasor_cc::gr_diff_phasor_cc () + : gr_sync_block ("diff_phasor_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ + set_history(2); +} + + +gr_diff_phasor_cc::~gr_diff_phasor_cc(){} + +int +gr_diff_phasor_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex const *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + in += 1; // ensure that i - 1 is valid. + + for(int i = 0; i < noutput_items; i++){ + out[i] = in[i] * conj(in[i-1]); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h new file mode 100644 index 00000000..64a3f291 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DIFF_PHASOR_CC_H +#define INCLUDED_GR_DIFF_PHASOR_CC_H + +#include + +class gr_diff_phasor_cc; +typedef boost::shared_ptr gr_diff_phasor_cc_sptr; + +gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); + + +class gr_diff_phasor_cc : public gr_sync_block +{ + friend gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); + + gr_diff_phasor_cc (); //constructor + + public: + ~gr_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/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i new file mode 100644 index 00000000..773d276b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,diff_phasor_cc) + +gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); + +class gr_diff_phasor_cc : public gr_sync_block +{ + private: + gr_diff_phasor_cc (); + + public: + ~gr_diff_phasor_cc(); +}; diff --git a/gnuradio-core/src/lib/general/gr_divide_XX.cc.t b/gnuradio-core/src/lib/general/gr_divide_XX.cc.t new file mode 100644 index 00000000..e85f7b0a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_divide_XX.cc.t @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return @SPTR_NAME@ (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + if (ninputs == 1){ // compute reciprocal + for (int i = 0; i < noutput_items; i++) + *optr++ = (@O_TYPE@) ((@O_TYPE@) 1 / + ((@I_TYPE@ *) input_items[0])[i]); + } + + else { + for (int i = 0; i < noutput_items; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc /= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_divide_XX.h.t b/gnuradio-core/src/lib/general/gr_divide_XX.h.t new file mode 100644 index 00000000..193d6f82 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_divide_XX.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 / input_1 / input_x ...) + * \ingroup block + * + * Divide across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_divide_XX.i.t b/gnuradio-core/src/lib/general/gr_divide_XX.i.t new file mode 100644 index 00000000..8479aad6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_divide_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/general/gr_endianness.h b/gnuradio-core/src/lib/general/gr_endianness.h new file mode 100644 index 00000000..e33af166 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_endianness.h @@ -0,0 +1,27 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_ENDIANNESS_H +#define INCLUDED_GR_ENDIANNESS_H + +typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} gr_endianness_t; + +#endif /* INCLUDED_GR_ENDIANNESS_H */ diff --git a/gnuradio-core/src/lib/general/gr_endianness.i b/gnuradio-core/src/lib/general/gr_endianness.i new file mode 100644 index 00000000..d05b06a0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_endianness.i @@ -0,0 +1,23 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%include diff --git a/gnuradio-core/src/lib/general/gr_expj.h b/gnuradio-core/src/lib/general/gr_expj.h new file mode 100644 index 00000000..502bfe9e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_expj.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_EXPJ_H +#define INCLUDED_GR_EXPJ_H + +#include +#include + +static inline gr_complex +gr_expj(float phase) +{ + float t_imag, t_real; + gr_sincosf(phase, &t_imag, &t_real); + return gr_complex(t_real, t_imag); +} + + +#endif /* INCLUDED_GR_EXPJ_H */ diff --git a/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc new file mode 100644 index 00000000..0ef4c46d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static const int PAD_VAL = 0xAA; + +gr_fake_channel_encoder_pp_sptr +gr_make_fake_channel_encoder_pp(int input_vlen, int output_vlen) +{ + return gr_fake_channel_encoder_pp_sptr(new gr_fake_channel_encoder_pp(input_vlen, + output_vlen)); +} + +gr_fake_channel_encoder_pp::gr_fake_channel_encoder_pp(int input_vlen, int output_vlen) + : gr_sync_block("fake_channel_encoder_pp", + gr_make_io_signature(1, 1, input_vlen * sizeof(unsigned char)), + gr_make_io_signature(1, 1, output_vlen * sizeof(unsigned char))), + d_input_vlen(input_vlen), d_output_vlen(output_vlen) +{ + if (input_vlen <= 0 || output_vlen <= 0 || input_vlen > output_vlen) + throw std::invalid_argument("gr_fake_channel_encoder_pp"); +} + +gr_fake_channel_encoder_pp::~gr_fake_channel_encoder_pp() +{ +} + +int +gr_fake_channel_encoder_pp::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]; + int npad = d_output_vlen - d_input_vlen; + + for (int i = 0; i < noutput_items; i++){ + memcpy(out, in, d_input_vlen); + memset(out + d_input_vlen, PAD_VAL, npad); + in += d_input_vlen; + out += d_output_vlen; + } + + return noutput_items; +} + +// ------------------------------------------------------------------------ + +gr_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen) +{ + return gr_fake_channel_decoder_pp_sptr(new gr_fake_channel_decoder_pp(input_vlen, + output_vlen)); +} + +gr_fake_channel_decoder_pp::gr_fake_channel_decoder_pp(int input_vlen, int output_vlen) + : gr_sync_block("fake_channel_decoder_pp", + gr_make_io_signature(1, 1, input_vlen * sizeof(unsigned char)), + gr_make_io_signature(1, 1, output_vlen * sizeof(unsigned char))), + d_input_vlen(input_vlen), d_output_vlen(output_vlen) +{ + if (input_vlen <= 0 || output_vlen <= 0 || output_vlen > input_vlen) + throw std::invalid_argument("gr_fake_channel_decoder_pp"); +} + +gr_fake_channel_decoder_pp::~gr_fake_channel_decoder_pp() +{ +} + +int +gr_fake_channel_decoder_pp::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++){ + memcpy(out, in, d_output_vlen); + in += d_input_vlen; + out += d_output_vlen; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h new file mode 100644 index 00000000..03b651e8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FAKE_CHANNEL_CODER_PP_H +#define INCLUDED_GR_FAKE_CHANNEL_CODER_PP_H + +#include + +class gr_fake_channel_encoder_pp; +typedef boost::shared_ptr gr_fake_channel_encoder_pp_sptr; + +gr_fake_channel_encoder_pp_sptr +gr_make_fake_channel_encoder_pp(int input_vlen, int output_vlen); + +/*! + * \brief pad packet with alternating 1,0 pattern. + * \ingroup block + * + * input: stream of byte vectors; output: stream of byte vectors + */ +class gr_fake_channel_encoder_pp : public gr_sync_block +{ + int d_input_vlen; + int d_output_vlen; + + gr_fake_channel_encoder_pp(int input_vlen, int output_vlen); + + friend gr_fake_channel_encoder_pp_sptr + gr_make_fake_channel_encoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_encoder_pp(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +// ------------------------------------------------------------------------ + +class gr_fake_channel_decoder_pp; +typedef boost::shared_ptr gr_fake_channel_decoder_pp_sptr; + +gr_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +/*! + * \brief remove fake padding from packet + * \ingroup block + * + * input: stream of byte vectors; output: stream of byte vectors + */ +class gr_fake_channel_decoder_pp : public gr_sync_block +{ + int d_input_vlen; + int d_output_vlen; + + gr_fake_channel_decoder_pp(int input_vlen, int output_vlen); + + friend gr_fake_channel_decoder_pp_sptr + gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_decoder_pp(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FAKE_CHANNEL_CODER_PP_H */ diff --git a/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i new file mode 100644 index 00000000..3bf394e2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,fake_channel_encoder_pp) + +gr_fake_channel_encoder_pp_sptr +gr_make_fake_channel_encoder_pp(int input_vlen, + int output_vlen + ) throw(std::invalid_argument); + +class gr_fake_channel_encoder_pp : public gr_sync_block +{ + gr_fake_channel_encoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_encoder_pp(); +}; + +// ------------------------------------------------------------------------ + +GR_SWIG_BLOCK_MAGIC(gr,fake_channel_decoder_pp) + +gr_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, + int output_vlen + ) throw(std::invalid_argument); + +class gr_fake_channel_decoder_pp : public gr_sync_block +{ + gr_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_decoder_pp(); +}; diff --git a/gnuradio-core/src/lib/general/gr_fast_atan2f.cc b/gnuradio-core/src/lib/general/gr_fast_atan2f.cc new file mode 100644 index 00000000..ebbece57 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fast_atan2f.cc @@ -0,0 +1,198 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include // declaration is in here +#include + +#define REAL float + +/***************************************************************************/ +/* Constant definitions */ +/***************************************************************************/ + +#define TAN_MAP_RES 0.003921569 /* (smallest non-zero value in table) */ +#define RAD_PER_DEG 0.017453293 +#define TAN_MAP_SIZE 256 + +/* arctangents from 0 to pi/4 radians */ +static REAL +fast_atan_table[257] = { + 0.000000e+00, 3.921549e-03, 7.842976e-03, 1.176416e-02, + 1.568499e-02, 1.960533e-02, 2.352507e-02, 2.744409e-02, + 3.136226e-02, 3.527947e-02, 3.919560e-02, 4.311053e-02, + 4.702413e-02, 5.093629e-02, 5.484690e-02, 5.875582e-02, + 6.266295e-02, 6.656816e-02, 7.047134e-02, 7.437238e-02, + 7.827114e-02, 8.216752e-02, 8.606141e-02, 8.995267e-02, + 9.384121e-02, 9.772691e-02, 1.016096e-01, 1.054893e-01, + 1.093658e-01, 1.132390e-01, 1.171087e-01, 1.209750e-01, + 1.248376e-01, 1.286965e-01, 1.325515e-01, 1.364026e-01, + 1.402496e-01, 1.440924e-01, 1.479310e-01, 1.517652e-01, + 1.555948e-01, 1.594199e-01, 1.632403e-01, 1.670559e-01, + 1.708665e-01, 1.746722e-01, 1.784728e-01, 1.822681e-01, + 1.860582e-01, 1.898428e-01, 1.936220e-01, 1.973956e-01, + 2.011634e-01, 2.049255e-01, 2.086818e-01, 2.124320e-01, + 2.161762e-01, 2.199143e-01, 2.236461e-01, 2.273716e-01, + 2.310907e-01, 2.348033e-01, 2.385093e-01, 2.422086e-01, + 2.459012e-01, 2.495869e-01, 2.532658e-01, 2.569376e-01, + 2.606024e-01, 2.642600e-01, 2.679104e-01, 2.715535e-01, + 2.751892e-01, 2.788175e-01, 2.824383e-01, 2.860514e-01, + 2.896569e-01, 2.932547e-01, 2.968447e-01, 3.004268e-01, + 3.040009e-01, 3.075671e-01, 3.111252e-01, 3.146752e-01, + 3.182170e-01, 3.217506e-01, 3.252758e-01, 3.287927e-01, + 3.323012e-01, 3.358012e-01, 3.392926e-01, 3.427755e-01, + 3.462497e-01, 3.497153e-01, 3.531721e-01, 3.566201e-01, + 3.600593e-01, 3.634896e-01, 3.669110e-01, 3.703234e-01, + 3.737268e-01, 3.771211e-01, 3.805064e-01, 3.838825e-01, + 3.872494e-01, 3.906070e-01, 3.939555e-01, 3.972946e-01, + 4.006244e-01, 4.039448e-01, 4.072558e-01, 4.105574e-01, + 4.138496e-01, 4.171322e-01, 4.204054e-01, 4.236689e-01, + 4.269229e-01, 4.301673e-01, 4.334021e-01, 4.366272e-01, + 4.398426e-01, 4.430483e-01, 4.462443e-01, 4.494306e-01, + 4.526070e-01, 4.557738e-01, 4.589307e-01, 4.620778e-01, + 4.652150e-01, 4.683424e-01, 4.714600e-01, 4.745676e-01, + 4.776654e-01, 4.807532e-01, 4.838312e-01, 4.868992e-01, + 4.899573e-01, 4.930055e-01, 4.960437e-01, 4.990719e-01, + 5.020902e-01, 5.050985e-01, 5.080968e-01, 5.110852e-01, + 5.140636e-01, 5.170320e-01, 5.199904e-01, 5.229388e-01, + 5.258772e-01, 5.288056e-01, 5.317241e-01, 5.346325e-01, + 5.375310e-01, 5.404195e-01, 5.432980e-01, 5.461666e-01, + 5.490251e-01, 5.518738e-01, 5.547124e-01, 5.575411e-01, + 5.603599e-01, 5.631687e-01, 5.659676e-01, 5.687566e-01, + 5.715357e-01, 5.743048e-01, 5.770641e-01, 5.798135e-01, + 5.825531e-01, 5.852828e-01, 5.880026e-01, 5.907126e-01, + 5.934128e-01, 5.961032e-01, 5.987839e-01, 6.014547e-01, + 6.041158e-01, 6.067672e-01, 6.094088e-01, 6.120407e-01, + 6.146630e-01, 6.172755e-01, 6.198784e-01, 6.224717e-01, + 6.250554e-01, 6.276294e-01, 6.301939e-01, 6.327488e-01, + 6.352942e-01, 6.378301e-01, 6.403565e-01, 6.428734e-01, + 6.453808e-01, 6.478788e-01, 6.503674e-01, 6.528466e-01, + 6.553165e-01, 6.577770e-01, 6.602282e-01, 6.626701e-01, + 6.651027e-01, 6.675261e-01, 6.699402e-01, 6.723452e-01, + 6.747409e-01, 6.771276e-01, 6.795051e-01, 6.818735e-01, + 6.842328e-01, 6.865831e-01, 6.889244e-01, 6.912567e-01, + 6.935800e-01, 6.958943e-01, 6.981998e-01, 7.004964e-01, + 7.027841e-01, 7.050630e-01, 7.073330e-01, 7.095943e-01, + 7.118469e-01, 7.140907e-01, 7.163258e-01, 7.185523e-01, + 7.207701e-01, 7.229794e-01, 7.251800e-01, 7.273721e-01, + 7.295557e-01, 7.317307e-01, 7.338974e-01, 7.360555e-01, + 7.382053e-01, 7.403467e-01, 7.424797e-01, 7.446045e-01, + 7.467209e-01, 7.488291e-01, 7.509291e-01, 7.530208e-01, + 7.551044e-01, 7.571798e-01, 7.592472e-01, 7.613064e-01, + 7.633576e-01, 7.654008e-01, 7.674360e-01, 7.694633e-01, + 7.714826e-01, 7.734940e-01, 7.754975e-01, 7.774932e-01, + 7.794811e-01, 7.814612e-01, 7.834335e-01, 7.853983e-01, + 7.853983e-01 + }; + + +/***************************************************************************** +Function: Arc tangent + +Syntax: angle = fast_atan2(y, x); +REAL y y component of input vector +REAL x x component of input vector +REAL angle angle of vector (x, y) in radians + +Description: This function calculates the angle of the vector (x,y) based +on a table lookup and linear interpolation. The table uses +a 256 point table covering -45 to +45 degrees and uses +symetry to determine the final angle value in the range of +-180 to 180 degrees. Note that this function uses the small +angle approximation for values close to zero. This routine +calculates the arc tangent with an average error of ++/- 0.045 degrees. +*****************************************************************************/ + +REAL +gr_fast_atan2f(REAL y, REAL x) +{ + REAL x_abs, y_abs, z; + REAL alpha, angle, base_angle; + int index; + + /* don't divide by zero! */ // FIXME could get hosed with -0.0 + if ((y == 0.0) && (x == 0.0)) + return 0.0; + + /* normalize to +/- 45 degree range */ + y_abs = fabs(y); + x_abs = fabs(x); + //z = (y_abs < x_abs ? y_abs / x_abs : x_abs / y_abs); + if (y_abs < x_abs) + z = y_abs / x_abs; + else + z = x_abs / y_abs; + + /* when ratio approaches the table resolution, the angle is */ + /* best approximated with the argument itself... */ + if (z < TAN_MAP_RES) + base_angle = z; + else { + /* find index and interpolation value */ + alpha = z * (REAL) TAN_MAP_SIZE - .5; + index = (int) alpha; + alpha -= (REAL) index; + /* determine base angle based on quadrant and */ + /* add or subtract table value from base angle based on quadrant */ + base_angle = fast_atan_table[index]; + base_angle += + (fast_atan_table[index + 1] - fast_atan_table[index]) * alpha; + } + + if (x_abs > y_abs) { /* -45 -> 45 or 135 -> 225 */ + if (x >= 0.0) { /* -45 -> 45 */ + if (y >= 0.0) + angle = base_angle; /* 0 -> 45, angle OK */ + else + angle = -base_angle; /* -45 -> 0, angle = -angle */ + } else { /* 135 -> 180 or 180 -> -135 */ + angle = 3.14159265358979323846; + if (y >= 0.0) + angle -= base_angle; /* 135 -> 180, angle = 180 - angle */ + else + angle = base_angle - angle; /* 180 -> -135, angle = angle - 180 */ + } + } else { /* 45 -> 135 or -135 -> -45 */ + if (y >= 0.0) { /* 45 -> 135 */ + angle = 1.57079632679489661923; + if (x >= 0.0) + angle -= base_angle; /* 45 -> 90, angle = 90 - angle */ + else + angle += base_angle; /* 90 -> 135, angle = 90 + angle */ + } else { /* -135 -> -45 */ + angle = -1.57079632679489661923; + if (x >= 0.0) + angle += base_angle; /* -90 -> -45, angle = -90 + angle */ + else + angle -= base_angle; /* -135 -> -90, angle = -90 - angle */ + } + } + +#ifdef ZERO_TO_TWOPI + if (angle < 0) + return (angle + TWOPI); + else + return (angle); +#else + return (angle); +#endif +} diff --git a/gnuradio-core/src/lib/general/gr_feval.cc b/gnuradio-core/src/lib/general/gr_feval.cc new file mode 100644 index 00000000..b30930ec --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +gr_feval_dd::~gr_feval_dd(){} + +double +gr_feval_dd::eval(double x) +{ + return 0; +} + +gr_feval_ff::~gr_feval_ff(){} + +float +gr_feval_ff::eval(float x) +{ + return 0; +} + +gr_feval_cc::~gr_feval_cc(){} + +gr_complex +gr_feval_cc::eval(gr_complex x) +{ + return 0; +} + +gr_feval_ll::~gr_feval_ll(){} + +long +gr_feval_ll::eval(long x) +{ + return 0; +} + +/* + * Trivial examples showing C++ (transparently) calling Python + */ +double +gr_feval_dd_example(gr_feval_dd *f, double x) +{ + return f->eval(x); +} + +float +gr_feval_ff_example(gr_feval_ff *f, float x) +{ + return f->eval(x); +} + +gr_complex +gr_feval_cc_example(gr_feval_cc *f, gr_complex x) +{ + return f->eval(x); +} + +long +gr_feval_ll_example(gr_feval_ll *f, long x) +{ + return f->eval(x); +} diff --git a/gnuradio-core/src/lib/general/gr_feval.h b/gnuradio-core/src/lib/general/gr_feval.h new file mode 100644 index 00000000..e9f3ae35 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.h @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FEVAL_H +#define INCLUDED_GR_FEVAL_H + +#include + +/*! + * \brief base class for evaluating a function: double -> double + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + */ +class gr_feval_dd +{ +public: + gr_feval_dd() {} + virtual ~gr_feval_dd(); + + /*! + * \brief override this to define the function + */ + virtual double eval(double x); +}; + +/*! + * \brief base class for evaluating a function: float -> float + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + */ +class gr_feval_ff +{ +public: + gr_feval_ff() {} + virtual ~gr_feval_ff(); + + /*! + * \brief override this to define the function + */ + virtual float eval(float x); +}; + +/*! + * \brief base class for evaluating a function: complex -> complex + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + */ +class gr_feval_cc +{ +public: + gr_feval_cc() {} + virtual ~gr_feval_cc(); + + /*! + * \brief override this to define the function + */ + virtual gr_complex eval(gr_complex x); +}; + +/*! + * \brief base class for evaluating a function: long -> long + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + */ +class gr_feval_ll +{ +public: + gr_feval_ll() {} + virtual ~gr_feval_ll(); + + /*! + * \brief override this to define the function + */ + virtual long eval(long x); +}; + +/*! + * \brief trivial examples / test cases showing C++ calling Python code + */ +double gr_feval_dd_example(gr_feval_dd *f, double x); +float gr_feval_ff_example(gr_feval_ff *f, float x); +gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); +long gr_feval_ll_example(gr_feval_ll *f, long x); + + +#endif /* INCLUDED_GR_FEVAL_H */ diff --git a/gnuradio-core/src/lib/general/gr_feval.i b/gnuradio-core/src/lib/general/gr_feval.i new file mode 100644 index 00000000..f7d8c221 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.i @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Enable SWIG directors for these classes +%feature("director") gr_feval_dd; +%feature("director") gr_feval_cc; +%feature("director") gr_feval_ll; + + +%rename(feval_dd) gr_feval_dd; +class gr_feval_dd +{ +public: + gr_feval_dd() {} + virtual ~gr_feval_dd(); + + virtual double eval(double x); +}; + +%rename(feval_cc) gr_feval_cc; +class gr_feval_cc +{ +public: + gr_feval_cc() {} + virtual ~gr_feval_cc(); + + virtual gr_complex eval(gr_complex x); +}; + +%rename(feval_ll) gr_feval_ll; +class gr_feval_ll +{ +public: + gr_feval_ll() {} + virtual ~gr_feval_ll(); + + virtual long eval(long x); +}; + + +// examples / test cases + +%rename(feval_dd_example) gr_feval_dd_example; +double gr_feval_dd_example(gr_feval_dd *f, double x); + +%rename(feval_cc_example) gr_feval_cc_example; +gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); + +%rename(feval_ll_example) gr_feval_ll_example; +long gr_feval_ll_example(gr_feval_ll *f, long x); diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.cc b/gnuradio-core/src/lib/general/gr_fft_vcc.cc new file mode 100644 index 00000000..e5291590 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.cc @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward,const std::vector window) +{ + return gr_fft_vcc_sptr (new gr_fft_vcc (fft_size, forward, window)); +} + +gr_fft_vcc::gr_fft_vcc (int fft_size, bool forward, const std::vector window) + : gr_sync_block ("fft_vcc", + 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_fft = new gri_fft_complex (d_fft_size, forward); + + set_window(window); + +} + +gr_fft_vcc::~gr_fft_vcc () +{ + delete d_fft; +} + +int +gr_fft_vcc::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(); + for (unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + else + memcpy (d_fft->get_inbuf(), in, input_data_size); + + // compute the fft + d_fft->execute (); + + // cpoy result to our output + memcpy (out, d_fft->get_outbuf (), output_data_size); + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; +} + +bool +gr_fft_vcc::set_window(const std::vector window) +{ + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; +} diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.h b/gnuradio-core/src/lib/general/gr_fft_vcc.h new file mode 100644 index 00000000..784471a3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FFT_VCC_H +#define INCLUDED_GR_FFT_VCC_H + +#include + +class gri_fft_complex; + +class gr_fft_vcc; +typedef boost::shared_ptr gr_fft_vcc_sptr; + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); + +/*! + * \brief Compute forward or reverse FFT. complex vector in / complex vector out. + * \ingroup block + */ + +class gr_fft_vcc : public gr_sync_block +{ + friend gr_fft_vcc_sptr + gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); + + unsigned int d_fft_size; + std::vector d_window; + gri_fft_complex *d_fft; + + gr_fft_vcc (int fft_size, bool forward, const std::vector window); + + public: + ~gr_fft_vcc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + bool set_window(const std::vector window); +}; + + +#endif /* INCLUDED_GR_FFT_VCC_H */ diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.i b/gnuradio-core/src/lib/general/gr_fft_vcc.i new file mode 100644 index 00000000..a171d122 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr, fft_vcc) + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); + +class gr_fft_vcc : public gr_sync_block +{ + protected: + gr_fft_vcc (int fft_size, bool forward, const std::vector window); + + public: + bool set_window(const std::vector window); +}; diff --git a/gnuradio-core/src/lib/general/gr_fft_vfc.cc b/gnuradio-core/src/lib/general/gr_fft_vfc.cc new file mode 100644 index 00000000..d6d24791 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.cc @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + + +// FIXME after this is working, change to use native real to complex fft. +// It should run twice as fast. + + + + +gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, const std::vector window) +{ + return gr_fft_vfc_sptr (new gr_fft_vfc (fft_size, forward, window)); +} + +gr_fft_vfc::gr_fft_vfc (int fft_size, bool forward, const std::vector window) + : gr_sync_block ("fft_vfc", + gr_make_io_signature (1, 1, fft_size * sizeof (float)), + gr_make_io_signature (1, 1, fft_size * sizeof (gr_complex))), + d_fft_size(fft_size), d_window() +{ + if (!forward){ + fprintf (stderr, "fft_vfc: forward must == true\n"); + throw std::invalid_argument ("fft_vfc: forward must == true"); + } + + d_fft = new gri_fft_complex (d_fft_size, forward); + + set_window(window); +} + +gr_fft_vfc::~gr_fft_vfc () +{ + delete d_fft; +} + +int +gr_fft_vfc::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 (); + + // cpoy result to our output + memcpy (out, d_fft->get_outbuf (), output_data_size); + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; +} + +bool +gr_fft_vfc::set_window(const std::vector window) +{ + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; +} diff --git a/gnuradio-core/src/lib/general/gr_fft_vfc.h b/gnuradio-core/src/lib/general/gr_fft_vfc.h new file mode 100644 index 00000000..a30495d8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FFT_VFC_H +#define INCLUDED_GR_FFT_VFC_H + +#include + +class gri_fft_complex; + +class gr_fft_vfc; +typedef boost::shared_ptr gr_fft_vfc_sptr; + +gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, const std::vector); + +/*! + * \brief Compute forward FFT. float vector in / complex vector out. + * \ingroup block + */ + +class gr_fft_vfc : public gr_sync_block +{ + friend gr_fft_vfc_sptr + gr_make_fft_vfc (int fft_size, bool forward, const std::vector window); + + unsigned int d_fft_size; + std::vector d_window; + gri_fft_complex *d_fft; + + gr_fft_vfc (int fft_size, bool forward, const std::vector window); + + public: + ~gr_fft_vfc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + bool set_window(const std::vector window); +}; + + +#endif /* INCLUDED_GR_FFT_VFC_H */ diff --git a/gnuradio-core/src/lib/general/gr_fft_vfc.i b/gnuradio-core/src/lib/general/gr_fft_vfc.i new file mode 100644 index 00000000..f30606d8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr, fft_vfc) + +gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, const std::vector window); + +class gr_fft_vfc : public gr_sync_block +{ + protected: + gr_fft_vfc (int fft_size, bool forward, const std::vector window); + + public: + bool set_window(const std::vector window); +}; diff --git a/gnuradio-core/src/lib/general/gr_firdes.cc b/gnuradio-core/src/lib/general/gr_firdes.cc new file mode 100644 index 00000000..d09d68d6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.cc @@ -0,0 +1,584 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + + +using std::vector; + +#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */ + +static double Izero(double x) +{ + double sum, u, halfx, temp; + int n; + + sum = u = n = 1; + halfx = x/2.0; + do { + temp = halfx/(double)n; + n += 1; + temp *= temp; + u *= temp; + sum += u; + } while (u >= IzeroEPSILON*sum); + return(sum); +} + + +// +// === Low Pass === +// + +vector +gr_firdes::low_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_1f (sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response + // [sin(x)/x for the low pass case] + + vector taps(ntaps); + vector w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = fwT0 / M_PI * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = sin (n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For low-pass, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// === High Pass === +// + +vector +gr_firdes::high_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_1f (sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector taps(ntaps); + vector w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = -sin (n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For high-pass, gain @ fs/2 freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos (n * M_PI); + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// === Band Pass === +// + +vector +gr_firdes::band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector taps(ntaps); + vector w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M]; + else { + taps[n + M] = (sin (n * fwT1) - sin (n * fwT0)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-pass, gain @ center freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos (n * (fwT0 + fwT1) * 0.5); + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// === Complex Band Pass === +// + +vector +gr_firdes::complex_band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f_c (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector taps(ntaps); + vector lptaps(ntaps); + vector w = window (window_type, ntaps, beta); + + lptaps = low_pass(gain,sampling_freq,(high_cutoff_freq - low_cutoff_freq)/2,transition_width,window_type,beta); + + gr_complex *optr = &taps[0]; + float *iptr = &lptaps[0]; + float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq; + float phase=0; + if (lptaps.size() & 01) { + phase = - freq * ( lptaps.size() >> 1 ); + } else phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1); + for(unsigned int i=0;i +gr_firdes::band_reject (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector taps(ntaps); + vector w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (1.0 + (fwT0 - fwT1)) / M_PI * w[n + M]; + else { + taps[n + M] = (sin (n * fwT0) - sin (n * fwT1)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-reject, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// Hilbert Transform +// + +vector +gr_firdes::hilbert (unsigned int ntaps, + win_type windowtype, + double beta) +{ + if(!(ntaps & 1)) + throw std::out_of_range("Hilbert: Must have odd number of taps"); + + vector taps(ntaps); + vector w = window (windowtype, ntaps, beta); + unsigned int h = (ntaps-1)/2; + float gain=0; + for (unsigned int i = 1; i <= h; i++) + { + if(i&1) + { + float x = 1/(float)i; + taps[h+i] = x * w[h+i]; + taps[h-i] = -x * w[h-i]; + gain = taps[h+i] - gain; + } + else + taps[h+i] = taps[h-i] = 0; + } + gain = 2 * fabs(gain); + for ( unsigned int i = 0; i < ntaps; i++) + taps[i] /= gain; + return taps; +} + +// +// Gaussian +// + +vector +gr_firdes::gaussian (double gain, + double spb, + double bt, + int ntaps) +{ + + vector taps(ntaps); + double scale = 0; + double dt = 1.0/spb; + double s = 1.0/(sqrt(log(2)) / (2*M_PI*bt)); + double t0 = -0.5 * ntaps; + double ts; + for(int i=0;i +gr_firdes::root_raised_cosine (double gain, + double sampling_freq, + double symbol_rate, + double alpha, + int ntaps) +{ + ntaps |= 1; // ensure that ntaps is odd + + double spb = sampling_freq/symbol_rate; // samples per bit/symbol + vector taps(ntaps); + double scale = 0; + for(int i=0;i= 0.000001 ) // Avoid Rounding errors... + { + if( i != ntaps/2 ) + num = cos((1+alpha)*x1) + sin((1-alpha)*x1)/(4*alpha*xindx/spb); + else + num = cos((1+alpha)*x1) + (1-alpha) * M_PI / (4*alpha); + den = x3 * M_PI; + } + else + { + if(alpha==1) + { + taps[i] = -1; + continue; + } + x3 = (1-alpha)*x1; + x2 = (1+alpha)*x1; + num = (sin(x2)*(1+alpha)*M_PI + - cos(x3)*((1-alpha)*M_PI*spb)/(4*alpha*xindx) + + sin(x3)*spb*spb/(4*alpha*xindx*xindx)); + den = -32 * M_PI * alpha * alpha * xindx/spb; + } + taps[i] = 4 * alpha * num / den; + scale += taps[i]; + } + + for(int i=0;i +gr_firdes::window (win_type type, int ntaps, double beta) +{ + vector taps(ntaps); + int M = ntaps - 1; // filter order + + switch (type){ + case WIN_RECTANGULAR: + for (int n = 0; n < ntaps; n++) + taps[n] = 1; + + case WIN_HAMMING: + for (int n = 0; n < ntaps; n++) + taps[n] = 0.54 - 0.46 * cos ((2 * M_PI * n) / M); + break; + + case WIN_HANN: + for (int n = 0; n < ntaps; n++) + taps[n] = 0.5 - 0.5 * cos ((2 * M_PI * n) / M); + break; + + case WIN_BLACKMAN: + for (int n = 0; n < ntaps; n++) + taps[n] = 0.42 - 0.50 * cos ((2*M_PI * n) / (M-1)) - 0.08 * cos ((4*M_PI * n) / (M-1)); + break; + +#if 0 + case WIN_KAISER: + for (int n = 0; n < ntaps; n++) + taps[n] = bessi0(beta*sqrt(1.0 - (4.0*n/(M*M))))/bessi0(beta); + break; +#else + + case WIN_KAISER: + { + double IBeta = 1.0/Izero(beta); + double inm1 = 1.0/((double)(ntaps)); + double temp; + //fprintf(stderr, "IBeta = %g; inm1 = %g\n", IBeta, inm1); + + for (int i=0; i 0"); + + if (fa <= 0.0 || fa > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (transition_width <= 0) + throw std::out_of_range ("gr_dirdes check failed: transition_width > 0"); +} + +void +gr_firdes::sanity_check_2f (double sampling_freq, + double fa, // first cutoff freq + double fb, // second cutoff freq + double transition_width) +{ + if (sampling_freq <= 0.0) + throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0"); + + if (fa <= 0.0 || fa > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (fb <= 0.0 || fb > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fb <= sampling_freq / 2"); + + if (fa > fb) + throw std::out_of_range ("gr_firdes check failed: fa <= fb"); + + if (transition_width <= 0) + throw std::out_of_range ("gr_firdes check failed: transition_width > 0"); +} + +void +gr_firdes::sanity_check_2f_c (double sampling_freq, + double fa, // first cutoff freq + double fb, // second cutoff freq + double transition_width) +{ + if (sampling_freq <= 0.0) + throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0"); + + if (fa < -sampling_freq / 2 || fa > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (fb < -sampling_freq / 2 || fb > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fb <= sampling_freq / 2"); + + if (fa > fb) + throw std::out_of_range ("gr_firdes check failed: fa <= fb"); + + if (transition_width <= 0) + throw std::out_of_range ("gr_firdes check failed: transition_width > 0"); +} diff --git a/gnuradio-core/src/lib/general/gr_firdes.h b/gnuradio-core/src/lib/general/gr_firdes.h new file mode 100644 index 00000000..734f8ee9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.h @@ -0,0 +1,225 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_FIRDES_H_ +#define _GR_FIRDES_H_ + +#include +#include +#include + +/*! + * \brief Finite Impulse Response (FIR) filter design functions. + */ + +class gr_firdes { + public: + + enum win_type { + WIN_HAMMING = 0, // max attenuation 53 dB + WIN_HANN = 1, // max attenuation 44 dB + WIN_BLACKMAN = 2, // max attenuation 74 dB + WIN_RECTANGULAR = 3, + WIN_KAISER = 4 // max attenuation a function of beta, google it + }; + + + // ... class methods ... + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector + low_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector + high_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector + band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + + /*! + * \brief use "window method" to design a complex band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector + complex_band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector + band_reject (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*!\brief design a Hilbert Transform Filter + * + * \p ntaps: Number of taps, must be odd + * \p window_type: What kind of window to use + * \p beta: Only used for Kaiser + */ + static std::vector + hilbert (unsigned int ntaps, + win_type windowtype = WIN_RECTANGULAR, + double beta = 6.76); + + /*! + * \brief design a Root Cosine FIR Filter (do we need a window?) + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p symbol rate: symbol rate, must be a factor of sample rate + * \p alpha: excess bandwidth factor + * \p ntaps: number of taps + */ + static std::vector + root_raised_cosine (double gain, + double sampling_freq, + double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK) + double alpha, // Excess Bandwidth Factor + int ntaps); + + /*! + * \brief design a Gaussian filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p symbols per bit: symbol rate, must be a factor of sample rate + * \p ntaps: number of taps + */ + static std::vector + gaussian (double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps); + + // window functions ... + static std::vector window (win_type type, int ntaps, double beta); + +private: + static double bessi0(double x); + static void sanity_check_1f (double sampling_freq, double f1, + double transition_width); + static void sanity_check_2f (double sampling_freq, double f1, double f2, + double transition_width); + static void sanity_check_2f_c (double sampling_freq, double f1, double f2, + double transition_width); + + static int compute_ntaps (double sampling_freq, + double transition_width, + win_type window_type, double beta); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_firdes.i b/gnuradio-core/src/lib/general/gr_firdes.i new file mode 100644 index 00000000..a0ea2f45 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.i @@ -0,0 +1,187 @@ +/* -*- C++ -*- */ + +/*! + * \brief Finite Impulse Response (FIR) filter design functions. + */ + +%rename(firdes) gr_firdes; + +class gr_firdes { + public: + + enum win_type { + WIN_HAMMING = 0, // max attenuation 53 dB + WIN_HANN = 1, // max attenuation 44 dB + WIN_BLACKMAN = 2, // max attenuation 74 dB + WIN_RECTANGULAR = 3, + WIN_KAISER = 4 // max attenuation variable with beta, google it + }; + + // ... class methods ... + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector + low_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector + high_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector + band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector + complex_band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector + band_reject (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*!\brief design a Hilbert Transform Filter + * + * \p ntaps: Number of taps, must be odd + * \p window_type: What kind of window to use + * \p beta: Only used for Kaiser + */ + static std::vector + hilbert (unsigned int ntaps, + win_type windowtype = WIN_RECTANGULAR, + double beta = 6.76); + + /*! + * \brief design a Root Cosine FIR Filter (do we need a window?) + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p symbol rate: symbol rate, must be a factor of sample rate + * \p alpha: excess bandwidth factor + * \p ntaps: number of taps + */ + static std::vector + root_raised_cosine (double gain, + double sampling_freq, + double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK) + double alpha, // Excess Bandwidth Factor + int ntaps); + + /*! + * \brief design a Gaussian filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p symbols per bit: symbol rate, must be a factor of sample rate + * \p bt: BT bandwidth time product + * \p ntaps: number of taps + */ + static std::vector + gaussian (double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps); + + /*! + * Return window given type, ntaps and optional beta. + */ + static std::vector gr_firdes::window (win_type type, int ntaps, double beta); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.cc b/gnuradio-core/src/lib/general/gr_float_to_char.cc new file mode 100644 index 00000000..ed9538fc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_float_to_char_sptr +gr_make_float_to_char () +{ + return gr_float_to_char_sptr (new gr_float_to_char ()); +} + +gr_float_to_char::gr_float_to_char () + : gr_sync_block ("gr_float_to_char", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (char))) +{ +} + +int +gr_float_to_char::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]; + char *out = (char *) output_items[0]; + + gri_float_to_char (in, out, noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.h b/gnuradio-core/src/lib/general/gr_float_to_char.h new file mode 100644 index 00000000..e1d0f9f0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_CHAR_H +#define INCLUDED_GR_FLOAT_TO_CHAR_H + +#include + +class gr_float_to_char; +typedef boost::shared_ptr gr_float_to_char_sptr; + +gr_float_to_char_sptr +gr_make_float_to_char (); + +/*! + * \brief Convert stream of float to a stream of char + * \ingroup converter + */ + +class gr_float_to_char : public gr_sync_block +{ + friend gr_float_to_char_sptr gr_make_float_to_char (); + gr_float_to_char (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_CHAR_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.i b/gnuradio-core/src/lib/general/gr_float_to_char.i new file mode 100644 index 00000000..139439c3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_char) + +gr_float_to_char_sptr gr_make_float_to_char (); + +class gr_float_to_char : public gr_sync_block +{ + gr_float_to_char (); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.cc b/gnuradio-core/src/lib/general/gr_float_to_complex.cc new file mode 100644 index 00000000..547d9173 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_float_to_complex_sptr +gr_make_float_to_complex () +{ + return gr_float_to_complex_sptr (new gr_float_to_complex ()); +} + +gr_float_to_complex::gr_float_to_complex () + : gr_sync_block ("gr_float_to_complex", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ +} + +int +gr_float_to_complex::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *r = (float *)input_items[0]; + float *i = (float *)input_items[1]; + gr_complex *out = (gr_complex *) output_items[0]; + + switch (input_items.size ()){ + case 1: + for (int j = 0; j < noutput_items; j++) + out[j] = gr_complex (r[j], 0); + break; + + case 2: + for (int j = 0; j < noutput_items; j++) + out[j] = gr_complex (r[j], i[j]); + break; + + default: + assert (0); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.h b/gnuradio-core/src/lib/general/gr_float_to_complex.h new file mode 100644 index 00000000..8c285217 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_COMPLEX_H +#define INCLUDED_GR_FLOAT_TO_COMPLEX_H + +#include +#include + +class gr_float_to_complex; +typedef boost::shared_ptr gr_float_to_complex_sptr; + +gr_float_to_complex_sptr +gr_make_float_to_complex (); + +/*! + * \brief Convert 1 or 2 streams of float to a stream of gr_complex + * \ingroup converter + */ + +class gr_float_to_complex : public gr_sync_block +{ + friend gr_float_to_complex_sptr gr_make_float_to_complex (); + gr_float_to_complex (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_COMPLEX_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.i b/gnuradio-core/src/lib/general/gr_float_to_complex.i new file mode 100644 index 00000000..4a6ea324 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_complex) + +gr_float_to_complex_sptr gr_make_float_to_complex (); + +class gr_float_to_complex : public gr_sync_block +{ + gr_float_to_complex (); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.cc b/gnuradio-core/src/lib/general/gr_float_to_short.cc new file mode 100644 index 00000000..171726b8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_float_to_short_sptr +gr_make_float_to_short () +{ + return gr_float_to_short_sptr (new gr_float_to_short ()); +} + +gr_float_to_short::gr_float_to_short () + : gr_sync_block ("gr_float_to_short", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (short))) +{ +} + +int +gr_float_to_short::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]; + short *out = (short *) output_items[0]; + + gri_float_to_short (in, out, noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.h b/gnuradio-core/src/lib/general/gr_float_to_short.h new file mode 100644 index 00000000..75fdd943 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_SHORT_H +#define INCLUDED_GR_FLOAT_TO_SHORT_H + +#include + +class gr_float_to_short; +typedef boost::shared_ptr gr_float_to_short_sptr; + +gr_float_to_short_sptr +gr_make_float_to_short (); + +/*! + * \brief Convert stream of float to a stream of short + * \ingroup converter + */ + +class gr_float_to_short : public gr_sync_block +{ + friend gr_float_to_short_sptr gr_make_float_to_short (); + gr_float_to_short (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_SHORT_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.i b/gnuradio-core/src/lib/general/gr_float_to_short.i new file mode 100644 index 00000000..10726bc8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_short) + +gr_float_to_short_sptr gr_make_float_to_short (); + +class gr_float_to_short : public gr_sync_block +{ + gr_float_to_short (); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_uchar.cc b/gnuradio-core/src/lib/general/gr_float_to_uchar.cc new file mode 100644 index 00000000..d9402427 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_float_to_uchar_sptr +gr_make_float_to_uchar () +{ + return gr_float_to_uchar_sptr (new gr_float_to_uchar ()); +} + +gr_float_to_uchar::gr_float_to_uchar () + : gr_sync_block ("gr_float_to_uchar", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ +} + +int +gr_float_to_uchar::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]; + unsigned char *out = (unsigned char *) output_items[0]; + + gri_float_to_uchar (in, out, noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_uchar.h b/gnuradio-core/src/lib/general/gr_float_to_uchar.h new file mode 100644 index 00000000..bab00c42 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_UCHAR_H +#define INCLUDED_GR_FLOAT_TO_UCHAR_H + +#include + +class gr_float_to_uchar; +typedef boost::shared_ptr gr_float_to_uchar_sptr; + +gr_float_to_uchar_sptr +gr_make_float_to_uchar (); + +/*! + * \brief Convert stream of float to a stream of unsigned char + * \ingroup converter + */ + +class gr_float_to_uchar : public gr_sync_block +{ + friend gr_float_to_uchar_sptr gr_make_float_to_uchar (); + gr_float_to_uchar (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_UCHAR_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_uchar.i b/gnuradio-core/src/lib/general/gr_float_to_uchar.i new file mode 100644 index 00000000..8c0ee584 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_uchar) + +gr_float_to_uchar_sptr gr_make_float_to_uchar (); + +class gr_float_to_uchar : public gr_sync_block +{ + gr_float_to_uchar (); +}; diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.cc b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc new file mode 100644 index 00000000..c1afc434 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc @@ -0,0 +1,175 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define VERBOSE 0 + +inline void +gr_framer_sink_1::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; +} + +inline void +gr_framer_sink_1::enter_have_sync() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_sync\n"); + + d_state = STATE_HAVE_SYNC; + d_header = 0; + d_headerbitlen_cnt = 0; +} + +inline void +gr_framer_sink_1::enter_have_header(int payload_len) +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_header (payload_len = %d)\n", payload_len); + + d_state = STATE_HAVE_HEADER; + d_packetlen = payload_len; + d_packetlen_cnt = 0; + d_packet_byte = 0; + d_packet_byte_index = 0; +} + +gr_framer_sink_1_sptr +gr_make_framer_sink_1(gr_msg_queue_sptr target_queue) +{ + return gr_framer_sink_1_sptr(new gr_framer_sink_1(target_queue)); +} + + +gr_framer_sink_1::gr_framer_sink_1(gr_msg_queue_sptr target_queue) + : gr_sync_block ("framer_sink_1", + gr_make_io_signature (1, 1, sizeof(unsigned char)), + gr_make_io_signature (0, 0, 0)), + d_target_queue(target_queue) +{ + enter_search(); +} + +gr_framer_sink_1::~gr_framer_sink_1 () +{ +} + +int +gr_framer_sink_1::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + int count=0; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"); + + while (count < noutput_items){ + switch(d_state) { + + case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt + if (VERBOSE) + fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items); + + while (count < noutput_items) { + if (in[count] & 0x2){ // Found it, set up for header decode + enter_have_sync(); + break; + } + count++; + } + break; + + case STATE_HAVE_SYNC: + if (VERBOSE) + fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", + d_headerbitlen_cnt, d_header); + + while (count < noutput_items) { // Shift bits one at a time into header + d_header = (d_header << 1) | (in[count++] & 0x1); + if (++d_headerbitlen_cnt == HEADERBITLEN) { + + if (VERBOSE) + fprintf(stderr, "got header: 0x%08x\n", d_header); + + // we have a full header, check to see if it has been received properly + if (header_ok()){ + int payload_len = 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"); + + 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 + gr_message_sptr msg = gr_make_message(0, 0, 0, d_packetlen_cnt); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + break; + } + } + } + break; + + default: + assert(0); + + } // switch + + } // while + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.h b/gnuradio-core/src/lib/general/gr_framer_sink_1.h new file mode 100644 index 00000000..3e38aeed --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.h @@ -0,0 +1,103 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FRAMER_SINK_1_H +#define INCLUDED_GR_FRAMER_SINK_1_H + +#include +#include + +class gr_framer_sink_1; +typedef boost::shared_ptr gr_framer_sink_1_sptr; + +gr_framer_sink_1_sptr +gr_make_framer_sink_1 (gr_msg_queue_sptr target_queue); + +/*! + * \brief Given a stream of bits and access_code flags, assemble packets. + * \ingroup sink + * + * input: stream of bytes from gr_correlate_access_code_bb + * output: none. Pushes assembled packet into target queue + * + * The framer expects a fixed length header of 2 16-bit shorts + * containing the payload length, followed by the payload. If the + * 2 16-bit shorts are not identical, this packet is ignored. Better + * algs are welcome. + * + * The input data consists of bytes that have two bits used. + * Bit 0, the LSB, contains the data bit. + * Bit 1 if set, indicates that the corresponding bit is the + * the first bit of the packet. That is, this bit is the first + * one after the access code. + */ +class gr_framer_sink_1 : public gr_sync_block +{ + friend gr_framer_sink_1_sptr + gr_make_framer_sink_1 (gr_msg_queue_sptr target_queue); + + private: + enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; + + static const int MAX_PKT_LEN = 4096; + static const int HEADERBITLEN = 32; + + gr_msg_queue_sptr d_target_queue; // where to send the packet when received + state_t d_state; + unsigned int d_header; // header bits + int d_headerbitlen_cnt; // how many so far + + unsigned char d_packet[MAX_PKT_LEN]; // assembled payload + unsigned char d_packet_byte; // byte being assembled + int d_packet_byte_index; // which bit of d_packet_byte we're working on + int d_packetlen; // length of packet + int d_packetlen_cnt; // how many so far + + protected: + gr_framer_sink_1(gr_msg_queue_sptr target_queue); + + void enter_search(); + void enter_have_sync(); + void enter_have_header(int payload_len); + + bool header_ok() + { + // confirm that two copies of header info are identical + return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; + } + + int header_payload_len() + { + // header consists of two 16-bit shorts in network byte order + int t = (d_header >> 16) & 0xffff; + return t; + } + + public: + ~gr_framer_sink_1(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FRAMER_SINK_1_H */ diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.i b/gnuradio-core/src/lib/general/gr_framer_sink_1.i new file mode 100644 index 00000000..fbc55696 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,framer_sink_1); + +gr_framer_sink_1_sptr +gr_make_framer_sink_1(gr_msg_queue_sptr target_queue); + +class gr_framer_sink_1 : public gr_sync_block +{ + protected: + gr_framer_sink_1(gr_msg_queue_sptr target_queue); + + public: + ~gr_framer_sink_1(); +}; diff --git a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc new file mode 100644 index 00000000..271b8d33 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + + +gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity) +{ + return gr_frequency_modulator_fc_sptr (new gr_frequency_modulator_fc (sensitivity)); +} + +gr_frequency_modulator_fc::gr_frequency_modulator_fc (double sensitivity) + : gr_sync_block ("frequency_modulator_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_sensitivity (sensitivity), d_phase (0) +{ +} + +int +gr_frequency_modulator_fc::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]; + + for (int i = 0; i < noutput_items; i++){ + d_phase = d_phase + d_sensitivity * in[i]; + float oi, oq; + gr_sincosf (d_phase, &oq, &oi); + out[i] = gr_complex (oi, oq); + } + + // Limit the phase accumulator to [-16*pi,16*pi] + // to avoid loss of precision in the addition above. + + if (fabs (d_phase) > 16 * M_PI){ + double ii = trunc (d_phase / (2 * M_PI)); + d_phase = d_phase - (ii * 2 * M_PI); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h new file mode 100644 index 00000000..6080adb9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FREQUENCY_MODULATOR_FC_H +#define INCLUDED_GR_FREQUENCY_MODULATOR_FC_H + +#include + +class gr_frequency_modulator_fc; +typedef boost::shared_ptr gr_frequency_modulator_fc_sptr; + +gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity); + +/*! + * \brief Frequency modulator block + * \ingroup block + * + * float input; complex baseband output + */ +class gr_frequency_modulator_fc : public gr_sync_block +{ + double d_sensitivity; + double d_phase; + + friend gr_frequency_modulator_fc_sptr + gr_make_frequency_modulator_fc (double sensitivity); + + gr_frequency_modulator_fc (double sensitivity); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FREQUENCY_MODULATOR_FC_H */ diff --git a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i new file mode 100644 index 00000000..04a8b536 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,frequency_modulator_fc) + +gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity); + +class gr_frequency_modulator_fc : public gr_sync_block +{ + private: + gr_frequency_modulator_fc (double sensitivity); +}; diff --git a/gnuradio-core/src/lib/general/gr_fxpt.cc b/gnuradio-core/src/lib/general/gr_fxpt.cc new file mode 100644 index 00000000..62ed8bd6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +const float gr_fxpt::s_sine_table[1 << NBITS][2] = { +#include "sine_table.h" +}; + +// gcc 4.x fix +const float gr_fxpt::TWO_TO_THE_31; +const float gr_fxpt::PI; + +#if 0 +/* + * Compute sine using table lookup with linear interpolation. + * Each table entry contains slope and intercept. + */ +float +gr_fxpt::sin (gr_int32 x) +{ + gr_uint32 ux = x; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; +} + +float +gr_fxpt::cos (gr_int32 x) +{ + gr_uint32 ux = x + 0x40000000; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; +} +#endif diff --git a/gnuradio-core/src/lib/general/gr_fxpt.h b/gnuradio-core/src/lib/general/gr_fxpt.h new file mode 100644 index 00000000..fc8432d6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FXPT_H +#define INCLUDED_GR_FXPT_H + +#include + +/*! + * \brief fixed point sine and cosine and friends. + * + * fixed pt radians + * --------- -------- + * -2**31 -pi + * 0 0 + * 2**31-1 pi - epsilon + * + */ +class gr_fxpt +{ + static const int WORDBITS = 32; + static const int NBITS = 10; + static const float s_sine_table[1 << NBITS][2]; + static const float PI = 3.14159265358979323846; + static const float TWO_TO_THE_31 = 2147483648.0; +public: + + static gr_int32 + float_to_fixed (float x) + { + return (gr_int32) ((float) x * TWO_TO_THE_31 / PI); + } + + static float + fixed_to_float (gr_int32 x) + { + return x * (PI / TWO_TO_THE_31); + } + + /*! + * \brief Given a fixed point angle x, return float sine (x) + */ + static float + sin (gr_int32 x) + { + gr_uint32 ux = x; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; + } + + /* + * \brief Given a fixed point angle x, return float cosine (x) + */ + static float + cos (gr_int32 x) + { + gr_uint32 ux = x + 0x40000000; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; + } + +}; + +#endif /* INCLUDED_GR_FXPT_H */ diff --git a/gnuradio-core/src/lib/general/gr_fxpt_nco.h b/gnuradio-core/src/lib/general/gr_fxpt_nco.h new file mode 100644 index 00000000..c779bdfe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt_nco.h @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FXPT_NCO_H +#define INCLUDED_GR_FXPT_NCO_H + +#include +#include + +/*! + * \brief Numerically Controlled Oscillator (NCO) + */ +class gr_fxpt_nco { + gr_int32 d_phase; + gr_int32 d_phase_inc; + +public: + gr_fxpt_nco () : d_phase (0), d_phase_inc (0) {} + + ~gr_fxpt_nco () {} + + // radians + void set_phase (float angle) { + d_phase = gr_fxpt::float_to_fixed (angle); + } + + void adjust_phase (float delta_phase) { + d_phase += gr_fxpt::float_to_fixed (delta_phase); + } + + // angle_rate is in radians / step + void set_freq (float angle_rate){ + d_phase_inc = gr_fxpt::float_to_fixed (angle_rate); + } + + // angle_rate is a delta in radians / step + void adjust_freq (float delta_angle_rate) + { + d_phase_inc += gr_fxpt::float_to_fixed (delta_angle_rate); + } + + // increment current phase angle + + void step () + { + d_phase += d_phase_inc; + } + + void step (int n) + { + d_phase += d_phase_inc * n; + } + + // units are radians / step + float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); } + float get_freq () const { return gr_fxpt::fixed_to_float (d_phase_inc); } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const + { + *sinx = gr_fxpt::sin (d_phase); + *cosx = gr_fxpt::cos (d_phase); + } + + // compute cos and sin for a block of phase angles + void sincos (gr_complex *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = gr_complex(gr_fxpt::cos (d_phase) * ampl, gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin (float *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute cos for a block of phase angles + void cos (float *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(gr_fxpt::cos (d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin (short *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute cos for a block of phase angles + void cos (short *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(gr_fxpt::cos (d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin (int *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute cos for a block of phase angles + void cos (int *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(gr_fxpt::cos (d_phase) * ampl); + step (); + } + } + + // compute cos or sin for current phase angle + float cos () const { return gr_fxpt::cos (d_phase); } + float sin () const { return gr_fxpt::sin (d_phase); } +}; + +#endif /* INCLUDED_GR_FXPT_NCO_H */ diff --git a/gnuradio-core/src/lib/general/gr_fxpt_vco.h b/gnuradio-core/src/lib/general/gr_fxpt_vco.h new file mode 100644 index 00000000..c57a577b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt_vco.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FXPT_VCO_H +#define INCLUDED_GR_FXPT_VCO_H + +#include +#include + +/*! + * \brief Voltage Controlled Oscillator (VCO) + */ +class gr_fxpt_vco { + gr_int32 d_phase; + +public: + gr_fxpt_vco () : d_phase (0) {} + + ~gr_fxpt_vco () {} + + // radians + void set_phase (float angle) { + d_phase = gr_fxpt::float_to_fixed (angle); + } + + void adjust_phase (float delta_phase) { + d_phase += gr_fxpt::float_to_fixed (delta_phase); + } + + float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const + { + *sinx = gr_fxpt::sin (d_phase); + *cosx = gr_fxpt::cos (d_phase); + } + + // compute a block at a time + void cos (float *output, const float *input, int noutput_items, float k, float ampl = 1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(gr_fxpt::cos (d_phase) * ampl); + adjust_phase(input[i] * k); + } + } + + // compute cos or sin for current phase angle + float cos () const { return gr_fxpt::cos (d_phase); } + float sin () const { return gr_fxpt::sin (d_phase); } +}; + +#endif /* INCLUDED_GR_FXPT_VCO_H */ diff --git a/gnuradio-core/src/lib/general/gr_head.cc b/gnuradio-core/src/lib/general/gr_head.cc new file mode 100644 index 00000000..7771ed51 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +gr_head::gr_head (size_t sizeof_stream_item, int nitems) + : gr_sync_block ("head", + gr_make_io_signature (1, 1, sizeof_stream_item), + gr_make_io_signature (1, 1, sizeof_stream_item)), + d_nitems (nitems), d_ncopied_items (0) +{ +} + +gr_block_sptr +gr_make_head (size_t sizeof_stream_item, int nitems) +{ + return gr_block_sptr (new gr_head (sizeof_stream_item, nitems)); +} + +int +gr_head::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + if (d_ncopied_items >= d_nitems) + return -1; // Done! + + unsigned n = std::min (d_nitems - d_ncopied_items, noutput_items); + + if (n == 0) + return 0; + + memcpy (output_items[0], input_items[0], n * input_signature()->sizeof_stream_item (0)); + d_ncopied_items += n; + + return n; +} diff --git a/gnuradio-core/src/lib/general/gr_head.h b/gnuradio-core/src/lib/general/gr_head.h new file mode 100644 index 00000000..125ee14b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_HEAD_H +#define INCLUDED_GR_HEAD_H + +#include +#include // size_t + +/*! + * \brief copies the first N items to the output then signals done + * \ingroup block + * + * Useful for building test cases + */ + +class gr_head : public gr_sync_block +{ + friend gr_block_sptr gr_make_head (size_t sizeof_stream_item, int nitems); + gr_head (size_t sizeof_stream_item, int nitems); + + int d_nitems; + int d_ncopied_items; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +gr_block_sptr +gr_make_head (size_t sizeof_stream_item, int nitems); + + +#endif /* INCLUDED_GR_HEAD_H */ diff --git a/gnuradio-core/src/lib/general/gr_head.i b/gnuradio-core/src/lib/general/gr_head.i new file mode 100644 index 00000000..0a34214d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_head; +class gr_head : public gr_block { + friend gr_block_sptr gr_make_head (size_t sizeof_stream_item, int nitems); + gr_head (size_t sizeof_stream_item, int nitems); +}; + +%rename(head) gr_make_head; +gr_block_sptr gr_make_head (size_t sizeof_stream_item, int nitems); diff --git a/gnuradio-core/src/lib/general/gr_interleave.cc b/gnuradio-core/src/lib/general/gr_interleave.cc new file mode 100644 index 00000000..cae0cd9d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_interleave_sptr +gr_make_interleave (size_t itemsize) +{ + return gr_interleave_sptr (new gr_interleave (itemsize)); +} + +gr_interleave::gr_interleave (size_t itemsize) + : gr_sync_interpolator ("interleave", + gr_make_io_signature (1, gr_io_signature::IO_INFINITE, itemsize), + gr_make_io_signature (1, 1, itemsize), + 1), + d_itemsize (itemsize) +{ +} + +gr_interleave::~gr_interleave () +{ + // NOP +} + +bool +gr_interleave::check_topology (int ninputs, int noutputs) +{ + set_interpolation (ninputs); + return true; +} + +int +gr_interleave::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t nchan = input_items.size (); + size_t itemsize = d_itemsize; + const char **in = (const char **) &input_items[0]; + char *out = (char *) output_items[0]; + + for (int i = 0; i < noutput_items; i += nchan){ + for (unsigned int n = 0; n < nchan; n++){ + memcpy (out, in[n], itemsize); + out += itemsize; + in[n] += itemsize; + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_interleave.h b/gnuradio-core/src/lib/general/gr_interleave.h new file mode 100644 index 00000000..128ed7ce --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_INTERLEAVE_H +#define INCLUDED_GR_INTERLEAVE_H + +#include + +class gr_interleave; +typedef boost::shared_ptr gr_interleave_sptr; + +gr_interleave_sptr gr_make_interleave (size_t itemsize); + +/*! + * \brief interleave N inputs to a single output + * \ingroup block + */ +class gr_interleave : public gr_sync_interpolator +{ + friend gr_interleave_sptr gr_make_interleave (size_t itemsize); + + size_t d_itemsize; + + gr_interleave (size_t itemsize); + +public: + ~gr_interleave (); + + 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); + +}; + +#endif /* INCLUDED_GR_INTERLEAVE_H */ diff --git a/gnuradio-core/src/lib/general/gr_interleave.i b/gnuradio-core/src/lib/general/gr_interleave.i new file mode 100644 index 00000000..f082531f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,interleave) + +gr_interleave_sptr gr_make_interleave (size_t itemsize); + +class gr_interleave : public gr_sync_interpolator +{ + gr_interleave (size_t itemsize); +}; diff --git a/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc new file mode 100644 index 00000000..c43e7254 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_interleaved_short_to_complex_sptr +gr_make_interleaved_short_to_complex () +{ + return gr_interleaved_short_to_complex_sptr (new gr_interleaved_short_to_complex ()); +} + +gr_interleaved_short_to_complex::gr_interleaved_short_to_complex () + : gr_sync_decimator ("gr_interleaved_short_to_complex", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (1, 1, sizeof (gr_complex)), + 2) +{ +} + +int +gr_interleaved_short_to_complex::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const short *in = (const short *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + gri_interleaved_short_to_complex (in, out, 2 * noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h new file mode 100644 index 00000000..0eb1a32f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_H +#define INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_H + +#include + +class gr_interleaved_short_to_complex; +typedef boost::shared_ptr + gr_interleaved_short_to_complex_sptr; + +gr_interleaved_short_to_complex_sptr +gr_make_interleaved_short_to_complex (); + +/*! + * \brief Convert stream of interleaved shorts to a stream of complex + * \ingroup converter + */ + +class gr_interleaved_short_to_complex : public gr_sync_decimator +{ + friend gr_interleaved_short_to_complex_sptr gr_make_interleaved_short_to_complex (); + gr_interleaved_short_to_complex (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_H */ diff --git a/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i new file mode 100644 index 00000000..02d1ec01 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,interleaved_short_to_complex) + +gr_interleaved_short_to_complex_sptr gr_make_interleaved_short_to_complex (); + +class gr_interleaved_short_to_complex : public gr_sync_decimator +{ + gr_interleaved_short_to_complex (); +}; diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc new file mode 100644 index 00000000..e3020708 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t item_size, int n) +{ + return gr_keep_one_in_n_sptr (new gr_keep_one_in_n (item_size, n)); +} + +gr_keep_one_in_n::gr_keep_one_in_n (size_t item_size, int n) + : gr_block ("keep_one_in_n", + gr_make_io_signature (1, 1, item_size), + gr_make_io_signature (1, 1, item_size)), + d_n (n), d_count(n) +{ +} + +void +gr_keep_one_in_n::set_n(int n) +{ + if (n < 1) + n = 1; + + d_n = n; + d_count = n; +} + +int +gr_keep_one_in_n::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + size_t item_size = input_signature ()->sizeof_stream_item (0); + int ni = 0; + int no = 0; + + while (ni < ninput_items[0] && no < noutput_items){ + d_count--; + if (d_count <= 0){ + memcpy (out, in, item_size); // copy 1 item + out += item_size; + no++; + d_count = d_n; + } + in += item_size; + ni++; + } + + consume_each (ni); + return no; +} diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.h b/gnuradio-core/src/lib/general/gr_keep_one_in_n.h new file mode 100644 index 00000000..44a84740 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_KEEP_ONE_IN_N_H +#define INCLUDED_GR_KEEP_ONE_IN_N_H + +#include + +class gr_keep_one_in_n; +typedef boost::shared_ptr gr_keep_one_in_n_sptr; + +gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t item_size, int n); + + +/*! + * \brief decimate a stream, keeping one item out of every n. + * \ingroup block + */ +class gr_keep_one_in_n : public gr_block +{ + friend gr_keep_one_in_n_sptr + gr_make_keep_one_in_n (size_t item_size, int n); + + int d_n; + int d_count; + + protected: + gr_keep_one_in_n (size_t item_size, int n); + + public: + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_n(int n); + +}; + +#endif /* INCLUDED_GR_KEEP_ONE_IN_N_H */ diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.i b/gnuradio-core/src/lib/general/gr_keep_one_in_n.i new file mode 100644 index 00000000..13ed9a38 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,keep_one_in_n) + +gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t itemsize, int n); + +class gr_keep_one_in_n : public gr_block +{ + protected: + gr_keep_one_in_n (size_t itemsize, int n); + + public: + void set_n(int n); +}; diff --git a/gnuradio-core/src/lib/general/gr_kludge_copy.cc b/gnuradio-core/src/lib/general/gr_kludge_copy.cc new file mode 100644 index 00000000..bf980d23 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.cc @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_kludge_copy_sptr +gr_make_kludge_copy(size_t itemsize) +{ + return gr_kludge_copy_sptr(new gr_kludge_copy(itemsize)); +} + +gr_kludge_copy::gr_kludge_copy(size_t itemsize) + : gr_sync_block ("kludge_copy", + gr_make_io_signature (1, -1, sizeof (float)), + gr_make_io_signature (1, -1, sizeof (float))), + d_itemsize(itemsize) +{ +} + +bool +gr_kludge_copy::check_topology(int ninputs, int noutputs) +{ + return ninputs == noutputs; +} + +int +gr_kludge_copy::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float **in = (const float **) &input_items[0]; + float **out = (float **) &output_items[0]; + + int ninputs = input_items.size(); + for (int i = 0; i < ninputs; i++){ + memcpy(out[i], in[i], noutput_items * d_itemsize); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_kludge_copy.h b/gnuradio-core/src/lib/general/gr_kludge_copy.h new file mode 100644 index 00000000..d1cf54ee --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_KLUDGE_COPY_H +#define INCLUDED_GR_KLUDGE_COPY_H + +#include + +class gr_kludge_copy; +typedef boost::shared_ptr gr_kludge_copy_sptr; + +gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + +/*! + * \brief output[i] = input[i] + * \ingroup block + * + * This is a short term kludge to work around a problem with the hierarchical block impl. + */ +class gr_kludge_copy : public gr_sync_block +{ + size_t d_itemsize; + + friend gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + gr_kludge_copy(size_t itemsize); + + public: + + bool check_topology(int ninputs, int noutputs); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_kludge_copy.i b/gnuradio-core/src/lib/general/gr_kludge_copy.i new file mode 100644 index 00000000..828ec212 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,kludge_copy) + +gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + +class gr_kludge_copy : public gr_sync_block +{ + private: + gr_kludge_copy(size_t itemsize); +}; diff --git a/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc new file mode 100644 index 00000000..8a0b8768 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + + +gr_lfsr_32k_source_s_sptr +gr_make_lfsr_32k_source_s () +{ + return gr_lfsr_32k_source_s_sptr (new gr_lfsr_32k_source_s ()); +} + + +gr_lfsr_32k_source_s::gr_lfsr_32k_source_s () + : gr_sync_block ("lfsr_32k_source_s", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (short))), + d_index (0) +{ + gri_lfsr_32k lfsr; + + for (int i = 0; i < BUFSIZE; i++) + d_buffer[i] = lfsr.next_short (); +} + +int +gr_lfsr_32k_source_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + short *out = (short *) output_items[0]; + short *buf = d_buffer; + int index = d_index; + + for (int i = 0; i < noutput_items; i++){ + out[i] = buf[index]; + // index = (index + 1) & (BUFSIZE - 1); + index = index + 1; + if (index >= BUFSIZE) + index = 0; + } + + d_index = index; + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h new file mode 100644 index 00000000..d3d72a98 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_LFSR_32K_SOURCE_S_H +#define INCLUDED_GR_LFSR_32K_SOURCE_S_H + +#include +#include + +class gr_lfsr_32k_source_s; +typedef boost::shared_ptr gr_lfsr_32k_source_s_sptr; + +gr_lfsr_32k_source_s_sptr gr_make_lfsr_32k_source_s (); + +/*! + * \brief LFSR pseudo-random source with period of 2^15 bits (2^11 shorts) + * \ingroup source + * + * This source is typically used along with gr_check_lfsr_32k_s to test + * the USRP using its digital loopback mode. + */ +class gr_lfsr_32k_source_s : public gr_sync_block +{ + friend gr_lfsr_32k_source_s_sptr gr_make_lfsr_32k_source_s (); + + + static const int BUFSIZE = 2048 - 1; // ensure pattern isn't packet aligned + int d_index; + short d_buffer[BUFSIZE]; + + gr_lfsr_32k_source_s (); + + public: + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.i b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.i new file mode 100644 index 00000000..60b62679 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,lfsr_32k_source_s); + +gr_lfsr_32k_source_s_sptr gr_make_lfsr_32k_source_s (); + +class gr_lfsr_32k_source_s : public gr_sync_block +{ + private: + gr_lfsr_32k_source_s (); +}; diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc new file mode 100644 index 00000000..874ad84f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_complex +gr_lms_dfe_cc::slicer_0deg (gr_complex sample) +{ + gr_complex out; + if(fabs(real(sample))>fabs(imag(sample))) { + if(real(sample) > 0) + out = gr_complex(1,0); + else + out = gr_complex(-1,0); + } + else { + if(imag(sample) > 0) + out = gr_complex(0,1); + else + out = gr_complex(0,-1); + } + return out; +} + +gr_complex +gr_lms_dfe_cc::slicer_45deg (gr_complex sample) +{ + gr_complex out; + if(real(sample) > 0) + out = gr_complex(1,0); + else + out = gr_complex(-1,0); + if(imag(sample) > 0) + out += gr_complex(0,1); + else + out += gr_complex(0,-1); + return out; +} + +gr_lms_dfe_cc_sptr +gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps) +{ + return gr_lms_dfe_cc_sptr (new gr_lms_dfe_cc (lambda_ff, lambda_fb, + num_fftaps, num_fbtaps)); +} + +gr_lms_dfe_cc::gr_lms_dfe_cc (float lambda_ff, float lambda_fb , + unsigned int num_fftaps, unsigned int num_fbtaps) + : gr_sync_block ("lms_dfe_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), + d_ff_delayline(gr_rounduppow2(num_fftaps)), + d_fb_delayline(gr_rounduppow2(num_fbtaps)), + d_ff_taps(num_fftaps),d_fb_taps(num_fbtaps), + d_ff_index(0), d_fb_index(0) +{ + gr_zero_vector(d_ff_taps); + d_ff_taps [d_ff_taps.size()/2] = 1; + + gr_zero_vector(d_fb_taps); + gr_zero_vector(d_ff_delayline); + gr_zero_vector(d_fb_delayline); +} + +int +gr_lms_dfe_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (const gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + gr_complex acc, decision, error; + unsigned int i; + + unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 + unsigned int fb_mask = d_fb_delayline.size() - 1; + + int size = noutput_items; + while (size-- > 0){ + acc = 0; + d_ff_delayline[d_ff_index] = *iptr++; + + // Compute output + for (i=0; i < d_ff_taps.size(); i++) + acc += conj(d_ff_delayline[(i+d_ff_index) & ff_mask]) * d_ff_taps[i]; + + for (i=0; i < d_fb_taps.size(); i++) + acc -= conj(d_fb_delayline[(i+d_fb_index) & fb_mask]) * d_fb_taps[i]; + + decision = slicer_45deg(acc); + error = decision - acc; + + // Update taps + for (i=0; i < d_ff_taps.size(); i++) + d_ff_taps[i] += d_lambda_ff * conj(error) * d_ff_delayline[(i+d_ff_index) & ff_mask]; + + for (i=0; i < d_fb_taps.size(); i++) + d_fb_taps[i] -= d_lambda_fb * conj(error) * d_fb_delayline[(i+d_fb_index) & fb_mask]; + + d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index + d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index + + d_fb_delayline[d_fb_index] = decision; // Save decision in feedback + + *optr++ = acc; // Output decision + } + + if (0){ + std::cout << "FF Taps\t"; + for(i=0;i + +class gr_lms_dfe_cc; +typedef boost::shared_ptr gr_lms_dfe_cc_sptr; + +gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +/*! + * \brief Least-Mean-Square Decision Feedback Equalizer (complex in/out) + * \ingroup block + */ +class gr_lms_dfe_cc : public gr_sync_block +{ + friend gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + + float d_lambda_ff; + float d_lambda_fb; + std::vector d_ff_delayline; + std::vector d_fb_delayline; + std::vector d_ff_taps; + std::vector d_fb_taps; + unsigned int d_ff_index; + unsigned int d_fb_index; + + gr_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + gr_complex slicer_0deg(gr_complex baud); + gr_complex slicer_45deg(gr_complex baud); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i new file mode 100644 index 00000000..4ea4a6ae --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_cc) + +gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +class gr_lms_dfe_cc : public gr_sync_block +{ + private: + gr_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + gr_complex slicer_0deg(gr_complex baud); + gr_complex slicer_45deg(gr_complex baud); + gr_complex conjg(gr_complex val); +}; diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc new file mode 100644 index 00000000..017c90a2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc @@ -0,0 +1,122 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +float +slice(float val) +{ + if (val>0) + return 1; + else + return -1; +} + +gr_lms_dfe_ff_sptr +gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps) +{ + return gr_lms_dfe_ff_sptr (new gr_lms_dfe_ff (lambda_ff,lambda_fb,num_fftaps,num_fbtaps)); +} + +gr_lms_dfe_ff::gr_lms_dfe_ff (float lambda_ff, float lambda_fb , + unsigned int num_fftaps, unsigned int num_fbtaps) + : gr_sync_block ("lms_dfe_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), + d_ff_delayline(gr_rounduppow2(num_fftaps)), + d_fb_delayline(gr_rounduppow2(num_fbtaps)), + d_ff_taps(num_fftaps), d_fb_taps(num_fbtaps), + d_ff_index(0), d_fb_index(0) +{ + gr_zero_vector(d_ff_taps); + d_ff_taps [d_ff_taps.size()/2] = 1; + + gr_zero_vector(d_fb_taps); + gr_zero_vector(d_ff_delayline); + gr_zero_vector(d_fb_delayline); +} + +int +gr_lms_dfe_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *iptr = (const float *) input_items[0]; + float *optr = (float *) output_items[0]; + + float acc, decision, error; + unsigned int i; + + unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 + unsigned int fb_mask = d_fb_delayline.size() - 1; + + int size = noutput_items; + while(size-- > 0) { + acc = 0; + d_ff_delayline[d_ff_index] = *iptr++; + + // Compute output + for (i=0; i < d_ff_taps.size(); i++) + acc += d_ff_delayline[(i+d_ff_index) & ff_mask] * d_ff_taps[i]; + + for (i=0; i < d_fb_taps.size(); i++) + acc -= d_fb_delayline[(i+d_fb_index) & fb_mask] * d_fb_taps[i]; + + decision = slice(acc); + error = decision - acc; + + // Update taps + for (i=0; i < d_ff_taps.size(); i++) + d_ff_taps[i] += d_lambda_ff * error * d_ff_delayline[(i+d_ff_index) & ff_mask]; + + for (i=0; i < d_fb_taps.size(); i++) + d_fb_taps[i] -= d_lambda_fb * error * d_fb_delayline[(i+d_fb_index) & fb_mask]; + + d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index + d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index + + d_fb_delayline[d_fb_index] = decision; // Save decision in feedback + + *optr++ = acc; // Output decision + } + + if (0){ + std::cout << "FF Taps\t"; + for(i=0;i + +class gr_lms_dfe_ff; +typedef boost::shared_ptr gr_lms_dfe_ff_sptr; + +gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +/*! + * \brief Least-Mean-Square Decision Feedback Equalizer (float in/out) + * \ingroup block + */ +class gr_lms_dfe_ff : public gr_sync_block +{ + friend gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + + float d_lambda_ff; + float d_lambda_fb; + std::vector d_ff_delayline; + std::vector d_fb_delayline; + std::vector d_ff_taps; + std::vector d_fb_taps; + unsigned int d_ff_index; + unsigned int d_fb_index; + + gr_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i new file mode 100644 index 00000000..6b9e439d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_ff) + +gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +class gr_lms_dfe_ff : public gr_sync_block +{ + private: + gr_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); +}; diff --git a/gnuradio-core/src/lib/general/gr_log2_const.h b/gnuradio-core/src/lib/general/gr_log2_const.h new file mode 100644 index 00000000..fe255045 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_log2_const.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/* + * a bit of template hackery... + */ +#ifndef INCLUDED_GR_LOG2_CONST_H +#define INCLUDED_GR_LOG2_CONST_H + +#include + +template static inline int gr_log2_const() { assert(0); } + +template<> static inline int gr_log2_const<1>() { return 0; } +template<> static inline int gr_log2_const<2>() { return 1; } +template<> static inline int gr_log2_const<4>() { return 2; } +template<> static inline int gr_log2_const<8>() { return 3; } +template<> static inline int gr_log2_const<16>() { return 4; } +template<> static inline int gr_log2_const<32>() { return 5; } +template<> static inline int gr_log2_const<64>() { return 6; } +template<> static inline int gr_log2_const<128>() { return 7; } +template<> static inline int gr_log2_const<256>() { return 8; } +template<> static inline int gr_log2_const<512>() { return 9; } +template<> static inline int gr_log2_const<1024>(){ return 10; } + +#endif /* INCLUDED_GR_LOG2_CONST_H */ diff --git a/gnuradio-core/src/lib/general/gr_map_bb.cc b/gnuradio-core/src/lib/general/gr_map_bb.cc new file mode 100644 index 00000000..891ff02c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_map_bb_sptr +gr_make_map_bb (const std::vector &map) +{ + return gr_map_bb_sptr (new gr_map_bb (map)); +} + +gr_map_bb::gr_map_bb (const std::vector &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::max((size_t) 0x100, map.size()); + for (unsigned int i = 0; i < size; i++) + d_map[i] = map[i]; +} + +int +gr_map_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) + out[i] = d_map[in[i]]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_map_bb.h b/gnuradio-core/src/lib/general/gr_map_bb.h new file mode 100644 index 00000000..f5f7fa8d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MAP_BB_H +#define INCLUDED_GR_MAP_BB_H + +#include + +class gr_map_bb; +typedef boost::shared_ptr gr_map_bb_sptr; + +gr_map_bb_sptr gr_make_map_bb(const std::vector &map); + +/*! + * \brief output[i] = map[input[i]] + * \ingroup block + */ + +class gr_map_bb : public gr_sync_block +{ + friend gr_map_bb_sptr gr_make_map_bb(const std::vector &map); + + unsigned char d_map[0x100]; + + gr_map_bb(const std::vector &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/gnuradio-core/src/lib/general/gr_map_bb.i b/gnuradio-core/src/lib/general/gr_map_bb.i new file mode 100644 index 00000000..a4282a3e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,map_bb); + +gr_map_bb_sptr gr_make_map_bb (const std::vector &map); + +class gr_map_bb : public gr_sync_block +{ + private: + gr_map_bb (const std::vector &map); +}; + diff --git a/gnuradio-core/src/lib/general/gr_math.cc b/gnuradio-core/src/lib/general/gr_math.cc new file mode 100644 index 00000000..e2e7249e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_math.cc @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +/* + * Greatest Common Divisor, using Euclid's algorithm. + * [There are faster algorithms. See Knuth 4.5.2 if you care] + */ + +long +gr_gcd (long m, long n) +{ + if (m < 0) + m = -m; + + if (n < 0) + n = -n; + + while (n != 0){ + long t = m % n; + m = n; + n = t; + } + + return m; +} + + +/* + * These really need some configure hacking to figure out the right answer. + * As a stop gap, try for a macro, and if not that, then try std:: + */ + +// returns a non-zero value if value is "not-a-number" (NaN), and 0 otherwise + +#if defined(isnan) || !defined(CXX_HAS_STD_ISNAN) + +int +gr_isnan (double value) +{ + return isnan (value); +} + +#else + +int +gr_isnan (double value) +{ + return std::isnan (value); +} + +#endif + +// returns a non-zero value if the value of x has its sign bit set. +// +// This is not the same as `x < 0.0', because IEEE 754 floating point +// allows zero to be signed. The comparison `-0.0 < 0.0' is false, but +// `gr_signbit (-0.0)' will return a nonzero value. + +#ifdef signbit + +int +gr_signbit (double x) +{ + return signbit (x); +} + +#else + +int +gr_signbit (double x) +{ + return std::signbit (x); +} + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_math.h b/gnuradio-core/src/lib/general/gr_math.h new file mode 100644 index 00000000..5ce8fb78 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_math.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * mathematical odds and ends. + */ + +#ifndef _GR_MATH_H_ +#define _GR_MATH_H_ + +long gr_gcd (long m, long n); + +// returns a non-zero value if value is "not-a-number" (NaN), and 0 otherwise +int gr_isnan (double value); + +// returns a non-zero value if the value of x has its sign bit set. +// +// This is not the same as `x < 0.0', because IEEE 754 floating point +// allows zero to be signed. The comparison `-0.0 < 0.0' is false, but +// `gr_signbit (-0.0)' will return a nonzero value. + +int gr_signbit (double x); + +/*! + * \brief Fast arc tangent using table lookup and linear interpolation + * + * \param y component of input vector + * \param x component of input vector + * \returns float angle angle of vector (x, y) in radians + * + * This function calculates the angle of the vector (x,y) based on a + * table lookup and linear interpolation. The table uses a 256 point + * table covering -45 to +45 degrees and uses symetry to determine the + * final angle value in the range of -180 to 180 degrees. Note that + * this function uses the small angle approximation for values close + * to zero. This routine calculates the arc tangent with an average + * error of +/- 0.045 degrees. + */ +float gr_fast_atan2f(float y, float x); + +#endif /* _GR_MATH_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_misc.cc b/gnuradio-core/src/lib/general/gr_misc.cc new file mode 100644 index 00000000..d1520227 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_misc.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +unsigned int +gr_rounduppow2(unsigned int n) +{ + int i; + for (i=0;((n-1)>>i) != 0;i++) + ; + return 1< &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} diff --git a/gnuradio-core/src/lib/general/gr_misc.h b/gnuradio-core/src/lib/general/gr_misc.h new file mode 100644 index 00000000..177df964 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_misc.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_MISC_H +#define INCLUDED_GR_MISC_H + +#include + +unsigned int +gr_rounduppow2(unsigned int n); + +// FIXME should be template +void gr_zero_vector(std::vector &v); +void gr_zero_vector(std::vector &v); +void gr_zero_vector(std::vector &v); +void gr_zero_vector(std::vector &v); + + +#endif /* INCLUDED_GR_MISC_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_XX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_XX.cc.t new file mode 100644 index 00000000..a9c43224 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return @SPTR_NAME@ (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (int i = 0; i < noutput_items; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc *= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_multiply_XX.h.t b/gnuradio-core/src/lib/general/gr_multiply_XX.h.t new file mode 100644 index 00000000..cfa416f1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_XX.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = prod (input_0, input_1, ...) + * \ingroup block + * + * Multiply across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_multiply_XX.i.t b/gnuradio-core/src/lib/general/gr_multiply_XX.i.t new file mode 100644 index 00000000..8479aad6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_XX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_const_XX.cc.t new file mode 100644 index 00000000..b312b9c0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (@O_TYPE@ k) +{ + return @SPTR_NAME@ (new @NAME@ (k)); +} + +@NAME@::@NAME@ (@O_TYPE@ k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_k (k) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + while (size >= 8){ + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++ * d_k; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_XX.h.t b/gnuradio-core/src/lib/general/gr_multiply_const_XX.h.t new file mode 100644 index 00000000..6e771e0b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output = input * constant + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + + @O_TYPE@ d_k; // the constant + @NAME@ (@O_TYPE@ k); + + public: + @O_TYPE@ k () const { return d_k; } + void set_k (@O_TYPE@ k) { d_k = k; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_XX.i.t b/gnuradio-core/src/lib/general/gr_multiply_const_XX.i.t new file mode 100644 index 00000000..c2c814b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_XX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (@TYPE@ k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (@TYPE@ k); + + public: + @TYPE@ k () const { return d_k; } + void set_k (@TYPE@ k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_vXX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.cc.t new file mode 100755 index 00000000..9b723a3e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.cc.t @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k) +{ + return @SPTR_NAME@ (new @NAME@ (k)); +} + +@NAME@::@NAME@ (const std::vector<@I_TYPE@> k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof(@I_TYPE@)*k.size()), + gr_make_io_signature (1, 1, sizeof(@O_TYPE@)*k.size())) +{ + d_k = k; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@O_TYPE@ *)input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *)output_items[0]; + + int nitems_per_block = output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@); + + for (int i = 0; i < noutput_items; i++) + for (int j = 0; j < nitems_per_block; j++) + *optr++ = *iptr++ * d_k[j]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_vXX.h.t b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.h.t new file mode 100755 index 00000000..dba875c3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + +/*! + * \brief output vector = input vector * constant vector (element-wise) + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + + std::vector<@I_TYPE@> d_k; // the constant + @NAME@ (const std::vector<@I_TYPE@> k); + + public: + const std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> k) { d_k = k; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_vXX.i.t b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.i.t new file mode 100755 index 00000000..38c39943 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (const std::vector<@I_TYPE@> k); + + public: + std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_vXX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_vXX.cc.t new file mode 100755 index 00000000..cc242dda --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_vXX.cc.t @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (size_t nitems_per_block) +{ + return @SPTR_NAME@ (new @NAME@ (nitems_per_block)); +} + +@NAME@::@NAME@ (size_t nitems_per_block) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*nitems_per_block), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*nitems_per_block)) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + int nitems_per_block = output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@); + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nitems_per_block; j++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i*nitems_per_block+j]; + for (int k = 1; k < ninputs; k++) + acc *= ((@I_TYPE@ *) input_items[k])[i*nitems_per_block+j]; + + *optr++ = (@O_TYPE@) acc; + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_multiply_vXX.h.t b/gnuradio-core/src/lib/general/gr_multiply_vXX.h.t new file mode 100755 index 00000000..c6388d93 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_vXX.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +/*! + * \brief output = prod (input_0, input_1, ...) + * \ingroup block + * + * Element-wise multiply across all input vectors. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + + @NAME@ (size_t nitems_per_block); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_multiply_vXX.i.t b/gnuradio-core/src/lib/general/gr_multiply_vXX.i.t new file mode 100755 index 00000000..08109610 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_vXX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t nitems_per_block); +}; diff --git a/gnuradio-core/src/lib/general/gr_mute_XX.cc.t b/gnuradio-core/src/lib/general/gr_mute_XX.cc.t new file mode 100644 index 00000000..740821e5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_mute_XX.cc.t @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include +#include + + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (bool mute) +{ + return @SPTR_NAME@ (new @NAME@ (mute)); +} + +@NAME@::@NAME@ (bool mute) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_mute (mute) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + if (d_mute){ + memset (optr, 0, noutput_items * sizeof(@O_TYPE@)); + } + else { + while (size >= 8){ + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_mute_XX.h.t b/gnuradio-core/src/lib/general/gr_mute_XX.h.t new file mode 100644 index 00000000..88915322 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_mute_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (bool mute=false); + +/*! + * \brief output = input or zero if muted. + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (bool mute); + + bool d_mute; + @NAME@ (bool mute); + + public: + bool mute () const { return d_mute; } + void set_mute (bool mute) { d_mute = mute; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_mute_XX.i.t b/gnuradio-core/src/lib/general/gr_mute_XX.i.t new file mode 100644 index 00000000..413e5298 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_mute_XX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@(bool mute=false); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (bool mute); + + public: + bool mute () const { return d_mute; } + void set_mute (bool mute) { d_mute = mute; } +}; diff --git a/gnuradio-core/src/lib/general/gr_nco.h b/gnuradio-core/src/lib/general/gr_nco.h new file mode 100644 index 00000000..2cf41fd7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nco.h @@ -0,0 +1,197 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_NCO_H_ +#define _GR_NCO_H_ + + +#include +#include +#include +#include + +/*! + * \brief base class template for Numerically Controlled Oscillator (NCO) + */ + + +//FIXME Eventually generalize this to fixed point + +template +class gr_nco { +public: + gr_nco () : phase (0), phase_inc(0) {} + + virtual ~gr_nco () {} + + // radians + void set_phase (double angle) { + phase = angle; + } + + void adjust_phase (double delta_phase) { + phase += delta_phase; + } + + + // angle_rate is in radians / step + void set_freq (double angle_rate){ + phase_inc = angle_rate; + } + + // angle_rate is a delta in radians / step + void adjust_freq (double delta_angle_rate) + { + phase_inc += delta_angle_rate; + } + + // increment current phase angle + + void step () + { + phase += phase_inc; + if (fabs (phase) > M_PI){ + + while (phase > M_PI) + phase -= 2*M_PI; + + while (phase < -M_PI) + phase += 2*M_PI; + } + } + + void step (int n) + { + phase += phase_inc * n; + if (fabs (phase) > M_PI){ + + while (phase > M_PI) + phase -= 2*M_PI; + + while (phase < -M_PI) + phase += 2*M_PI; + } + } + + // units are radians / step + double get_phase () const { return phase; } + double get_freq () const { return phase_inc; } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const; + + // compute cos or sin for current phase angle + float cos () const { return std::cos (phase); } + float sin () const { return std::sin (phase); } + + // compute a block at a time + void sin (float *output, int noutput_items, double ampl = 1.0); + void cos (float *output, int noutput_items, double ampl = 1.0); + void sincos (gr_complex *output, int noutput_items, double ampl = 1.0); + void sin (short *output, int noutput_items, double ampl = 1.0); + void cos (short *output, int noutput_items, double ampl = 1.0); + void sin (int *output, int noutput_items, double ampl = 1.0); + void cos (int *output, int noutput_items, double ampl = 1.0); + +protected: + double phase; + double phase_inc; +}; + +template +void +gr_nco::sincos (float *sinx, float *cosx) const +{ + gr_sincosf (phase, sinx, cosx); +} + +template +void +gr_nco::sin (float *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(sin () * ampl); + step (); + } +} + +template +void +gr_nco::cos (float *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(cos () * ampl); + step (); + } +} + +template +void +gr_nco::sin (short *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(sin() * ampl); + step (); + } +} + +template +void +gr_nco::cos (short *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(cos () * ampl); + step (); + } +} + +template +void +gr_nco::sin (int *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(sin () * ampl); + step (); + } +} + +template +void +gr_nco::cos (int *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(cos () * ampl); + step (); + } +} + +template +void +gr_nco::sincos (gr_complex *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + float cosx, sinx; + sincos (&sinx, &cosx); + output[i] = gr_complex(cosx * ampl, sinx * ampl); + step (); + } +} +#endif /* _NCO_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_nlog10_ff.cc b/gnuradio-core/src/lib/general/gr_nlog10_ff.cc new file mode 100644 index 00000000..71e8279a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.cc @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_nlog10_ff_sptr +gr_make_nlog10_ff (float n, unsigned vlen, float k) +{ + return gr_nlog10_ff_sptr(new gr_nlog10_ff(n, vlen, k)); +} + +gr_nlog10_ff::gr_nlog10_ff(float n, unsigned vlen, float k) + : gr_sync_block("nlog10_ff", + gr_make_io_signature(1, 1, sizeof(float) * vlen), + gr_make_io_signature(1, 1, sizeof(float) * vlen)), + d_vlen(vlen), d_n(n), d_k(k) +{ +} + +gr_nlog10_ff::~gr_nlog10_ff() +{ +} + +int +gr_nlog10_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + float n = d_n; + float k = d_k; + + for (int i = 0; i < noi; i++) + out[i] = n * log10(std::max(in[i], (float) 1e-18)) + k; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_nlog10_ff.h b/gnuradio-core/src/lib/general/gr_nlog10_ff.h new file mode 100644 index 00000000..04a6f80d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_NLOG10_FF_H +#define INCLUDED_GR_NLOG10_FF_H + +#include + +class gr_nlog10_ff; +typedef boost::shared_ptr gr_nlog10_ff_sptr; + +gr_nlog10_ff_sptr gr_make_nlog10_ff (float n=1.0, unsigned vlen=1, float k=0); + +/*! + * \brief output = n*log10(input) + k + * \ingroup block + */ +class gr_nlog10_ff : public gr_sync_block +{ + friend gr_nlog10_ff_sptr gr_make_nlog10_ff (float n, unsigned vlen, float k); + + unsigned int d_vlen; + float d_n; + float d_k; + + gr_nlog10_ff (float n, unsigned vlen, float k); + +public: + ~gr_nlog10_ff(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_NLOG10_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_nlog10_ff.i b/gnuradio-core/src/lib/general/gr_nlog10_ff.i new file mode 100644 index 00000000..3dbd12d8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,nlog10_ff); + +gr_nlog10_ff_sptr gr_make_nlog10_ff (float n=1.0, unsigned vlen=1, float k=0); + +class gr_nlog10_ff : public gr_sync_block +{ + gr_nlog10_ff (float n, unsigned vlen, float k); + +public: + ~gr_nlog10_ff(); +}; diff --git a/gnuradio-core/src/lib/general/gr_noise_source_X.cc.t b/gnuradio-core/src/lib/general/gr_noise_source_X.cc.t new file mode 100644 index 00000000..401bed19 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_source_X.cc.t @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include <@NAME@.h> +#include +#include + + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed) +{ + return @NAME@_sptr (new @NAME@ (type, ampl, seed)); +} + + +@NAME@::@NAME@ (gr_noise_type_t type, float ampl, long seed) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_type (type), + d_ampl (ampl), + d_rng (seed) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *out = (@TYPE@ *) output_items[0]; + + switch (d_type){ +#if @IS_COMPLEX@ // complex? + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + out[i] = gr_complex (d_ampl * ((d_rng.ran1 () * 2.0) - 1.0), + d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + out[i] = d_ampl * d_rng.rayleigh_complex (); + break; + +#else // nope... + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * d_rng.gasdev ()); + break; + + case GR_LAPLACIAN: + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * d_rng.laplacian ()); + break; + + case GR_IMPULSE: // FIXME changeable impulse settings + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * d_rng.impulse (9)); + break; +#endif + + default: + throw std::runtime_error ("invalid type"); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_noise_source_X.h.t b/gnuradio-core/src/lib/general/gr_noise_source_X.h.t new file mode 100644 index 00000000..bc016aff --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_source_X.h.t @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +#include +#include + + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + +/*! + * \brief random number source + * \ingroup source + */ +class @NAME@ : public gr_sync_block { + friend @NAME@_sptr + gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed); + + gr_noise_type_t d_type; + float d_ampl; + gr_random d_rng; + + @NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_noise_source_X.i.t b/gnuradio-core/src/lib/general/gr_noise_source_X.i.t new file mode 100644 index 00000000..0a3ad96a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_source_X.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + +class @NAME@ : public gr_block { + private: + @NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } +}; diff --git a/gnuradio-core/src/lib/general/gr_noise_type.h b/gnuradio-core/src/lib/general/gr_noise_type.h new file mode 100644 index 00000000..886d5f44 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_type.h @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NOISE_TYPE_H +#define INCLUDED_GR_NOISE_TYPE_H + +typedef enum { + GR_UNIFORM = 200, GR_GAUSSIAN, GR_LAPLACIAN, GR_IMPULSE +} gr_noise_type_t; + +#endif /* INCLUDED_GR_NOISE_TYPE_H */ diff --git a/gnuradio-core/src/lib/general/gr_nop.cc b/gnuradio-core/src/lib/general/gr_nop.cc new file mode 100644 index 00000000..0a3f4f33 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +gr_nop::gr_nop (size_t sizeof_stream_item) + : gr_block ("nop", + gr_make_io_signature (0, -1, sizeof_stream_item), + gr_make_io_signature (0, -1, sizeof_stream_item)) +{ +} + +gr_block_sptr +gr_make_nop (size_t sizeof_stream_item) +{ + return gr_block_sptr (new gr_nop (sizeof_stream_item)); +} + +int +gr_nop::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // eat any input that's available + for (unsigned i = 0; i < ninput_items.size (); i++) + consume (i, ninput_items[i]); + + return noutput_items; +} + + diff --git a/gnuradio-core/src/lib/general/gr_nop.h b/gnuradio-core/src/lib/general/gr_nop.h new file mode 100644 index 00000000..faf93862 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NOP_H +#define INCLUDED_GR_NOP_H + +#include +#include // size_t + +/*! + * \brief Does nothing. Used for testing only. + * \ingroup block + */ +class gr_nop : public gr_block +{ + friend gr_block_sptr gr_make_nop (size_t sizeof_stream_item); + + gr_nop (size_t sizeof_stream_item); + + public: + virtual int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +gr_block_sptr +gr_make_nop (size_t sizeof_stream_item); + +#endif /* INCLUDED_GR_NOP_H */ diff --git a/gnuradio-core/src/lib/general/gr_nop.i b/gnuradio-core/src/lib/general/gr_nop.i new file mode 100644 index 00000000..556ad573 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_nop; +class gr_nop : public gr_block { + friend gr_block_sptr gr_make_nop (size_t sizeof_stream_item); + gr_nop (size_t sizeof_stream_item); +}; + +%rename(nop) gr_make_nop; +gr_block_sptr gr_make_nop (size_t sizeof_stream_item); diff --git a/gnuradio-core/src/lib/general/gr_null_sink.cc b/gnuradio-core/src/lib/general/gr_null_sink.cc new file mode 100644 index 00000000..7e9c7a79 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.cc @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_null_sink::gr_null_sink (size_t sizeof_stream_item) + : gr_sync_block ("null_sink", + gr_make_io_signature (1, 1, sizeof_stream_item), + gr_make_io_signature (0, 0, 0)) +{ +} + +gr_block_sptr +gr_make_null_sink (size_t sizeof_stream_item) +{ + return gr_block_sptr (new gr_null_sink (sizeof_stream_item)); +} + +int +gr_null_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_null_sink.h b/gnuradio-core/src/lib/general/gr_null_sink.h new file mode 100644 index 00000000..55b61aac --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NULL_SINK_H +#define INCLUDED_GR_NULL_SINK_H + +#include +#include // size_t + +/*! + * \brief Bit bucket + * \ingroup sink + */ + +class gr_null_sink : public gr_sync_block +{ + friend gr_block_sptr gr_make_null_sink (size_t sizeof_stream_item); + + gr_null_sink (size_t sizeof_stream_item); + + public: + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +gr_block_sptr +gr_make_null_sink (size_t sizeof_stream_item); + +#endif /* INCLUDED_GR_NULL_SINK_H */ diff --git a/gnuradio-core/src/lib/general/gr_null_sink.i b/gnuradio-core/src/lib/general/gr_null_sink.i new file mode 100644 index 00000000..145be901 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_null_sink; +class gr_null_sink : public gr_sync_block { + friend gr_block_sptr gr_make_null_sink (size_t sizeof_stream_item); + gr_null_sink (size_t sizeof_stream_item); +}; + +%rename(null_sink) gr_make_null_sink; +gr_block_sptr gr_make_null_sink (size_t sizeof_stream_item); diff --git a/gnuradio-core/src/lib/general/gr_null_source.cc b/gnuradio-core/src/lib/general/gr_null_source.cc new file mode 100644 index 00000000..65923cf7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.cc @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_null_source::gr_null_source (size_t sizeof_stream_item) + : gr_sync_block ("null_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof_stream_item)) +{ +} + +gr_block_sptr +gr_make_null_source (size_t sizeof_stream_item) +{ + return gr_block_sptr (new gr_null_source (sizeof_stream_item)); +} + +int +gr_null_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + void *optr = (void *) output_items[0]; + memset (optr, 0, noutput_items * output_signature()->sizeof_stream_item (0)); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_null_source.h b/gnuradio-core/src/lib/general/gr_null_source.h new file mode 100644 index 00000000..9fc43a07 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NULL_SOURCE_H +#define INCLUDED_GR_NULL_SOURCE_H + +#include + +/*! + * \brief A source of zeros. + * \ingroup source + */ + +class gr_null_source : public gr_sync_block +{ + friend gr_block_sptr gr_make_null_source (size_t sizeof_stream_item); + + gr_null_source (size_t sizeof_stream_item); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +gr_block_sptr +gr_make_null_source (size_t sizeof_stream_item); + +#endif /* INCLUDED_GR_NULL_SOURCE_H */ diff --git a/gnuradio-core/src/lib/general/gr_null_source.i b/gnuradio-core/src/lib/general/gr_null_source.i new file mode 100644 index 00000000..8a88f359 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_null_source; +class gr_null_source : public gr_sync_block { + friend gr_block_sptr gr_make_null_source (size_t sizeof_stream_item); + gr_null_source (size_t sizeof_stream_item); +}; + +%rename(null_source) gr_make_null_source; +gr_block_sptr gr_make_null_source (size_t sizeof_stream_item); diff --git a/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc new file mode 100644 index 00000000..7f470af9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_pa_2x2_phase_combiner_sptr +gr_make_pa_2x2_phase_combiner() +{ + return gr_pa_2x2_phase_combiner_sptr(new gr_pa_2x2_phase_combiner()); +} + +gr_pa_2x2_phase_combiner::gr_pa_2x2_phase_combiner () + : gr_sync_block ("pa_2x2_phase_combiner", + gr_make_io_signature (1, 1, NM * sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))) +{ + set_theta(0); +} + +void +gr_pa_2x2_phase_combiner::set_theta(float theta) +{ + d_theta = theta; + gr_complex j = gr_complex(0,1); + d_phase[0] = exp(j * (float) (M_PI * (sin(theta) + cos(theta)))); + d_phase[1] = exp(j * (float) (M_PI * cos(theta))); + d_phase[2] = exp(j * (float) (M_PI * sin(theta))); + d_phase[3] = exp(j * (float) 0.0); +} + +int +gr_pa_2x2_phase_combiner::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]; + + for (int i = 0; i < noutput_items; i++){ + gr_complex acc = 0; + acc += in[0] * d_phase[0]; + acc += in[1] * d_phase[1]; + acc += in[2] * d_phase[2]; + acc += in[3] * d_phase[3]; + out[i] = acc; + in += 4; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h new file mode 100644 index 00000000..e8634968 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PA_2X2_PHASE_COMBINER_H +#define INCLUDED_GR_PA_2X2_PHASE_COMBINER_H + +#include + +class gr_pa_2x2_phase_combiner; +typedef boost::shared_ptr gr_pa_2x2_phase_combiner_sptr; + +gr_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner (); + +/*! + * \brief pa_2x2 phase combiner + * \ingroup block + * + * Anntenas are arranged like this: + * + * 2 3 + * 0 1 + * + * dx and dy are lambda/2. + */ +class gr_pa_2x2_phase_combiner : public gr_sync_block +{ + static const int NM = 4; + + float d_theta; + gr_complex d_phase[NM]; + + gr_pa_2x2_phase_combiner (); + friend gr_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner(); + + public: + float theta() const { return d_theta; } + void set_theta(float theta); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_PA_2X2_PHASE_COMBINER_H */ diff --git a/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i new file mode 100644 index 00000000..a19413af --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pa_2x2_phase_combiner) + +gr_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner(); + +class gr_pa_2x2_phase_combiner : public gr_sync_block +{ + gr_pa_2x2_phase_combiner(); + + public: + float theta() const; + void set_theta(float theta); +}; diff --git a/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t new file mode 100644 index 00000000..f585c4a6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t @@ -0,0 +1,133 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include +#include +#include + +static const unsigned int BITS_PER_TYPE = sizeof(@I_TYPE@) * 8; +static const unsigned int LOG2_L_TYPE = gr_log2_const(); + + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness) +{ + return @SPTR_NAME@ + (new @NAME@ (bits_per_chunk,endianness)); +} + +@NAME@::@NAME@ (unsigned int bits_per_chunk, + gr_endianness_t endianness) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, -1, sizeof (@O_TYPE@))), + d_bits_per_chunk(bits_per_chunk),d_endianness(endianness),d_index(0) +{ + assert (bits_per_chunk <= BITS_PER_TYPE); + assert (bits_per_chunk > 0); + + set_relative_rate ((1.0 * BITS_PER_TYPE) / bits_per_chunk); +} + +void +@NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + + int input_required = (int) ceil((d_index + noutput_items * d_bits_per_chunk) / (1.0 * BITS_PER_TYPE)); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + //printf("Forecast wants %d needs %d\n",noutput_items,ninput_items_required[i]); + } +} + +unsigned int +get_bit_le (const @I_TYPE@ *in_vector,unsigned int bit_addr) +{ + @I_TYPE@ x = in_vector[bit_addr>>LOG2_L_TYPE]; + return (x>>(bit_addr&(BITS_PER_TYPE-1)))&1; +} + +unsigned int +get_bit_be (const @I_TYPE@ *in_vector,unsigned int bit_addr) +{ + @I_TYPE@ x = in_vector[bit_addr>>LOG2_L_TYPE]; + return (x>>((BITS_PER_TYPE-1)-(bit_addr&(BITS_PER_TYPE-1))))&1; +} + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + 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 + + switch (d_endianness){ + + case GR_MSB_FIRST: + for (int i = 0; i < noutput_items; i++){ + //printf("here msb %d\n",i); + @O_TYPE@ x = 0; + for(unsigned int j=0; j= (int) ((d_index+(BITS_PER_TYPE-1))>>LOG2_L_TYPE)); + } + + consume_each (d_index >> LOG2_L_TYPE); + d_index = d_index & (BITS_PER_TYPE-1); + //printf("got to end\n"); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.h.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.h.t new file mode 100644 index 00000000..1c9d2a0d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.h.t @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +/*! + * \brief Convert a stream of packed bytes or shorts to stream of unpacked bytes or shorts. + * \ingroup block + * + * input: stream of @I_TYPE@; output: stream of @O_TYPE@ + * + * This is the inverse of gr_unpacked_to_packed_XX. + * + * The bits in the bytes or shorts input stream are grouped into chunks of + * \p bits_per_chunk bits and each resulting chunk is written right- + * justified to the output stream of bytes or shorts. + * All b or 16 bits of the each input bytes or short are processed. + * The right thing is done if bits_per_chunk is not a power of two. + * + * The combination of gr_packed_to_unpacked_XX_ followed by + * gr_chunks_to_symbols_Xf or gr_chunks_to_symbols_Xc handles the + * general case of mapping from a stream of bytes or shorts into + * arbitrary float or complex symbols. + * + * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, + * \sa gr_packed_to_unpacked_ss, gr_unpacked_to_packed_ss, + * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. + * \sa gr_chunks_to_symbols_sf, gr_chunks_to_symbols_sc. + */ + +class @NAME@ : public gr_block +{ + friend @SPTR_NAME@ + gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + unsigned int d_bits_per_chunk; + gr_endianness_t d_endianness; + unsigned int d_index; + + 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); + + bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } + +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.i.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.i.t new file mode 100644 index 00000000..9517a8ac --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +class @NAME@ : public gr_block +{ + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); +}; diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.cc b/gnuradio-core/src/lib/general/gr_packet_sink.cc new file mode 100644 index 00000000..f88758b9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.cc @@ -0,0 +1,206 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERBOSE 0 + +static const int DEFAULT_THRESHOLD = 12; // detect access code with up to DEFAULT_THRESHOLD bits wrong + +inline void +gr_packet_sink::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; + d_shift_reg = 0; +} + +inline void +gr_packet_sink::enter_have_sync() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_sync\n"); + + d_state = STATE_HAVE_SYNC; + d_header = 0; + d_headerbitlen_cnt = 0; +} + +inline void +gr_packet_sink::enter_have_header(int payload_len) +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_header (payload_len = %d)\n", payload_len); + + d_state = STATE_HAVE_HEADER; + d_packetlen = payload_len; + d_packetlen_cnt = 0; + d_packet_byte = 0; + d_packet_byte_index = 0; +} + +gr_packet_sink_sptr +gr_make_packet_sink (const std::vector& sync_vector, + gr_msg_queue_sptr target_queue, int threshold) +{ + return gr_packet_sink_sptr (new gr_packet_sink (sync_vector, target_queue, threshold)); +} + + +gr_packet_sink::gr_packet_sink (const std::vector& sync_vector, + gr_msg_queue_sptr target_queue, int threshold) + : gr_sync_block ("packet_sink", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (0, 0, 0)), + d_target_queue(target_queue), d_threshold(threshold == -1 ? DEFAULT_THRESHOLD : threshold) +{ + d_sync_vector = 0; + for(int i=0;i<8;i++){ + d_sync_vector <<= 8; + d_sync_vector |= sync_vector[i]; + } + + enter_search(); +} + +gr_packet_sink::~gr_packet_sink () +{ +} + +int +gr_packet_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *inbuf = (float *) input_items[0]; + int count=0; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"),fflush(stderr); + + while (countmsg(), d_packet, d_packetlen_cnt); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + break; + } + } + } + break; + + default: + assert(0); + + } // switch + + } // while + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.h b/gnuradio-core/src/lib/general/gr_packet_sink.h new file mode 100644 index 00000000..3c468afd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.h @@ -0,0 +1,111 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PACKET_SINK_H +#define INCLUDED_GR_PACKET_SINK_H + +#include +#include + +class gr_packet_sink; +typedef boost::shared_ptr gr_packet_sink_sptr; + +gr_packet_sink_sptr +gr_make_packet_sink (const std::vector& 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 + */ +class gr_packet_sink : public gr_sync_block +{ + friend gr_packet_sink_sptr + gr_make_packet_sink (const std::vector& sync_vector, + gr_msg_queue_sptr target_queue, + int threshold); + + private: + enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; + + static const int MAX_PKT_LEN = 4096; + static const int HEADERBITLEN = 32; + + gr_msg_queue_sptr d_target_queue; // where to send the packet when received + unsigned long long d_sync_vector; // access code to locate start of packet + unsigned int d_threshold; // how many bits may be wrong in sync vector + + state_t d_state; + + unsigned long long d_shift_reg; // used to look for sync_vector + + unsigned int d_header; // header bits + int d_headerbitlen_cnt; // how many so far + + unsigned char d_packet[MAX_PKT_LEN]; // assembled payload + unsigned char d_packet_byte; // byte being assembled + int d_packet_byte_index; // which bit of d_packet_byte we're working on + int d_packetlen; // length of packet + int d_packetlen_cnt; // how many so far + + protected: + gr_packet_sink(const std::vector& sync_vector, + gr_msg_queue_sptr target_queue, + int threshold); + + void enter_search(); + void enter_have_sync(); + void enter_have_header(int payload_len); + + int slice(float x) { return x > 0 ? 1 : 0; } + + bool header_ok() + { + // confirm that two copies of header info are identical + return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; + } + + int header_payload_len() + { + // header consists of two 16-bit shorts in network byte order + int t = (d_header >> 16) & 0xffff; + return t; + } + + public: + ~gr_packet_sink(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + + //! return true if we detect carrier + bool carrier_sensed() const + { + return d_state != STATE_SYNC_SEARCH; + } + +}; + +#endif /* INCLUDED_GR_PACKET_SINK_H */ diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.i b/gnuradio-core/src/lib/general/gr_packet_sink.i new file mode 100644 index 00000000..fb960729 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,packet_sink) + +gr_packet_sink_sptr +gr_make_packet_sink (const std::vector& sync_vector, + gr_msg_queue_sptr target_queue, + int threshold = -1 // -1 -> use default + ); + +class gr_packet_sink : public gr_sync_block +{ + protected: + gr_packet_sink (const std::vector& sync_vector, + gr_msg_queue_sptr target_queue, + int threshold); + public: + ~gr_packet_sink (); + + bool carrier_sensed() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc new file mode 100644 index 00000000..95631f09 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + + +gr_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity) +{ + return gr_phase_modulator_fc_sptr (new gr_phase_modulator_fc (sensitivity)); +} + +gr_phase_modulator_fc::gr_phase_modulator_fc (double sensitivity) + : gr_sync_block ("phase_modulator_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_sensitivity (sensitivity), d_phase (0) +{ +} + +int +gr_phase_modulator_fc::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]; + + for (int i = 0; i < noutput_items; i++){ + d_phase = d_sensitivity * in[i]; + float oi, oq; + gr_sincosf (d_phase, &oq, &oi); + out[i] = gr_complex (oi, oq); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_phase_modulator_fc.h b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.h new file mode 100644 index 00000000..ea274275 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PHASE_MODULATOR_FC_H +#define INCLUDED_GR_PHASE_MODULATOR_FC_H + +#include + +class gr_phase_modulator_fc; +typedef boost::shared_ptr gr_phase_modulator_fc_sptr; + +gr_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity); + +/*! + * \brief Phase modulator block + * \ingroup block + * output=complex(cos(in*sensitivity),sin(in*sensitivity)) + */ +class gr_phase_modulator_fc : public gr_sync_block +{ + double d_sensitivity; + double d_phase; + + friend gr_phase_modulator_fc_sptr + gr_make_phase_modulator_fc (double sensitivity); + + gr_phase_modulator_fc (double sensitivity); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_PHASE_MODULATOR_FC_H */ diff --git a/gnuradio-core/src/lib/general/gr_phase_modulator_fc.i b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.i new file mode 100644 index 00000000..0ce25fd1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,phase_modulator_fc) + +gr_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity); + +class gr_phase_modulator_fc : public gr_sync_block +{ + private: + gr_phase_modulator_fc (double sensitivity); +}; diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc new file mode 100644 index 00000000..4736e77c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define M_TWOPI (2*M_PI) + +gr_pll_carriertracking_cc_sptr +gr_make_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq) +{ + return gr_pll_carriertracking_cc_sptr (new gr_pll_carriertracking_cc (alpha, beta, max_freq, min_freq)); +} + +gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq) + : gr_sync_block ("pll_carriertracking_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2), + d_locksig(0),d_lock_threshold(0),d_squelch_enable(false) +{ +} + +float +gr_pll_carriertracking_cc::mod_2pi (float in) +{ + if(in>M_PI) + return in-M_TWOPI; + else if(in<-M_PI) + return in+M_TWOPI; + else + return in; +} + +float +gr_pll_carriertracking_cc::phase_detector(gr_complex sample,float ref_phase) +{ + float sample_phase; + sample_phase = atan2(sample.imag(),sample.real()); + return mod_2pi(sample_phase-ref_phase); +} + +bool +gr_pll_carriertracking_cc::lock_detector(void) +{ + return (fabs(d_locksig) > d_lock_threshold); +} + +bool +gr_pll_carriertracking_cc::squelch_enable(bool set_squelch) +{ + return d_squelch_enable = set_squelch; +} + +float +gr_pll_carriertracking_cc::set_lock_threshold(float threshold) +{ + return d_lock_threshold = threshold; +} + +int +gr_pll_carriertracking_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + float error; + float t_imag, t_real; + + for (int i = 0; i < noutput_items; i++){ + error = phase_detector(iptr[i],d_phase); + + d_freq = d_freq + d_beta * error; + d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + gr_sincosf(d_phase,&t_imag,&t_real); + optr[i] = gr_complex(t_real,t_imag); + d_locksig = d_locksig * (1.0 - d_alpha) + d_alpha*(iptr[i].real() * t_real + iptr[i].imag() * t_imag); + + if ((d_squelch_enable) && !lock_detector()) + optr[i] = 0; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h new file mode 100644 index 00000000..679eb24d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,206 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PLL_CARRIERTRACKING_CC_H +#define INCLUDED_GR_PLL_CARRIERTRACKING_CC_H + +#include + +class gr_pll_carriertracking_cc; +typedef boost::shared_ptr gr_pll_carriertracking_cc_sptr; + +gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, + float max_freq, float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs the + * input signal mixed with that carrier. + * \ingroup block + * + * input: stream of complex; output: stream of complex + * + * This PLL locks onto a [possibly noisy] reference carrier on + * the input and outputs that signal, downconverted to DC + * + * All settings max_freq and min_freq are in terms of radians per sample, + * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian) + * and beta is the frequency gain (second order, units of radians per sample per radian) + * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc + */ + +class gr_pll_carriertracking_cc : public gr_sync_block +{ + friend gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, + float max_freq, float min_freq); + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq,d_locksig,d_lock_threshold; + bool d_squelch_enable; + gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +private: + float mod_2pi (float in); + float phase_detector(gr_complex sample,float ref_phase); +public: + bool lock_detector(void); + bool squelch_enable(bool); + float set_lock_threshold(float); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i new file mode 100644 index 00000000..2653f8e8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_carriertracking_cc); + +gr_pll_carriertracking_cc_sptr +gr_make_pll_carriertracking_cc (float alpha, float beta, + float max_freq, float min_freq); + +class gr_pll_carriertracking_cc : public gr_sync_block +{ + private: + gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq); + public: + bool lock_detector(void); + bool squelch_enable(bool); + float set_lock_threshold(float); + +}; diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc new file mode 100644 index 00000000..f15f160d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define M_TWOPI (2*M_PI) + +gr_pll_freqdet_cf_sptr +gr_make_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq) +{ + return gr_pll_freqdet_cf_sptr (new gr_pll_freqdet_cf (alpha, beta, max_freq, min_freq)); +} + +gr_pll_freqdet_cf::gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq) + : gr_sync_block ("pll_freqdet_cf", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2) +{ +} + +float +gr_pll_freqdet_cf::mod_2pi (float in) +{ + if(in>M_PI) + return in-M_TWOPI; + else if(in<-M_PI) + return in+M_TWOPI; + else + return in; +} + +float +gr_pll_freqdet_cf::phase_detector(gr_complex sample,float ref_phase) +{ + float sample_phase; + sample_phase = atan2(sample.imag(),sample.real()); + return mod_2pi(sample_phase-ref_phase); +} + +int +gr_pll_freqdet_cf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + float *optr = (float *) output_items[0]; + + float error; + int size = noutput_items; + + while (size-- > 0) { + error = phase_detector(*iptr++,d_phase); + + d_freq = d_freq + d_beta * error; + d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + *optr++ = d_freq; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h new file mode 100644 index 00000000..3d05a1c2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PLL_FREQDET_CF_H +#define INCLUDED_GR_PLL_FREQDET_CF_H + +#include + +class gr_pll_freqdet_cf; +typedef boost::shared_ptr gr_pll_freqdet_cf_sptr; + +gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, + float max_freq, float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs + * an estimate of that frequency. Useful for FM Demod. + * \ingroup block + * + * input: stream of complex; output: stream of floats + * + * This PLL locks onto a [possibly noisy] reference carrier on + * the input and outputs an estimate of that frequency in radians per sample. + * All settings max_freq and min_freq are in terms of radians per sample, + * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian) + * and beta is the frequency gain (second order, units of radians per sample per radian) + * \sa gr_pll_refout_cc, gr_pll_carriertracking_cc + */ + +class gr_pll_freqdet_cf : public gr_sync_block +{ + friend gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, + float max_freq, float min_freq); + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq; + gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +private: + float mod_2pi (float in); + float phase_detector(gr_complex sample,float ref_phase); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i new file mode 100644 index 00000000..8a27c4fd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_freqdet_cf) + + gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, + float max_freq, float min_freq); + +class gr_pll_freqdet_cf : public gr_sync_block +{ + private: + gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq); +}; diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc new file mode 100644 index 00000000..e5356118 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define M_TWOPI (2*M_PI) + +gr_pll_refout_cc_sptr +gr_make_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq) +{ + return gr_pll_refout_cc_sptr (new gr_pll_refout_cc (alpha, beta, max_freq, min_freq)); +} + +gr_pll_refout_cc::gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq) + : gr_sync_block ("pll_refout_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2) +{ +} + +float +gr_pll_refout_cc::mod_2pi (float in) +{ + if(in>M_PI) + return in-M_TWOPI; + else if(in<-M_PI) + return in+M_TWOPI; + else + return in; +} + +float +gr_pll_refout_cc::phase_detector(gr_complex sample,float ref_phase) +{ + float sample_phase; + sample_phase = atan2(sample.imag(),sample.real()); + return mod_2pi(sample_phase-ref_phase); +} + +int +gr_pll_refout_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + float error; + float t_imag, t_real; + int size = noutput_items; + + while (size-- > 0) { + error = phase_detector(*iptr++,d_phase); + + d_freq = d_freq + d_beta * error; + d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + gr_sincosf(d_phase,&t_imag,&t_real); + *optr++ = gr_complex(t_real,t_imag); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h new file mode 100644 index 00000000..c46a65ee --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +#ifndef INCLUDED_GR_PLL_REFOUT_CC_H +#define INCLUDED_GR_PLL_REFOUT_CC_H + +#include + +class gr_pll_refout_cc; +typedef boost::shared_ptr gr_pll_refout_cc_sptr; + +gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, + float max_freq, float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs a carrier + * \ingroup block + * + * input: stream of complex; output: stream of complex + * + * This PLL locks onto a [possibly noisy] reference carrier on + * the input and outputs a clean version which is phase and frequency + * aligned to it. + * + * All settings max_freq and min_freq are in terms of radians per sample, + * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian) + * and beta is the frequency gain (second order, units of radians per sample per radian) + * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc + */ +class gr_pll_refout_cc : public gr_sync_block +{ + friend gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, + float max_freq, float min_freq); + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq; + gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +private: + float mod_2pi (float in); + float phase_detector(gr_complex sample,float ref_phase); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.i b/gnuradio-core/src/lib/general/gr_pll_refout_cc.i new file mode 100644 index 00000000..8cb4fde8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_refout_cc) + + gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, + float max_freq, float min_freq); + +class gr_pll_refout_cc : public gr_sync_block +{ + private: + gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq); +}; diff --git a/gnuradio-core/src/lib/general/gr_prefix.cc.in b/gnuradio-core/src/lib/general/gr_prefix.cc.in new file mode 100644 index 00000000..25c6960c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefix.cc.in @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +const std::string +gr_prefix() +{ + return "@prefix@"; +} diff --git a/gnuradio-core/src/lib/general/gr_prefix.h b/gnuradio-core/src/lib/general/gr_prefix.h new file mode 100644 index 00000000..a521b619 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefix.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PREFIX_H +#define INCLUDED_GR_PREFIX_H + +#include + +/*! + * \brief return ./configure --prefix argument. Typically /usr/local + */ +const std::string gr_prefix(); + + +#endif /* INCLUDED_GR_PREFIX_H */ diff --git a/gnuradio-core/src/lib/general/gr_prefix.i b/gnuradio-core/src/lib/general/gr_prefix.i new file mode 100644 index 00000000..04e1899a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefix.i @@ -0,0 +1,5 @@ +/* -*- c++ -*- */ + +%rename(prefix) gr_prefix; + +const std::string gr_prefix(); diff --git a/gnuradio-core/src/lib/general/gr_prefs.cc b/gnuradio-core/src/lib/general/gr_prefs.cc new file mode 100644 index 00000000..c9721f0f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.cc @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +/* + * Stub implementations + */ + +static gr_prefs s_default_singleton; +static gr_prefs *s_singleton = &s_default_singleton; + +gr_prefs * +gr_prefs::singleton() +{ + return s_singleton; +} + +void +gr_prefs::set_singleton(gr_prefs *p) +{ + s_singleton = p; +} + +gr_prefs::~gr_prefs() +{ + // nop +} + +bool +gr_prefs::has_section(const std::string section) +{ + return false; +} + +bool +gr_prefs::has_option(const std::string section, const std::string option) +{ + return false; +} + +const std::string +gr_prefs::get_string(const std::string section, const std::string option, const std::string default_val) +{ + return default_val; +} + +bool +gr_prefs::get_bool(const std::string section, const std::string option, bool default_val) +{ + return default_val; +} + +long +gr_prefs::get_long(const std::string section, const std::string option, long default_val) +{ + return default_val; +} + +double +gr_prefs::get_double(const std::string section, const std::string option, double default_val) +{ + return default_val; +} + diff --git a/gnuradio-core/src/lib/general/gr_prefs.h b/gnuradio-core/src/lib/general/gr_prefs.h new file mode 100644 index 00000000..eaf74870 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PREFS_H +#define INCLUDED_GR_PREFS_H + +#include + +/*! + * \brief Base class for representing user preferences a la windows INI files. + * + * The real implementation is in Python, and is accessable from C++ + * via the magic of SWIG directors. + */ + +class gr_prefs +{ +public: + static gr_prefs *singleton(); + static void set_singleton(gr_prefs *p); + + virtual ~gr_prefs(); + + /*! + * \brief Does \p section exist? + */ + virtual bool has_section(const std::string section); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string section, const std::string option); + + /*! + * \brief If option exists return associated value; else default_val. + */ + virtual const std::string get_string(const std::string section, + const std::string option, + const std::string default_val); + + /*! + * \brief If option exists and value can be converted to bool, return it; else default_val. + */ + virtual bool get_bool(const std::string section, + const std::string option, + bool default_val); + + /*! + * \brief If option exists and value can be converted to long, return it; else default_val. + */ + virtual long get_long(const std::string section, + const std::string option, + long default_val); + + /*! + * \brief If option exists and value can be converted to double, return it; else default_val. + */ + virtual double get_double(const std::string section, + const std::string option, + double default_val); +}; + + +#endif /* INCLUDED_GR_PREFS_H */ diff --git a/gnuradio-core/src/lib/general/gr_prefs.i b/gnuradio-core/src/lib/general/gr_prefs.i new file mode 100644 index 00000000..d11da173 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.i @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Generate SWIG directors for gr_prefs. +%feature("director") gr_prefs; + +class gr_prefs +{ +public: + static gr_prefs *singleton(); + static void set_singleton(gr_prefs *p); + + virtual ~gr_prefs(); + + /*! + * \brief Does \p section exist? + */ + virtual bool has_section(const std::string section); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string section, const std::string option); + + /*! + * \brief If option exists return associated value; else default_val. + */ + virtual const std::string get_string(const std::string section, + const std::string option, + const std::string default_val); + + /*! + * \brief If option exists and value can be converted to bool, return it; else default_val. + */ + virtual bool get_bool(const std::string section, + const std::string option, + bool default_val); + + /*! + * \brief If option exists and value can be converted to long, return it; else default_val. + */ + virtual long get_long(const std::string section, + const std::string option, + long default_val); + + /*! + * \brief If option exists and value can be converted to double, return it; else default_val. + */ + virtual double get_double(const std::string section, + const std::string option, + double default_val); +}; + diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc new file mode 100644 index 00000000..73c7343b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +gr_probe_avg_mag_sqrd_c_sptr +gr_make_probe_avg_mag_sqrd_c(double threshold_db, double alpha) +{ + return gr_probe_avg_mag_sqrd_c_sptr(new gr_probe_avg_mag_sqrd_c(threshold_db, alpha)); +} + +gr_probe_avg_mag_sqrd_c::gr_probe_avg_mag_sqrd_c (double threshold_db, double alpha) + : gr_sync_block ("probe_avg_mag_sqrd_c", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_iir(alpha), d_unmuted(false), d_level(0) +{ + set_threshold (threshold_db); +} + +gr_probe_avg_mag_sqrd_c::~gr_probe_avg_mag_sqrd_c() +{ +} + + +int +gr_probe_avg_mag_sqrd_c::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]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + d_iir.filter(mag_sqrd); // computed for side effect: prev_output() + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + d_level = d_iir.prev_output(); + return noutput_items; +} + +double +gr_probe_avg_mag_sqrd_c::threshold() const +{ + return 10 * std::log10(d_threshold); +} + +void +gr_probe_avg_mag_sqrd_c::set_threshold(double decibels) +{ + // convert to absolute threshold (mag squared) + d_threshold = std::pow(10.0, decibels/10); +} + +void +gr_probe_avg_mag_sqrd_c::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h new file mode 100644 index 00000000..85e2244b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_H + +#include +#include + +class gr_probe_avg_mag_sqrd_c; +typedef boost::shared_ptr gr_probe_avg_mag_sqrd_c_sptr; + +gr_probe_avg_mag_sqrd_c_sptr +gr_make_probe_avg_mag_sqrd_c (double threshold_db, double alpha = 0.0001); + +/*! + * \brief compute avg magnitude squared. + * \ingroup sink + * + * input: gr_complex + * + * Compute a running average of the magnitude squared of the the input. + * The level and indication as to whether the level exceeds threshold + * can be retrieved with the level and unmuted accessors. + */ +class gr_probe_avg_mag_sqrd_c : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir d_iir; + bool d_unmuted; + double d_level; + + friend gr_probe_avg_mag_sqrd_c_sptr + gr_make_probe_avg_mag_sqrd_c (double threshold_db, double alpha); + + gr_probe_avg_mag_sqrd_c (double threshold_db, double alpha); + +public: + ~gr_probe_avg_mag_sqrd_c (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + + double threshold() const; + + // SETTERS + void set_alpha (double alpha); + void set_threshold (double decibels); +}; + +#endif /* INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i new file mode 100644 index 00000000..0b8000c5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_avg_mag_sqrd_c); + +gr_probe_avg_mag_sqrd_c_sptr +gr_make_probe_avg_mag_sqrd_c (double threshold_db, double alpha = 0.0001); + +class gr_probe_avg_mag_sqrd_c : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + void set_alpha (double alpha); + void set_threshold (double decibels); + double threshold(); +}; diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc new file mode 100644 index 00000000..439138f0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +gr_probe_avg_mag_sqrd_f_sptr +gr_make_probe_avg_mag_sqrd_f(double threshold_db, double alpha) +{ + return gr_probe_avg_mag_sqrd_f_sptr(new gr_probe_avg_mag_sqrd_f(threshold_db, alpha)); +} + +gr_probe_avg_mag_sqrd_f::gr_probe_avg_mag_sqrd_f (double threshold_db, double alpha) + : gr_sync_block ("probe_avg_mag_sqrd_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_iir(alpha), d_unmuted(false), d_level(0) +{ + set_threshold (threshold_db); +} + +gr_probe_avg_mag_sqrd_f::~gr_probe_avg_mag_sqrd_f() +{ +} + + +int +gr_probe_avg_mag_sqrd_f::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]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i]*in[i]; + d_iir.filter(mag_sqrd); // computed for side effect: prev_output() + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + d_level = d_iir.prev_output(); + return noutput_items; +} + +double +gr_probe_avg_mag_sqrd_f::threshold() const +{ + return 10 * std::log10(d_threshold); +} + +void +gr_probe_avg_mag_sqrd_f::set_threshold(double decibels) +{ + // convert to absolute threshold (mag sqrd) + d_threshold = std::pow(10.0, decibels/10); +} + +void +gr_probe_avg_mag_sqrd_f::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h new file mode 100644 index 00000000..5f20a5ca --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_H + +#include +#include + +class gr_probe_avg_mag_sqrd_f; +typedef boost::shared_ptr gr_probe_avg_mag_sqrd_f_sptr; + +gr_probe_avg_mag_sqrd_f_sptr +gr_make_probe_avg_mag_sqrd_f (double threshold_db, double alpha = 0.0001); + +/*! + * \brief compute avg magnitude squared. + * \ingroup sink + * + * input: float + * + * Compute a running average of the magnitude squared of the the input. + * The level and indication as to whether the level exceeds threshold + * can be retrieved with the level and unmuted accessors. + */ +class gr_probe_avg_mag_sqrd_f : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir d_iir; + bool d_unmuted; + double d_level; + + friend gr_probe_avg_mag_sqrd_f_sptr + gr_make_probe_avg_mag_sqrd_f (double threshold_db, double alpha); + + gr_probe_avg_mag_sqrd_f (double threshold_db, double alpha); + +public: + ~gr_probe_avg_mag_sqrd_f (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + + double threshold() const; + + // SETTERS + void set_alpha (double alpha); + void set_threshold (double decibels); +}; + +#endif /* INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i new file mode 100644 index 00000000..f58caa2d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_avg_mag_sqrd_f); + +gr_probe_avg_mag_sqrd_f_sptr +gr_make_probe_avg_mag_sqrd_f (double threshold_db, double alpha = 0.0001); + +class gr_probe_avg_mag_sqrd_f : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + double threshold() const; + void set_alpha (double alpha); + void set_threshold (double decibels); +}; diff --git a/gnuradio-core/src/lib/general/gr_probe_signal_f.cc b/gnuradio-core/src/lib/general/gr_probe_signal_f.cc new file mode 100644 index 00000000..8c94b036 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_signal_f.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +gr_probe_signal_f_sptr +gr_make_probe_signal_f() +{ + return gr_probe_signal_f_sptr(new gr_probe_signal_f()); +} + +gr_probe_signal_f::gr_probe_signal_f () + : gr_sync_block ("probe_signal_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_level(0) +{ +} + +gr_probe_signal_f::~gr_probe_signal_f() +{ +} + + +int +gr_probe_signal_f::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]; + + if (noutput_items > 0) + d_level = in[noutput_items-1]; + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_probe_signal_f.h b/gnuradio-core/src/lib/general/gr_probe_signal_f.h new file mode 100644 index 00000000..72811b20 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_signal_f.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PROBE_SIGNAL_F_H +#define INCLUDED_GR_PROBE_SIGNAL_F_H + +#include + +class gr_probe_signal_f; +typedef boost::shared_ptr gr_probe_signal_f_sptr; + +gr_probe_signal_f_sptr +gr_make_probe_signal_f (); + +/*! + * \brief Sink that allows a sample to be grabbed from Python. + * \ingroup sink + */ +class gr_probe_signal_f : public gr_sync_block +{ + float d_level; + + friend gr_probe_signal_f_sptr + gr_make_probe_signal_f(); + + gr_probe_signal_f(); + +public: + ~gr_probe_signal_f(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + float level() const { return d_level; } + +}; + +#endif /* INCLUDED_GR_PROBE_SIGNAL_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_signal_f.i b/gnuradio-core/src/lib/general/gr_probe_signal_f.i new file mode 100644 index 00000000..14fc6f19 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_signal_f.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_signal_f); + +gr_probe_signal_f_sptr +gr_make_probe_signal_f (); + +class gr_probe_signal_f : public gr_sync_block +{ +public: + float level () const { return d_level; } +}; diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc new file mode 100644 index 00000000..33c12872 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_pwr_squelch_cc_sptr +gr_make_pwr_squelch_cc(double threshold, double alpha, int ramp, bool gate) +{ + return gr_pwr_squelch_cc_sptr(new gr_pwr_squelch_cc(threshold, alpha, ramp, gate)); +} + +gr_pwr_squelch_cc::gr_pwr_squelch_cc(double threshold, double alpha, int ramp, bool gate) : + gr_squelch_base_cc("pwr_squelch_cc", ramp, gate), + d_iir(alpha) +{ + set_threshold(threshold); +} + +std::vector gr_pwr_squelch_cc::squelch_range() const +{ + std::vector r(3); + r[0] = -50.0; // min FIXME + r[1] = +50.0; // max FIXME + r[2] = (r[1] - r[0]) / 100; // step size + + return r; +} + +void gr_pwr_squelch_cc::update_state(const gr_complex &in) +{ + d_pwr = d_iir.filter(in.real()*in.real()+in.imag()*in.imag()); +} diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h new file mode 100644 index 00000000..2822ee59 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PWR_SQUELCH_CC_H +#define INCLUDED_GR_PWR_SQUELCH_CC_H + +#include +#include +#include + +class gr_pwr_squelch_cc; +typedef boost::shared_ptr gr_pwr_squelch_cc_sptr; + +gr_pwr_squelch_cc_sptr +gr_make_pwr_squelch_cc(double db, double alpha = 0.0001, int ramp=0, bool gate=false); + +/*! + * \brief gate or zero output when input power below threshold + * \ingroup block + */ +class gr_pwr_squelch_cc : public gr_squelch_base_cc +{ +private: + double d_threshold; + double d_pwr; + gr_single_pole_iir d_iir; + + friend gr_pwr_squelch_cc_sptr gr_make_pwr_squelch_cc(double db, double alpha, int ramp, bool gate); + gr_pwr_squelch_cc(double db, double alpha, int ramp, bool gate); + +protected: + virtual void update_state(const gr_complex &in); + virtual bool mute() const { return d_pwr < d_threshold; } + +public: + std::vector squelch_range() const; + + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } +}; + +#endif /* INCLUDED_GR_PWR_SQUELCH_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i new file mode 100644 index 00000000..41832ab7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pwr_squelch_cc); + +%include gr_squelch_base_cc.i + +gr_pwr_squelch_cc_sptr +gr_make_pwr_squelch_cc(double db, double alpha=0.0001, int ramp=0, bool gate=false); + +class gr_pwr_squelch_cc : public gr_squelch_base_cc +{ +private: + gr_pwr_squelch_cc(double db, double alpha, int ramp, bool gate); + +public: + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } + std::vector squelch_range() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc new file mode 100644 index 00000000..8bc3aad6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_pwr_squelch_ff_sptr +gr_make_pwr_squelch_ff(double threshold, double alpha, int ramp, bool gate) +{ + return gr_pwr_squelch_ff_sptr(new gr_pwr_squelch_ff(threshold, alpha, ramp, gate)); +} + +gr_pwr_squelch_ff::gr_pwr_squelch_ff(double threshold, double alpha, int ramp, bool gate) : + gr_squelch_base_ff("pwr_squelch_ff", ramp, gate), + d_iir(alpha) +{ + set_threshold(threshold); +} + +std::vector gr_pwr_squelch_ff::squelch_range() const +{ + std::vector r(3); + r[0] = -50.0; // min FIXME + r[1] = +50.0; // max FIXME + r[2] = (r[1] - r[0]) / 100; // step size + + return r; +} + +void gr_pwr_squelch_ff::update_state(const float &in) +{ + d_pwr = d_iir.filter(in*in); +} diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h new file mode 100644 index 00000000..1eb61b16 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PWR_SQUELCH_FF_H +#define INCLUDED_GR_PWR_SQUELCH_FF_H + +#include +#include +#include + +class gr_pwr_squelch_ff; +typedef boost::shared_ptr gr_pwr_squelch_ff_sptr; + +gr_pwr_squelch_ff_sptr +gr_make_pwr_squelch_ff(double db, double alpha = 0.0001, int ramp=0, bool gate=false); + +/*! + * \brief gate or zero output when input power below threshold + * \ingroup block + */ +class gr_pwr_squelch_ff : public gr_squelch_base_ff +{ +private: + double d_threshold; + double d_pwr; + gr_single_pole_iir d_iir; + + friend gr_pwr_squelch_ff_sptr gr_make_pwr_squelch_ff(double db, double alpha, int ramp, bool gate); + gr_pwr_squelch_ff(double db, double alpha, int ramp, bool gate); + +protected: + virtual void update_state(const float &in); + virtual bool mute() const { return d_pwr < d_threshold; } + +public: + std::vector squelch_range() const; + + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } +}; + +#endif /* INCLUDED_GR_PWR_SQUELCH_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i new file mode 100644 index 00000000..4bc16b10 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pwr_squelch_ff); + +%include gr_squelch_base_ff.i + +gr_pwr_squelch_ff_sptr +gr_make_pwr_squelch_ff(double db, double alpha=0.0001, int ramp=0, bool gate=false); + +class gr_pwr_squelch_ff : public gr_squelch_base_ff +{ +private: + gr_pwr_squelch_ff(double db, double alpha, int ramp, bool gate); + +public: + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } + std::vector squelch_range() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc new file mode 100644 index 00000000..eb1fae85 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_quadrature_demod_cf::gr_quadrature_demod_cf (float gain) + : gr_sync_block ("quadrature_demod_cf", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))), + d_gain (gain) +{ + set_history (2); // we need to look at the previous value +} + +gr_quadrature_demod_cf_sptr +gr_make_quadrature_demod_cf (float gain) +{ + return gr_quadrature_demod_cf_sptr (new gr_quadrature_demod_cf (gain)); +} + +int +gr_quadrature_demod_cf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + float *out = (float *) output_items[0]; + in++; // ensure that in[-1] is valid + + for (int i = 0; i < noutput_items; i++){ + gr_complex product = in[i] * conj (in[i-1]); + // out[i] = d_gain * arg (product); + out[i] = d_gain * gr_fast_atan2f(imag(product), real(product)); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h new file mode 100644 index 00000000..7e625e7a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_QUADRATURE_DEMOD_CF_H +#define INCLUDED_GR_QUADRATURE_DEMOD_CF_H + +#include + +class gr_quadrature_demod_cf; +typedef boost::shared_ptr gr_quadrature_demod_cf_sptr; +gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + +/*! + * \brief quadrature demodulator: complex in, float out + * \ingroup block + * + * This can be used to demod FM, FSK, GMSK, etc. + * The input is complex baseband. + */ +class gr_quadrature_demod_cf : public gr_sync_block +{ + friend gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + gr_quadrature_demod_cf (float gain); + + float d_gain; + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_QUADRATURE_DEMOD_CF_H */ diff --git a/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i new file mode 100644 index 00000000..685b278f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC (gr, quadrature_demod_cf) + +gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + +class gr_quadrature_demod_cf : public gr_sync_block +{ + gr_quadrature_demod_cf (float gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_random.cc b/gnuradio-core/src/lib/general/gr_random.cc new file mode 100644 index 00000000..a56f2875 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random.cc @@ -0,0 +1,180 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Copyright 1997 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + */ + +#include +#include + +#define IA 16807 +#define IM 2147483647 +#define AM (1.0/IM) +#define IQ 127773 +#define IR 2836 +#define NDIV (1+(IM-1)/NTAB) +#define EPS 1.2e-7 +#define RNMX (1.0-EPS) + + +gr_random::gr_random (long seed) +{ + reseed (seed); +} + +void +gr_random::reseed (long seed) +{ + d_seed = seed; + d_iy = 0; + for (int i = 0; i < NTAB; i++) + d_iv[i] = 0; + d_iset = 0; + d_gset = 0; +} + +/* + * This looks like it returns a uniform random deviate between 0.0 and 1.0 + * It looks similar to code from "Numerical Recipes in C". + */ +float gr_random::ran1() +{ + int j; + long k; + float temp; + + if (d_seed <= 0 || !d_iy) { + if (-d_seed < 1) + d_seed=1; + else + d_seed = -d_seed; + for (j=NTAB+7;j>=0;j--) { + k=d_seed/IQ; + d_seed=IA*(d_seed-k*IQ)-IR*k; + if (d_seed < 0) + d_seed += IM; + if (j < NTAB) + d_iv[j] = d_seed; + } + d_iy=d_iv[0]; + } + k=(d_seed)/IQ; + d_seed=IA*(d_seed-k*IQ)-IR*k; + if (d_seed < 0) + d_seed += IM; + j=d_iy/NDIV; + d_iy=d_iv[j]; + d_iv[j] = d_seed; + temp=AM * d_iy; + if (temp > RNMX) + temp = RNMX; + return temp; +} + +/* + * Returns a normally distributed deviate with zero mean and variance 1. + * Also looks like it's from "Numerical Recipes in C". + */ +float gr_random::gasdev() +{ + float fac,rsq,v1,v2; + d_iset = 1 - d_iset; + if (d_iset) { + do { + v1=2.0*ran1()-1.0; + v2=2.0*ran1()-1.0; + rsq=v1*v1+v2*v2; + } while (rsq >= 1.0 || rsq == 0.0); + fac= sqrt(-2.0*log(rsq)/rsq); + d_gset=v1*fac; + return v2*fac; + } + return d_gset; +} + +/* + * Copied from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + +float gr_random::laplacian() +{ + float z = ran1(); + if (z < 0.5) + return log(2.0 * z) / M_SQRT2; + else + return -log(2.0 * (1.0 - z)) / M_SQRT2; +} + +/* + * Copied from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + + // 5 => scratchy, 8 => Geiger + +float gr_random::impulse(float factor = 5) +{ + float z = -M_SQRT2 * log(ran1()); + if (fabsf(z) <= factor) + return 0.0; + else + return z; +} + +/* + * Complex rayleigh is really gaussian I and gaussian Q + * It can also be generated by real rayleigh magnitude and + * uniform random angle + * Adapted from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + +gr_complex gr_random::rayleigh_complex() +{ + return gr_complex(gasdev(),gasdev()); +} + +/* Other option + mag = rayleigh(); + ang = 2.0 * M_PI * RNG(); + *Rx = rxx * cos(z); + *Iy = rxx * sin(z); +*/ + + +float gr_random::rayleigh() +{ + return sqrt(-2.0 * log(ran1())); +} diff --git a/gnuradio-core/src/lib/general/gr_random.h b/gnuradio-core/src/lib/general/gr_random.h new file mode 100644 index 00000000..9726ee9b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_RANDOM_H +#define INCLUDED_GR_RANDOM_H + +#include + +/*! + * \brief pseudo random number generator + */ +class gr_random { +protected: + static const int NTAB = 32; + long d_seed; + long d_iy; + long d_iv[NTAB]; + int d_iset; + float d_gset; + + +public: + gr_random (long seed=3021); + + void reseed (long seed); + + /*! + * \brief uniform random deviate in the range [0.0, 1.0) + */ + float ran1 (); + + /*! + * \brief normally distributed deviate with zero mean and variance 1 + */ + float gasdev (); + + float laplacian (); + float impulse (float factor); + float rayleigh (); + gr_complex rayleigh_complex (); +}; + +#endif /* INCLUDED_GR_RANDOM_H */ + diff --git a/gnuradio-core/src/lib/general/gr_remez.cc b/gnuradio-core/src/lib/general/gr_remez.cc new file mode 100644 index 00000000..10039000 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.cc @@ -0,0 +1,1031 @@ +/************************************************************************** + * Parks-McClellan algorithm for FIR filter design (C version) + *------------------------------------------------- + * Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu) + * Copyright (c) 2004 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Sep 1999 - Paul Kienzle (pkienzle@cs.indiana.edu) + * Modified for use in octave as a replacement for the matlab function + * remez.mex. In particular, magnitude responses are required for all + * band edges rather than one per band, griddensity is a parameter, + * and errors are returned rather than printed directly. + * Mar 2000 - Kai Habel (kahacjde@linux.zrz.tu-berlin.de) + * Change: ColumnVector x=arg(i).vector_value(); + * to: ColumnVector x(arg(i).vector_value()); + * There appear to be some problems with the routine Search. See comments + * therein [search for PAK:]. I haven't looked closely at the rest + * of the code---it may also have some problems. + *************************************************************************/ + +/* + * This code was extracted from octave.sf.net, and wrapped with + * GNU Radio glue. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + + +#ifndef LOCAL_BUFFER +#include +#define LOCAL_BUFFER(T, buf, size) \ + std::vector buf ## _vector (size); \ + T *buf = &(buf ## _vector[0]) +#endif + + +#define CONST const +#define BANDPASS 1 +#define DIFFERENTIATOR 2 +#define HILBERT 3 + +#define NEGATIVE 0 +#define POSITIVE 1 + +#define Pi 3.14159265358979323846 +#define Pi2 (2*Pi) + +#define GRIDDENSITY 16 +#define MAXITERATIONS 40 + +/******************* + * CreateDenseGrid + *================= + * Creates the dense grid of frequencies from the specified bands. + * Also creates the Desired Frequency Response function (D[]) and + * the Weight function (W[]) on that dense grid + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int numtaps - Number of taps in the resulting filter + * int numband - Number of bands in user specification + * double bands[] - User-specified band edges [2*numband] + * double des[] - Desired response per band [2*numband] + * double weight[] - Weight per band [numband] + * int symmetry - Symmetry of filter - used for grid check + * int griddensity + * + * OUTPUT: + * ------- + * int gridsize - Number of elements in the dense frequency grid + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + *******************/ + +static void +CreateDenseGrid (int r, int numtaps, int numband, const double bands[], + const double des[], const double weight[], int gridsize, + double Grid[], double D[], double W[], + int symmetry, int griddensity) +{ + int i, j, k, band; + double delf, lowf, highf, grid0; + + delf = 0.5/(griddensity*r); + +/* + * For differentiator, hilbert, + * symmetry is odd and Grid[0] = max(delf, bands[0]) + */ + grid0 = (symmetry == NEGATIVE) && (delf > bands[0]) ? delf : bands[0]; + + j=0; + for (band=0; band < numband; band++) + { + lowf = (band==0 ? grid0 : bands[2*band]); + highf = bands[2*band + 1]; + k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */ + for (i=0; i (0.5 - delf)) && + (numtaps % 2)) + { + Grid[gridsize-1] = 0.5-delf; + } +} + + +/******************** + * InitialGuess + *============== + * Places Extremal Frequencies evenly throughout the dense grid. + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int gridsize - Number of elements in the dense frequency grid + * + * OUTPUT: + * ------- + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + ********************/ + +static void +InitialGuess (int r, int Ext[], int gridsize) +{ + int i; + + for (i=0; i<=r; i++) + Ext[i] = i * (gridsize-1) / r; +} + + +/*********************** + * CalcParms + *=========== + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + * + * OUTPUT: + * ------- + * double ad[] - 'b' in Oppenheim & Schafer [r+1] + * double x[] - [r+1] + * double y[] - 'C' in Oppenheim & Schafer [r+1] + ***********************/ + +static void +CalcParms (int r, int Ext[], double Grid[], double D[], double W[], + double ad[], double x[], double y[]) +{ + int i, j, k, ld; + double sign, xi, delta, denom, numer; + +/* + * Find x[] + */ + for (i=0; i<=r; i++) + x[i] = cos(Pi2 * Grid[Ext[i]]); + +/* + * Calculate ad[] - Oppenheim & Schafer eq 7.132 + */ + ld = (r-1)/15 + 1; /* Skips around to avoid round errors */ + for (i=0; i<=r; i++) + { + denom = 1.0; + xi = x[i]; + for (j=0; j0.0) && (E[0]>E[1])) || + ((E[0]<0.0) && (E[0]=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) || + ((E[i]<=E[i-1]) && (E[i]= 2*r) return -3; + foundExt[k++] = i; + } + } + +/* + * Check for extremum at 0.5 + */ + j = gridsize-1; + if (((E[j]>0.0) && (E[j]>E[j-1])) || + ((E[j]<0.0) && (E[j]= 2*r) return -3; + foundExt[k++] = j; + } + + // PAK: we sometimes get not enough extremal frequencies + if (k < r+1) return -2; + + +/* + * Remove extra extremals + */ + extra = k - (r+1); + assert(extra >= 0); + + while (extra > 0) + { + if (E[foundExt[0]] > 0.0) + up = 1; /* first one is a maxima */ + else + up = 0; /* first one is a minima */ + + l=0; + alt = 1; + for (j=1; j 0.0)) + up = 1; /* switch to a maxima */ + else + { + alt = 0; + // PAK: break now and you will delete the smallest overall + // extremal. If you want to delete the smallest of the + // pair of non-alternating extremals, then you must do: + // + // if (fabs(E[foundExt[j]]) < fabs(E[foundExt[j-1]])) l=j; + // else l=j-1; + break; /* Ooops, found two non-alternating */ + } /* extrema. Delete smallest of them */ + } /* if the loop finishes, all extrema are alternating */ + +/* + * If there's only one extremal and all are alternating, + * delete the smallest of the first/last extremals. + */ + if ((alt) && (extra == 1)) + { + if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]])) + /* Delete last extremal */ + l = k-1; + // PAK: changed from l = foundExt[k-1]; + else + /* Delete first extremal */ + l = 0; + // PAK: changed from l = foundExt[0]; + } + + for (j=l; j max) + max = current; + } + return (((max-min)/max) < 0.0001); +} + +/******************** + * remez + *======= + * Calculates the optimal (in the Chebyshev/minimax sense) + * FIR filter impulse response given a set of band edges, + * the desired reponse on those bands, and the weight given to + * the error in those bands. + * + * INPUT: + * ------ + * int numtaps - Number of filter coefficients + * int numband - Number of bands in filter specification + * double bands[] - User-specified band edges [2 * numband] + * double des[] - User-specified band responses [2 * numband] + * double weight[] - User-specified error weights [numband] + * int type - Type of filter + * + * OUTPUT: + * ------- + * double h[] - Impulse response of final filter [numtaps] + * returns - true on success, false on failure to converge + ********************/ + +static int +remez (double h[], int numtaps, + int numband, const double bands[], + const double des[], const double weight[], + int type, int griddensity) +{ + double *Grid, *W, *D, *E; + int i, iter, gridsize, r, *Ext; + double *taps, c; + double *x, *y, *ad; + int symmetry; + + if (type == BANDPASS) + symmetry = POSITIVE; + else + symmetry = NEGATIVE; + + r = numtaps/2; /* number of extrema */ + if ((numtaps%2) && (symmetry == POSITIVE)) + r++; + +/* + * Predict dense grid size in advance for memory allocation + * .5 is so we round up, not truncate + */ + gridsize = 0; + for (i=0; i 0.0001) + W[i] = W[i]/Grid[i]; + } + } + +/* + * For odd or Negative symmetry filters, alter the + * D[] and W[] according to Parks McClellan + */ + if (symmetry == POSITIVE) + { + if (numtaps % 2 == 0) + { + for (i=0; i +gr_remez (int order, + const std::vector &arg_bands, + const std::vector &arg_response, + const std::vector &arg_weight, + const std::string filter_type, + int grid_density + ) throw (std::runtime_error) +{ + int numtaps = order + 1; + if (numtaps < 4) + punt ("gr_remez: number of taps must be >= 3"); + + int numbands = arg_bands.size () / 2; + LOCAL_BUFFER (double, bands, numbands * 2); + if (numbands < 1 || arg_bands.size () % 2 == 1) + punt ("gr_remez: must have an even number of band edges"); + + for (unsigned int i = 1; i < arg_bands.size (); i++){ + if (arg_bands[i] < arg_bands[i-1]) + punt ("gr_remez: band edges must be nondecreasing"); + } + + if (arg_bands[0] < 0 || arg_bands[arg_bands.size () - 1] > 1) + punt ("gr_remez: band edges must be in the range [0,1]"); + + for (int i = 0; i < 2 * numbands; i++) + bands[i] = arg_bands[i] / 2; // FIXME why / 2? + + LOCAL_BUFFER (double, response, numbands * 2); + if (arg_response.size () != arg_bands.size ()) + punt ("gr_remez: must have one response magnitude for each band edge"); + + for (int i = 0; i < 2 * numbands; i++) + response[i] = arg_response[i]; + + LOCAL_BUFFER (double, weight, numbands); + for (int i = 0; i < numbands; i++) + weight[i] = 1.0; + + if (arg_weight.size () != 0){ + if ((int) arg_weight.size () != numbands) + punt ("gr_remez: need one weight for each band [=length(band)/2]"); + for (int i = 0; i < numbands; i++) + weight[i] = arg_weight [i]; + } + + int itype = 0; + if (filter_type == "bandpass") + itype = BANDPASS; + else if (filter_type == "differentiator") + itype = DIFFERENTIATOR; + else if (filter_type == "hilbert") + itype = HILBERT; + else + punt ("gr_remez: unknown ftype '" + filter_type + "'"); + + if (grid_density < 16) + punt ("gr_remez: grid_density is too low; must be >= 16"); + + LOCAL_BUFFER (double, coeff, numtaps + 5); // FIXME why + 5? + int err = remez (coeff, numtaps, numbands, + bands, response, weight, itype, grid_density); + + if (err == -1) + punt ("gr_remez: failed to converge"); + + if (err == -2) + punt ("gr_remez: insufficient extremals -- cannot continue"); + + if (err == -3) + punt ("gr_remez: too many extremals -- cannot continue"); + + return std::vector (&coeff[0], &coeff[numtaps]); +} + + + +#if 0 +/* == Octave interface starts here ====================================== */ + +DEFUN_DLD (remez, args, , + "b = remez(n, f, a [, w] [, ftype] [, griddensity])\n\ +Parks-McClellan optimal FIR filter design.\n\ +n gives the number of taps in the returned filter\n\ +f gives frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]\n\ +a gives amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]\n\ +w gives weighting applied to each band\n\ +ftype is 'bandpass', 'hilbert' or 'differentiator'\n\ +griddensity determines how accurately the filter will be\n\ + constructed. The minimum value is 16, but higher numbers are\n\ + slower to compute.\n\ +\n\ +Frequency is in the range (0, 1), with 1 being the nyquist frequency") +{ + octave_value_list retval; + int i; + + int nargin = args.length(); + if (nargin < 3 || nargin > 6) { + print_usage("remez"); + return retval; + } + + int numtaps = NINT (args(0).double_value()) + 1; // #coeff = filter order+1 + if (numtaps < 4) { + error("remez: number of taps must be an integer greater than 3"); + return retval; + } + + ColumnVector o_bands(args(1).vector_value()); + int numbands = o_bands.length()/2; + OCTAVE_LOCAL_BUFFER(double, bands, numbands*2); + if (numbands < 1 || o_bands.length()%2 == 1) { + error("remez: must have an even number of band edges"); + return retval; + } + for (i=1; i < o_bands.length(); i++) { + if (o_bands(i) 1) { + error("band edges must be in the range [0,1]"); + return retval; + } + for(i=0; i < 2*numbands; i++) bands[i] = o_bands(i)/2.0; + + ColumnVector o_response(args(2).vector_value()); + OCTAVE_LOCAL_BUFFER (double, response, numbands*2); + if (o_response.length() != o_bands.length()) { + error("remez: must have one response magnitude for each band edge"); + return retval; + } + for(i=0; i < 2*numbands; i++) response[i] = o_response(i); + + std::string stype = std::string("bandpass"); + int density = 16; + OCTAVE_LOCAL_BUFFER (double, weight, numbands); + for (i=0; i < numbands; i++) weight[i] = 1.0; + if (nargin > 3) { + if (args(3).is_real_matrix()) { + ColumnVector o_weight(args(3).vector_value()); + if (o_weight.length() != numbands) { + error("remez: need one weight for each band [=length(band)/2]"); + return retval; + } + for (i=0; i < numbands; i++) weight[i] = o_weight(i); + } + else if (args(3).is_string()) + stype = args(3).string_value(); + else if (args(3).is_real_scalar()) + density = NINT(args(3).double_value()); + else { + error("remez: incorrect argument list"); + return retval; + } + } + if (nargin > 4) { + if (args(4).is_string() && !args(3).is_string()) + stype = args(4).string_value(); + else if (args(4).is_real_scalar() && !args(3).is_real_scalar()) + density = NINT(args(4).double_value()); + else { + error("remez: incorrect argument list"); + return retval; + } + } + if (nargin > 5) { + if (args(5).is_real_scalar() + && !args(4).is_real_scalar() + && !args(3).is_real_scalar()) + density = NINT(args(4).double_value()); + else { + error("remez: incorrect argument list"); + return retval; + } + } + + int itype; + if (stype == "bandpass") + itype = BANDPASS; + else if (stype == "differentiator") + itype = DIFFERENTIATOR; + else if (stype == "hilbert") + itype = HILBERT; + else { + error("remez: unknown ftype '%s'", stype.data()); + return retval; + } + + if (density < 16) { + error("remez: griddensity is too low; must be greater than 16"); + return retval; + } + + OCTAVE_LOCAL_BUFFER (double, coeff, numtaps+5); + int err = remez(coeff,numtaps,numbands,bands,response,weight,itype,density); + + if (err == -1) + warning("remez: -- failed to converge -- returned filter may be bad."); + else if (err == -2) { + error("remez: insufficient extremals--cannot continue"); + return retval; + } + else if (err == -3) { + error("remez: too many extremals--cannot continue"); + return retval; + } + + ColumnVector h(numtaps); + while(numtaps--) h(numtaps) = coeff[numtaps]; + + return octave_value(h); +} + +/* +%!test +%! b = [ +%! 0.0415131831103279 +%! 0.0581639884202646 +%! -0.0281579212691008 +%! -0.0535575358002337 +%! -0.0617245915143180 +%! 0.0507753178978075 +%! 0.2079018331396460 +%! 0.3327160895375440 +%! 0.3327160895375440 +%! 0.2079018331396460 +%! 0.0507753178978075 +%! -0.0617245915143180 +%! -0.0535575358002337 +%! -0.0281579212691008 +%! 0.0581639884202646 +%! 0.0415131831103279]; +%! assert(remez(15,[0,0.3,0.4,1],[1,1,0,0]),b,1e-14); + + */ + +#endif diff --git a/gnuradio-core/src/lib/general/gr_remez.h b/gnuradio-core/src/lib/general/gr_remez.h new file mode 100644 index 00000000..c910803b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_REMEZ_H +#define INCLUDED_GR_REMEZ_H + +#include +#include +#include + +/*! + * \brief Parks-McClellan FIR filter design. + * + * + * Calculates the optimal (in the Chebyshev/minimax sense) FIR filter + * inpulse reponse given a set of band edges, the desired reponse on + * those bands, and the weight given to the error in those bands. + * + * \param order filter order (number of taps in the returned filter - 1) + * \param bands frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...] + * \param ampl desired amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...] + * \param error_weight weighting applied to each band (usually 1) + * \param filter_type one of "bandpass", "hilbert" or "differentiator" + * \param grid_density determines how accurately the filter will be constructed. \ + * The minimum value is 16; higher values are slower to compute. + * + * Frequency is in the range [0, 1], with 1 being the Nyquist frequency (Fs/2) + * + * \returns vector of computed taps + * + * \throws std::runtime_error if args are invalid or calculation fails to converge. + */ + +std::vector +gr_remez (int order, + const std::vector &bands, + const std::vector &l, + const std::vector &error_weight, + const std::string filter_type = "bandpass", + int grid_density = 16 + ) throw (std::runtime_error); + + +#endif /* INCLUDED_GR_REMEZ_H */ diff --git a/gnuradio-core/src/lib/general/gr_remez.i b/gnuradio-core/src/lib/general/gr_remez.i new file mode 100644 index 00000000..2e2471e2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%rename(remez) gr_remez; + +std::vector +gr_remez (int order, + const std::vector &bands, + const std::vector &l, + const std::vector &error_weight, + const std::string filter_type = "bandpass", + int grid_density = 16 + ) throw (std::runtime_error); diff --git a/gnuradio-core/src/lib/general/gr_reverse.cc b/gnuradio-core/src/lib/general/gr_reverse.cc new file mode 100644 index 00000000..099deb60 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_reverse.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +std::vector +gr_reverse (const std::vector &taps) +{ + int size = taps.size (); + std::vector new_taps(size); + + if (size == 0) + return new_taps; + + for (int i = 0; i < size; i++) + new_taps[i] = taps[size - i - 1]; + + return new_taps; +} + + +std::vector +gr_reverse (const std::vector &taps) +{ + int size = taps.size (); + std::vector new_taps(size); + + if (size == 0) + return new_taps; + + for (int i = 0; i < size; i++) + new_taps[i] = taps[size - i - 1]; + + return new_taps; +} + diff --git a/gnuradio-core/src/lib/general/gr_reverse.h b/gnuradio-core/src/lib/general/gr_reverse.h new file mode 100644 index 00000000..cff53255 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_reverse.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_REVERSE_H +#define INCLUDED_GR_REVERSE_H + +#include +#include + +// reverse the order of taps +std::vector gr_reverse (const std::vector &taps); +std::vector gr_reverse (const std::vector &taps); + + +#endif /* INCLUDED_GR_REVERSE_H */ diff --git a/gnuradio-core/src/lib/general/gr_rms_cf.cc b/gnuradio-core/src/lib/general/gr_rms_cf.cc new file mode 100644 index 00000000..7abfefd1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +gr_rms_cf_sptr +gr_make_rms_cf(double alpha) +{ + return gr_rms_cf_sptr(new gr_rms_cf(alpha)); +} + +gr_rms_cf::gr_rms_cf (double alpha) + : gr_sync_block ("rms_cf", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(float))), + d_iir(alpha) +{ + +} + +gr_rms_cf::~gr_rms_cf() +{ +} + + +int +gr_rms_cf::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]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + double f = d_iir.filter(mag_sqrd); + out[i] = sqrt(f); + } + + return noutput_items; +} + +void +gr_rms_cf::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_rms_cf.h b/gnuradio-core/src/lib/general/gr_rms_cf.h new file mode 100644 index 00000000..bc16c23e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_RMS_CF_H +#define INCLUDED_GR_RMS_CF_H + +#include +#include + +class gr_rms_cf; +typedef boost::shared_ptr gr_rms_cf_sptr; + +gr_rms_cf_sptr +gr_make_rms_cf (double alpha = 0.0001); + +/*! + * \brief RMS average power + */ +class gr_rms_cf : public gr_sync_block +{ + gr_single_pole_iir d_iir; + bool d_unmuted; + + friend gr_rms_cf_sptr + gr_make_rms_cf (double alpha); + + gr_rms_cf (double alpha); + +public: + ~gr_rms_cf (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool unmuted () const { return d_unmuted; } + + void set_alpha (double alpha); +}; + +#endif /* INCLUDED_GR_RMS_CF_H */ diff --git a/gnuradio-core/src/lib/general/gr_rms_cf.i b/gnuradio-core/src/lib/general/gr_rms_cf.i new file mode 100644 index 00000000..0d7b05c8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,rms_cf); + +gr_rms_cf_sptr +gr_make_rms_cf (double alpha = 0.0001); + +class gr_rms_cf : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + void set_alpha (double alpha); +}; diff --git a/gnuradio-core/src/lib/general/gr_rms_ff.cc b/gnuradio-core/src/lib/general/gr_rms_ff.cc new file mode 100644 index 00000000..187be638 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +gr_rms_ff_sptr +gr_make_rms_ff(double alpha) +{ + return gr_rms_ff_sptr(new gr_rms_ff(alpha)); +} + +gr_rms_ff::gr_rms_ff (double alpha) + : gr_sync_block ("rms_ff", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_iir(alpha) +{ + +} + +gr_rms_ff::~gr_rms_ff() +{ +} + + +int +gr_rms_ff::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i]*in[i]; + double f = d_iir.filter(mag_sqrd); + out[i] = sqrt(f); + } + + return noutput_items; +} + +void +gr_rms_ff::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_rms_ff.h b/gnuradio-core/src/lib/general/gr_rms_ff.h new file mode 100644 index 00000000..3f276eb2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_RMS_FF_H +#define INCLUDED_GR_RMS_FF_H + +#include +#include + +class gr_rms_ff; +typedef boost::shared_ptr gr_rms_ff_sptr; + +gr_rms_ff_sptr +gr_make_rms_ff (double alpha = 0.0001); + +/*! + * \brief RMS average power + */ +class gr_rms_ff : public gr_sync_block +{ + gr_single_pole_iir d_iir; + bool d_unmuted; + + friend gr_rms_ff_sptr + gr_make_rms_ff (double alpha); + + gr_rms_ff (double alpha); + +public: + ~gr_rms_ff (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool unmuted () const { return d_unmuted; } + + void set_alpha (double alpha); +}; + +#endif /* INCLUDED_GR_RMS_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_rms_ff.i b/gnuradio-core/src/lib/general/gr_rms_ff.i new file mode 100644 index 00000000..bf9dbe2d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,rms_ff); + +gr_rms_ff_sptr +gr_make_rms_ff (double alpha = 0.0001); + +class gr_rms_ff : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + void set_alpha (double alpha); +}; diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.cc b/gnuradio-core/src/lib/general/gr_short_to_float.cc new file mode 100644 index 00000000..3ca79373 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_short_to_float_sptr +gr_make_short_to_float () +{ + return gr_short_to_float_sptr (new gr_short_to_float ()); +} + +gr_short_to_float::gr_short_to_float () + : gr_sync_block ("gr_short_to_float", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (1, 1, sizeof (float))) +{ +} + +int +gr_short_to_float::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const short *in = (const short *) input_items[0]; + float *out = (float *) output_items[0]; + + gri_short_to_float (in, out, noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.h b/gnuradio-core/src/lib/general/gr_short_to_float.h new file mode 100644 index 00000000..ee5a4ee1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SHORT_TO_FLOAT_H +#define INCLUDED_GR_SHORT_TO_FLOAT_H + +#include + +class gr_short_to_float; +typedef boost::shared_ptr gr_short_to_float_sptr; + +gr_short_to_float_sptr +gr_make_short_to_float (); + +/*! + * \brief Convert stream of short to a stream of float + * \ingroup converter + */ + +class gr_short_to_float : public gr_sync_block +{ + friend gr_short_to_float_sptr gr_make_short_to_float (); + gr_short_to_float (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_SHORT_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.i b/gnuradio-core/src/lib/general/gr_short_to_float.i new file mode 100644 index 00000000..724165d5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,short_to_float) + +gr_short_to_float_sptr gr_make_short_to_float (); + +class gr_short_to_float : public gr_sync_block +{ + gr_short_to_float (); +}; diff --git a/gnuradio-core/src/lib/general/gr_sig_source_X.cc.t b/gnuradio-core/src/lib/general/gr_sig_source_X.cc.t new file mode 100644 index 00000000..079864b2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sig_source_X.cc.t @@ -0,0 +1,149 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include <@NAME@.h> +#include +#include +#include +#include + + +@NAME@::@NAME@ (double sampling_freq, gr_waveform_t waveform, + double frequency, double ampl, @TYPE@ offset) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_sampling_freq (sampling_freq), d_waveform (waveform), d_frequency (frequency), + d_ampl (ampl), d_offset (offset) +{ + d_nco.set_freq (2 * M_PI * d_frequency / d_sampling_freq); +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double frequency, double ampl, @TYPE@ offset) +{ + return @NAME@_sptr (new @NAME@ (sampling_freq, waveform, frequency, ampl, offset)); +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *optr = (@TYPE@ *) output_items[0]; + @TYPE@ t; + + switch (d_waveform){ + +#if @IS_COMPLEX@ // complex? + + case GR_CONST_WAVE: + t = (gr_complex) d_ampl + d_offset; + for (int i = 0; i < noutput_items; i++) // FIXME unroll + optr[i] = t; + break; + + case GR_SIN_WAVE: + case GR_COS_WAVE: + d_nco.sincos (optr, noutput_items, d_ampl); + if (d_offset == gr_complex(0,0)) + break; + + for (int i = 0; i < noutput_items; i++){ + optr[i] += d_offset; + } + break; + +#else // nope... + + case GR_CONST_WAVE: + t = (@TYPE@) d_ampl + d_offset; + for (int i = 0; i < noutput_items; i++) // FIXME unroll + optr[i] = t; + break; + + case GR_SIN_WAVE: + d_nco.sin (optr, noutput_items, d_ampl); + if (d_offset == 0) + break; + + for (int i = 0; i < noutput_items; i++){ + optr[i] += d_offset; + } + break; + + case GR_COS_WAVE: + d_nco.cos (optr, noutput_items, d_ampl); + if (d_offset == 0) + break; + + for (int i = 0; i < noutput_items; i++){ + optr[i] += d_offset; + } + break; +#endif + + default: + throw std::runtime_error ("gr_sig_source: invalid waveform"); + } + + return noutput_items; +} + +void +@NAME@::set_sampling_freq (double sampling_freq) +{ + d_sampling_freq = sampling_freq; + d_nco.set_freq (2 * M_PI * d_frequency / d_sampling_freq); +} + +void +@NAME@::set_waveform (gr_waveform_t waveform) +{ + d_waveform = waveform; +} + +void +@NAME@::set_frequency (double frequency) +{ + d_frequency = frequency; + d_nco.set_freq (2 * M_PI * d_frequency / d_sampling_freq); +} + +void +@NAME@::set_amplitude (double ampl) +{ + d_ampl = ampl; +} + +void +@NAME@::set_offset (@TYPE@ offset) +{ + d_offset = offset; +} + diff --git a/gnuradio-core/src/lib/general/gr_sig_source_X.h.t b/gnuradio-core/src/lib/general/gr_sig_source_X.h.t new file mode 100644 index 00000000..2cdeb326 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sig_source_X.h.t @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +#include +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief signal generator with @TYPE@ output. + * \ingroup source + */ + +class @NAME@ : public gr_sync_block { + friend @NAME@_sptr + gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double frequency, double ampl, @TYPE@ offset); + + double d_sampling_freq; + gr_waveform_t d_waveform; + double d_frequency; + double d_ampl; + @TYPE@ d_offset; + gr_fxpt_nco d_nco; + + + @NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + double sampling_freq () const { return d_sampling_freq; } + gr_waveform_t waveform () const { return d_waveform; } + double frequency () const { return d_frequency; } + double amplitude () const { return d_ampl; } + @TYPE@ offset () const { return d_offset; } + + // MANIPULATORS + void set_sampling_freq (double sampling_freq); + void set_waveform (gr_waveform_t waveform); + void set_frequency (double frequency); + void set_amplitude (double ampl); + void set_offset (@TYPE@ offset); +}; + +@NAME@_sptr +gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset = 0); + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_sig_source_X.i.t b/gnuradio-core/src/lib/general/gr_sig_source_X.i.t new file mode 100644 index 00000000..3e769d42 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sig_source_X.i.t @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset = 0); + + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset); + + public: + + // ACCESSORS + double sampling_freq () const { return d_sampling_freq; } + gr_waveform_t waveform () const { return d_waveform; } + double frequency () const { return d_frequency; } + double amplitude () const { return d_ampl; } + @TYPE@ offset () const { return d_offset; } + + // MANIPULATORS + void set_sampling_freq (double sampling_freq); + void set_waveform (gr_waveform_t waveform); + void set_frequency (double frequency); + void set_amplitude (double ampl); + void set_offset (@TYPE@ offset); +}; diff --git a/gnuradio-core/src/lib/general/gr_sig_source_waveform.h b/gnuradio-core/src/lib/general/gr_sig_source_waveform.h new file mode 100644 index 00000000..2d0dc567 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sig_source_waveform.h @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_SIG_SOURCE_WAVEFORM_H +#define INCLUDED_GR_SIG_SOURCE_WAVEFORM_H + +typedef enum { + GR_CONST_WAVE = 100, GR_SIN_WAVE, GR_COS_WAVE +} gr_waveform_t; + +#endif /* INCLUDED_GR_SIG_SOURCE_WAVEFORM_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.cc b/gnuradio-core/src/lib/general/gr_simple_correlator.cc new file mode 100644 index 00000000..09c81239 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.cc @@ -0,0 +1,230 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + + +static const int THRESHOLD = 3; + +gr_simple_correlator_sptr +gr_make_simple_correlator (int payload_bytesize) +{ + return gr_simple_correlator_sptr (new gr_simple_correlator (payload_bytesize)); +} + +gr_simple_correlator::gr_simple_correlator (int payload_bytesize) + : gr_block ("simple_correlator", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_payload_bytesize (payload_bytesize), + d_state (ST_LOOKING), d_osi (0), + d_bblen ((payload_bytesize + GRSF_PAYLOAD_OVERHEAD) * GRSF_BITS_PER_BYTE), + d_bitbuf (new unsigned char [d_bblen]), + d_bbi (0) +{ + d_avbi = 0; + d_accum = 0.0; + d_avg = 0.0; + for (int i = 0; i < AVG_PERIOD; i++) + d_avgbuf[i] = 0.0; + +#ifdef DEBUG_SIMPLE_CORRELATOR + d_debug_fp = fopen("corr.log", "w"); +#endif + enter_looking (); + +} + +gr_simple_correlator::~gr_simple_correlator () +{ +#ifdef DEBUG_SIMPLE_CORRELATOR + fclose(d_debug_fp); +#endif + delete [] d_bitbuf; +} + + +void +gr_simple_correlator::enter_looking () +{ + fflush (stdout); + // fprintf (stderr, ">>> enter_looking\n"); + d_state = ST_LOOKING; + for (int i = 0; i < OVERSAMPLE; i++) + d_shift_reg[i] = 0; + d_osi = 0; + + d_avbi = 0; + d_avg = d_avg * 0.5; + d_accum = 0; + for (int i = 0; i < AVG_PERIOD; i++) + d_avgbuf[i] = 0.0; +} + +void +gr_simple_correlator::enter_under_threshold () +{ + fflush (stdout); + // fprintf (stderr, ">>> enter_under_threshold\n"); + d_state = ST_UNDER_THRESHOLD; + d_transition_osi = d_osi; +} + +void +gr_simple_correlator::enter_locked () +{ + d_state = ST_LOCKED; + int delta = sub_index (d_osi, d_transition_osi); + d_center_osi = add_index (d_transition_osi, delta/2); + d_center_osi = add_index (d_center_osi, 3); // FIXME + d_bbi = 0; + fflush (stdout); + // fprintf (stderr, ">>> enter_locked d_center_osi = %d\n", d_center_osi); + + d_avg = std::max(-1.0, std::min(1.0, d_accum * (1.0/AVG_PERIOD))); + // fprintf(stderr, ">>> enter_locked d_avg = %g\n", d_avg); +} + +static void +packit (unsigned char *pktbuf, const unsigned char *bitbuf, int bitcount) +{ + for (int i = 0; i < bitcount; i += 8){ + int t = bitbuf[i+0] & 0x1; + t = (t << 1) | (bitbuf[i+1] & 0x1); + t = (t << 1) | (bitbuf[i+2] & 0x1); + t = (t << 1) | (bitbuf[i+3] & 0x1); + t = (t << 1) | (bitbuf[i+4] & 0x1); + t = (t << 1) | (bitbuf[i+5] & 0x1); + t = (t << 1) | (bitbuf[i+6] & 0x1); + t = (t << 1) | (bitbuf[i+7] & 0x1); + *pktbuf++ = t; + } +} + +void +gr_simple_correlator::update_avg(float x) +{ + d_accum -= d_avgbuf[d_avbi]; + d_avgbuf[d_avbi] = x; + d_accum += x; + d_avbi = (d_avbi + 1) & (AVG_PERIOD-1); +} + + +int +gr_simple_correlator::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + + int n = 0; + int nin = ninput_items[0]; + int decision; + int hamming_dist; + + struct debug_data { + float raw_data; + float sampled; + float enter_locked; + } debug_data; + + while (n < nin){ + +#ifdef DEBUG_SIMPLE_CORRELATOR + debug_data.raw_data = in[n]; + debug_data.sampled = 0.0; + debug_data.enter_locked = 0.0; +#endif + + switch (d_state){ + + case ST_LOCKED: + if (d_osi == d_center_osi){ + +#ifdef DEBUG_SIMPLE_CORRELATOR + debug_data.sampled = 1.0; +#endif + decision = slice (in[n]); + + d_bitbuf[d_bbi] = decision; + d_bbi++; + if (d_bbi >= d_bblen){ + // printf ("got whole packet\n"); + unsigned char pktbuf[d_bblen/GRSF_BITS_PER_BYTE]; + packit (pktbuf, d_bitbuf, d_bbi); + printf ("seqno %3d\n", pktbuf[0]); + memcpy (out, &pktbuf[GRSF_PAYLOAD_OVERHEAD], d_payload_bytesize); + enter_looking (); + consume_each (n + 1); + return d_payload_bytesize; + } + } + break; + + case ST_LOOKING: + case ST_UNDER_THRESHOLD: + update_avg(in[n]); + decision = slice (in[n]); + d_shift_reg[d_osi] = (d_shift_reg[d_osi] << 1) | decision; + + hamming_dist = gr_count_bits64 (d_shift_reg[d_osi] ^ GRSF_SYNC); + // printf ("%2d %d\n", hamming_dist, d_osi); + + if (d_state == ST_LOOKING && hamming_dist <= THRESHOLD){ + // We're seeing a good PN code, remember location + enter_under_threshold (); + } + else if (d_state == ST_UNDER_THRESHOLD && hamming_dist > THRESHOLD){ + // no longer seeing good PN code, compute center of goodness + enter_locked (); + debug_data.enter_locked = 1.0; + } + break; + + default: + assert (0); + } + +#ifdef DEBUG_SIMPLE_CORRELATOR + fwrite(&debug_data, sizeof (debug_data), 1, d_debug_fp); +#endif + + d_osi = add_index (d_osi, 1); + n++; + } + + consume_each (n); + return 0; +} diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.h b/gnuradio-core/src/lib/general/gr_simple_correlator.h new file mode 100644 index 00000000..5697e170 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.h @@ -0,0 +1,109 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SIMPLE_CORRELATOR_H +#define INCLUDED_GR_SIMPLE_CORRELATOR_H + +#include +#include + +//#define DEBUG_SIMPLE_CORRELATOR + +class gr_simple_correlator; +typedef boost::shared_ptr gr_simple_correlator_sptr; + +gr_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + +/*! + * \brief inverse of gr_simple_framer (more or less) + * \ingroup block + */ +class gr_simple_correlator : public gr_block +{ + static const int OVERSAMPLE = 8; + enum state_t { ST_LOOKING, ST_UNDER_THRESHOLD, ST_LOCKED }; + + int d_payload_bytesize; + state_t d_state; + unsigned int d_osi; // over sample index [0,OVERSAMPLE-1] + unsigned int d_transition_osi; // first index where Hamming dist < thresh + unsigned int d_center_osi; // center of bit + unsigned long long int d_shift_reg[OVERSAMPLE]; + int d_bblen; // length of bitbuf + unsigned char *d_bitbuf; // demodulated bits + int d_bbi; // bitbuf index + + static const int AVG_PERIOD = 512; // must be power of 2 (for freq offset correction) + int d_avbi; + float d_avgbuf[AVG_PERIOD]; + float d_avg; + float d_accum; + +#ifdef DEBUG_SIMPLE_CORRELATOR + FILE *d_debug_fp; // binary log file +#endif + + friend gr_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + gr_simple_correlator (int payload_bytesize); + + + inline int slice (float x) + { + return x >= d_avg ? 1 : 0; + } + + void update_avg(float x); + + void enter_locked (); + void enter_under_threshold (); + void enter_looking (); + + static int add_index (int a, int b) + { + int t = a + b; + if (t >= OVERSAMPLE) + t -= OVERSAMPLE; + assert (t >= 0 && t < OVERSAMPLE); + return t; + } + + static int sub_index (int a, int b) + { + int t = a - b; + if (t < 0) + t += OVERSAMPLE; + assert (t >= 0 && t < OVERSAMPLE); + return t; + } + + + public: + ~gr_simple_correlator (); + + 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_CORRELATOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.i b/gnuradio-core/src/lib/general/gr_simple_correlator.i new file mode 100644 index 00000000..d143648f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,simple_correlator); + +gr_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + +class gr_simple_correlator : public gr_block +{ + private: + gr_simple_correlator (int payload_bytesize); +}; diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.cc b/gnuradio-core/src/lib/general/gr_simple_framer.cc new file mode 100644 index 00000000..797b1f3b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.cc @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + + +gr_simple_framer_sptr +gr_make_simple_framer (int payload_bytesize) +{ + return gr_simple_framer_sptr (new gr_simple_framer (payload_bytesize)); +} + +gr_simple_framer::gr_simple_framer (int payload_bytesize) + : gr_block ("simple_framer", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_seqno (0), d_payload_bytesize (payload_bytesize), + d_input_block_size (payload_bytesize), + d_output_block_size (payload_bytesize + GRSF_OVERHEAD) +{ + set_output_multiple (d_output_block_size); +} + +void +gr_simple_framer::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + assert (noutput_items % d_output_block_size == 0); + + int nblocks = noutput_items / d_output_block_size; + int input_required = nblocks * d_input_block_size; + + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = input_required; +} + +int +gr_simple_framer::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + int n = 0; + int nblocks = 0; + + memset (out, 0x55, noutput_items); + + while (n < noutput_items){ + out[0] = (GRSF_SYNC >> 56) & 0xff; + out[1] = (GRSF_SYNC >> 48) & 0xff; + out[2] = (GRSF_SYNC >> 40) & 0xff; + out[3] = (GRSF_SYNC >> 32) & 0xff; + out[4] = (GRSF_SYNC >> 24) & 0xff; + out[5] = (GRSF_SYNC >> 16) & 0xff; + out[6] = (GRSF_SYNC >> 8) & 0xff; + out[7] = (GRSF_SYNC >> 0) & 0xff; + out[8] = d_seqno++; + + memcpy (&out[9], in, d_input_block_size); + in += d_input_block_size; + out += d_output_block_size; + n += d_output_block_size; + nblocks++; + } + + assert (n == noutput_items); + + consume_each (nblocks * d_input_block_size); + return n; +} diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.h b/gnuradio-core/src/lib/general/gr_simple_framer.h new file mode 100644 index 00000000..33813741 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SIMPLE_FRAMER_H +#define INCLUDED_GR_SIMPLE_FRAMER_H + +#include + +class gr_simple_framer; +typedef boost::shared_ptr gr_simple_framer_sptr; + +gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); + +/*! + * \brief add sync field, seq number and command field to payload + * \ingroup block + */ +class gr_simple_framer : public gr_block +{ + int d_seqno; + int d_payload_bytesize; + int d_input_block_size; // bytes + int d_output_block_size; // bytes + + friend gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); + gr_simple_framer (int payload_bytesize); + + public: + void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_SIMPLE_FRAMER_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.i b/gnuradio-core/src/lib/general/gr_simple_framer.i new file mode 100644 index 00000000..4083ce16 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,simple_framer); + +gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); + +class gr_simple_framer : public gr_block +{ + private: + gr_simple_framer (int payload_bytesize); +}; diff --git a/gnuradio-core/src/lib/general/gr_simple_framer_sync.h b/gnuradio-core/src/lib/general/gr_simple_framer_sync.h new file mode 100644 index 00000000..c7f65528 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer_sync.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SIMPLE_FRAMER_SYNC_H +#define INCLUDED_GR_SIMPLE_FRAMER_SYNC_H + +/* + * Here are a couple of maximum length sequences (m-sequences) that were generated by the + * the "mseq" matlab/octave code downloaded from: + * http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=990&objectType=file + * + * 31-bit m-sequence: + * 0110100100001010111011000111110 + * 0x690AEC76 (padded on right with a zero) + * + * 63-bit m-sequence: + * 101011001101110110100100111000101111001010001100001000001111110 + * 0xACDDA4E2F28C20FC (padded on right with a zero) + */ + +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/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc new file mode 100644 index 00000000..e34f9a13 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +gr_simple_squelch_cc_sptr +gr_make_simple_squelch_cc(double threshold_db, double alpha) +{ + return gr_simple_squelch_cc_sptr(new gr_simple_squelch_cc(threshold_db, alpha)); +} + +gr_simple_squelch_cc::gr_simple_squelch_cc (double threshold_db, double alpha) + : gr_sync_block ("simple_squelch_cc", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))), + d_iir(alpha), d_unmuted(false) +{ + set_threshold (threshold_db); +} + +gr_simple_squelch_cc::~gr_simple_squelch_cc() +{ +} + + +int +gr_simple_squelch_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]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + double f = d_iir.filter(mag_sqrd); + if (f >= d_threshold) + out[i] = in[i]; + else + out[i] = 0; + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + return noutput_items; +} + +void +gr_simple_squelch_cc::set_threshold(double decibels) +{ + // convert to absolute threshold (mag squared) + d_threshold = std::pow(10.0, decibels/10); +} + +double +gr_simple_squelch_cc::threshold() const +{ + return 10 * log10(d_threshold); +} + +void +gr_simple_squelch_cc::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} + +std::vector +gr_simple_squelch_cc::squelch_range() const +{ + std::vector r(3); + r[0] = -50.0; // min FIXME + r[1] = +50.0; // max FIXME + r[2] = (r[1] - r[0]) / 100; // step size + + return r; +} diff --git a/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h new file mode 100644 index 00000000..31fde128 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_SIMPLE_SQUELCH_CC_H +#define INCLUDED_GR_SIMPLE_SQUELCH_CC_H + +#include +#include + +class gr_simple_squelch_cc; +typedef boost::shared_ptr gr_simple_squelch_cc_sptr; + +gr_simple_squelch_cc_sptr +gr_make_simple_squelch_cc (double threshold_db, double alpha = 0.0001); + +/*! + * \brief simple squelch block based on average signal power and threshold in dB. + */ +class gr_simple_squelch_cc : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir d_iir; + bool d_unmuted; + + friend gr_simple_squelch_cc_sptr + gr_make_simple_squelch_cc (double threshold_db, double alpha); + + gr_simple_squelch_cc (double threshold_db, double alpha); + +public: + ~gr_simple_squelch_cc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool unmuted () const { return d_unmuted; } + + void set_alpha (double alpha); + void set_threshold (double decibels); + + double threshold() const; + std::vector squelch_range() const; + +}; + +#endif /* INCLUDED_GR_SIMPLE_SQUELCH_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_squelch_cc.i b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.i new file mode 100644 index 00000000..5e3339a2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.i @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,simple_squelch_cc); + +gr_simple_squelch_cc_sptr +gr_make_simple_squelch_cc (double threshold_db, double alpha = 0.0001); + +class gr_simple_squelch_cc : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + void set_alpha (double alpha); + void set_threshold (double decibels); + + double threshold() const; + std::vector squelch_range() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_skiphead.cc b/gnuradio-core/src/lib/general/gr_skiphead.cc new file mode 100644 index 00000000..599d00bf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +gr_skiphead::gr_skiphead (size_t sizeof_stream_item, int nitems) + : gr_sync_block ("skiphead", + gr_make_io_signature (1, 1, sizeof_stream_item), + gr_make_io_signature (1, 1, sizeof_stream_item)), + d_nitems (nitems), d_nskipped_items (0) +{ +} + +gr_block_sptr +gr_make_skiphead (size_t sizeof_stream_item, int nitems) +{ + return gr_block_sptr (new gr_skiphead (sizeof_stream_item, nitems)); +} + +int +gr_skiphead::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int items_to_skip = d_nitems - d_nskipped_items; + if (items_to_skip <=0) + { + //Done with skipping, copy all input to the output; + memcpy (output_items[0], input_items[0], noutput_items * input_signature()->sizeof_stream_item (0)); + return noutput_items; + } else if (items_to_skip < noutput_items) + { + memcpy (output_items[0], &(((char *)input_items[0])[items_to_skip*input_signature()->sizeof_stream_item (0)]), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); + //memcpy (output_items[0], &((input_items[0])[items_to_skip]), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); + //memcpy (output_items[0], input_items[0]+items_to_skip*input_signature()->sizeof_stream_item (0), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); + d_nskipped_items += items_to_skip; + consume_each (items_to_skip); + return (noutput_items -items_to_skip); + } else + { + d_nskipped_items += noutput_items; + consume_each (items_to_skip); + return 0; + } + + return -1;//Should never get here +} diff --git a/gnuradio-core/src/lib/general/gr_skiphead.h b/gnuradio-core/src/lib/general/gr_skiphead.h new file mode 100644 index 00000000..e87f8a4e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SKIPHEAD_H +#define INCLUDED_GR_SKIPHEAD_H + +#include +#include // size_t + +/*! + * \brief skips the first N items, from then on copies items to the output + * \ingroup block + * + * Useful for building test cases and sources which have metadata or junk at the start + */ + +class gr_skiphead : public gr_sync_block +{ + friend gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); + gr_skiphead (size_t sizeof_stream_item, int nitems); + + int d_nitems; + int d_nskipped_items; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +gr_block_sptr +gr_make_skiphead (size_t sizeof_stream_item, int nitems); + + +#endif /* INCLUDED_GR_SKIPHEAD_H */ diff --git a/gnuradio-core/src/lib/general/gr_skiphead.i b/gnuradio-core/src/lib/general/gr_skiphead.i new file mode 100644 index 00000000..deedeb3b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_skiphead; +class gr_skiphead : public gr_block { + friend gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); + gr_skiphead (size_t sizeof_stream_item, int nitems); +}; + +%rename(skiphead) gr_make_skiphead; +gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_cc.cc b/gnuradio-core/src/lib/general/gr_squelch_base_cc.cc new file mode 100644 index 00000000..b3e61fcc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_squelch_base_cc::gr_squelch_base_cc(const char *name, int ramp, bool gate) : + gr_block(name, + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))) +{ + set_ramp(ramp); + set_gate(gate); + d_state = ST_MUTED; + d_envelope = d_ramp ? 0.0 : 1.0; + d_ramped = 0; +} + +int gr_squelch_base_cc::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int j = 0; + + for (int i = 0; i < noutput_items; i++) { + update_state(in[i]); + + // Adjust envelope based on current state + switch(d_state) { + case ST_MUTED: + if (!mute()) + d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; // If not ramping, go straight to unmuted + break; + + case ST_UNMUTED: + if (mute()) + d_state = d_ramp ? ST_DECAY : ST_MUTED; // If not ramping, go straight to muted + break; + + case ST_ATTACK: + d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped >= d_ramp) { // use >= in case d_ramp is set to lower value elsewhere + d_state = ST_UNMUTED; + d_envelope = 1.0; + } + break; + + case ST_DECAY: + d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped == 0.0) + d_state = ST_MUTED; + break; + }; + + // If unmuted, copy input times envelope to output + // Otherwise, if not gating, copy zero to output + if (d_state != ST_MUTED) + out[j++] = in[i]*gr_complex(d_envelope, 0.0); + else + if (!d_gate) + out[j++] = 0.0; + } + + consume_each(noutput_items); // Use all the inputs + return j; // But only report outputs copied +} diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_cc.h b/gnuradio-core/src/lib/general/gr_squelch_base_cc.h new file mode 100644 index 00000000..4e331284 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SQUELCH_BASE_CC_H +#define INCLUDED_GR_SQUELCH_BASE_CC_H + +#include + +class gr_squelch_base_cc : public gr_block +{ +private: + int d_ramp; + int d_ramped; + bool d_gate; + double d_envelope; + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +protected: + virtual void update_state(const gr_complex &sample) {}; + virtual bool mute() const { return false; }; + +public: + gr_squelch_base_cc(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector squelch_range() const = 0; + + 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_SQUELCH_BASE_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_cc.i b/gnuradio-core/src/lib/general/gr_squelch_base_cc.i new file mode 100644 index 00000000..0ef674c4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +class gr_squelch_base_cc : public gr_block +{ +private: + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +public: + gr_squelch_base_cc(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector squelch_range() const = 0; +}; diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_ff.cc b/gnuradio-core/src/lib/general/gr_squelch_base_ff.cc new file mode 100644 index 00000000..a457c5f6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_squelch_base_ff::gr_squelch_base_ff(const char *name, int ramp, bool gate) : + gr_block(name, + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))) +{ + set_ramp(ramp); + set_gate(gate); + d_state = ST_MUTED; + d_envelope = d_ramp ? 0.0 : 1.0; + d_ramped = 0; +} + +int gr_squelch_base_ff::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + int j = 0; + + for (int i = 0; i < noutput_items; i++) { + update_state(in[i]); + + // Adjust envelope based on current state + switch(d_state) { + case ST_MUTED: + if (!mute()) + d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; // If not ramping, go straight to unmuted + break; + + case ST_UNMUTED: + if (mute()) + d_state = d_ramp ? ST_DECAY : ST_MUTED; // If not ramping, go straight to muted + break; + + case ST_ATTACK: + d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped >= d_ramp) { // use >= in case d_ramp is set to lower value elsewhere + d_state = ST_UNMUTED; + d_envelope = 1.0; + } + break; + + case ST_DECAY: + d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped == 0.0) + d_state = ST_MUTED; + break; + }; + + // If unmuted, copy input times envelope to output + // Otherwise, if not gating, copy zero to output + if (d_state != ST_MUTED) + out[j++] = in[i]*d_envelope; + else + if (!d_gate) + out[j++] = 0.0; + } + + consume_each(noutput_items); // Use all the inputs + return j; // But only report outputs copied +} diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_ff.h b/gnuradio-core/src/lib/general/gr_squelch_base_ff.h new file mode 100644 index 00000000..4128735a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SQUELCH_BASE_FF_H +#define INCLUDED_GR_SQUELCH_BASE_FF_H + +#include + +class gr_squelch_base_ff : public gr_block +{ +private: + int d_ramp; + int d_ramped; + bool d_gate; + double d_envelope; + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +protected: + virtual void update_state(const float &sample) {}; + virtual bool mute() const { return false; }; + +public: + gr_squelch_base_ff(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector squelch_range() const = 0; + + 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_SQUELCH_BASE_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_ff.i b/gnuradio-core/src/lib/general/gr_squelch_base_ff.i new file mode 100644 index 00000000..d749d498 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +class gr_squelch_base_ff : public gr_block +{ +private: + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +public: + gr_squelch_base_ff(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector squelch_range() const = 0; +}; diff --git a/gnuradio-core/src/lib/general/gr_stream_to_streams.cc b/gnuradio-core/src/lib/general/gr_stream_to_streams.cc new file mode 100644 index 00000000..d4627964 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t item_size, size_t nstreams) +{ + return gr_stream_to_streams_sptr (new gr_stream_to_streams (item_size, nstreams)); +} + +gr_stream_to_streams::gr_stream_to_streams (size_t item_size, size_t nstreams) + : gr_sync_decimator ("stream_to_streams", + gr_make_io_signature (1, 1, item_size), + gr_make_io_signature (nstreams, + nstreams, item_size), + nstreams) +{ +} + +int +gr_stream_to_streams::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = output_signature()->sizeof_stream_item (0); + + const char *in = (const char *) input_items[0]; + char **outv = (char **) &output_items[0]; + int nstreams = output_items.size(); + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(outv[j], in, item_size); + outv[j] += item_size; + in += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_stream_to_streams.h b/gnuradio-core/src/lib/general/gr_stream_to_streams.h new file mode 100644 index 00000000..3775e79b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_STREAM_TO_STREAMS_H +#define INCLUDED_GR_STREAM_TO_STREAMS_H + +#include + +class gr_stream_to_streams; +typedef boost::shared_ptr gr_stream_to_streams_sptr; + +gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t item_size, size_t nstreams); + + +/*! + * \brief convert a stream of items into a N streams of items + * \ingroup block + * + * Converts a stream of N items into N streams of 1 item. + * Repeat ad infinitum. + */ +class gr_stream_to_streams : public gr_sync_decimator +{ + friend gr_stream_to_streams_sptr + gr_make_stream_to_streams (size_t item_size, size_t nstreams); + + protected: + gr_stream_to_streams (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAM_TO_STREAMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_stream_to_streams.i b/gnuradio-core/src/lib/general/gr_stream_to_streams.i new file mode 100644 index 00000000..59b93da0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,stream_to_streams) + +gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t itemsize, size_t nstreams); + +class gr_stream_to_streams : public gr_sync_decimator +{ + protected: + gr_stream_to_streams (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_stream_to_vector.cc b/gnuradio-core/src/lib/general/gr_stream_to_vector.cc new file mode 100644 index 00000000..3d815cf5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block) +{ + return gr_stream_to_vector_sptr (new gr_stream_to_vector (item_size, nitems_per_block)); +} + +gr_stream_to_vector::gr_stream_to_vector (size_t item_size, size_t nitems_per_block) + : gr_sync_decimator ("stream_to_vector", + gr_make_io_signature (1, 1, item_size), + gr_make_io_signature (1, 1, item_size * nitems_per_block), + nitems_per_block) +{ +} + +int +gr_stream_to_vector::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t block_size = output_signature()->sizeof_stream_item (0); + + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + memcpy (out, in, noutput_items * block_size); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_stream_to_vector.h b/gnuradio-core/src/lib/general/gr_stream_to_vector.h new file mode 100644 index 00000000..a0a318b6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_STREAM_TO_VECTOR_H +#define INCLUDED_GR_STREAM_TO_VECTOR_H + +#include + +class gr_stream_to_vector; +typedef boost::shared_ptr gr_stream_to_vector_sptr; + +gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block); + + +/*! + * \brief convert a stream of items into a stream of blocks containing nitems_per_block + * \ingroup block + */ +class gr_stream_to_vector : public gr_sync_decimator +{ + friend gr_stream_to_vector_sptr + gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block); + + protected: + gr_stream_to_vector (size_t item_size, size_t nitems_per_block); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_STREAM_TO_VECTOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_stream_to_vector.i b/gnuradio-core/src/lib/general/gr_stream_to_vector.i new file mode 100644 index 00000000..16550ac0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,stream_to_vector) + +gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t itemsize, size_t nitems_per_block); + +class gr_stream_to_vector : public gr_sync_decimator +{ + protected: + gr_stream_to_vector (size_t itemsize, size_t nitems_per_block); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_streams_to_stream.cc b/gnuradio-core/src/lib/general/gr_streams_to_stream.cc new file mode 100644 index 00000000..9d05fbf7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t item_size, size_t nstreams) +{ + return gr_streams_to_stream_sptr (new gr_streams_to_stream (item_size, nstreams)); +} + +gr_streams_to_stream::gr_streams_to_stream (size_t item_size, size_t nstreams) + : gr_sync_interpolator ("streams_to_stream", + gr_make_io_signature (nstreams, nstreams, item_size), + gr_make_io_signature (1, 1, item_size), + nstreams) +{ +} + +int +gr_streams_to_stream::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = output_signature()->sizeof_stream_item (0); + + const char **inv = (const char **) &input_items[0]; + char *out = (char *) output_items[0]; + int nstreams = input_items.size(); + + assert (noutput_items % nstreams == 0); + int ni = noutput_items / nstreams; + + for (int i = 0; i < ni; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(out, inv[j], item_size); + out += item_size; + inv[j] += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_streams_to_stream.h b/gnuradio-core/src/lib/general/gr_streams_to_stream.h new file mode 100644 index 00000000..86d39094 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_STREAMS_TO_STREAM_H +#define INCLUDED_GR_STREAMS_TO_STREAM_H + +#include + +class gr_streams_to_stream; +typedef boost::shared_ptr gr_streams_to_stream_sptr; + +gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t item_size, size_t nstreams); + + +/*! + * \brief Convert N streams of 1 item into a 1 stream of N items + * \ingroup block + * + * Convert N streams of 1 item into 1 stream of N items. + * Repeat ad infinitum. + */ +class gr_streams_to_stream : public gr_sync_interpolator +{ + friend gr_streams_to_stream_sptr + gr_make_streams_to_stream (size_t item_size, size_t nstreams); + + protected: + gr_streams_to_stream (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAMS_TO_STREAM_H */ diff --git a/gnuradio-core/src/lib/general/gr_streams_to_stream.i b/gnuradio-core/src/lib/general/gr_streams_to_stream.i new file mode 100644 index 00000000..0f9e46fc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,streams_to_stream) + +gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t itemsize, size_t nstreams); + +class gr_streams_to_stream : public gr_sync_interpolator +{ + protected: + gr_streams_to_stream (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_streams_to_vector.cc b/gnuradio-core/src/lib/general/gr_streams_to_vector.cc new file mode 100644 index 00000000..794254dd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.cc @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t item_size, size_t nstreams) +{ + return gr_streams_to_vector_sptr (new gr_streams_to_vector (item_size, nstreams)); +} + +gr_streams_to_vector::gr_streams_to_vector (size_t item_size, size_t nstreams) + : gr_sync_block ("streams_to_vector", + gr_make_io_signature (nstreams, nstreams, item_size), + gr_make_io_signature (1, 1, nstreams * item_size)) +{ +} + +int +gr_streams_to_vector::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = input_signature()->sizeof_stream_item(0); + int nstreams = input_items.size(); + + const char **inv = (const char **) &input_items[0]; + char *out = (char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(out, inv[j], item_size); + inv[j] += item_size; + out += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_streams_to_vector.h b/gnuradio-core/src/lib/general/gr_streams_to_vector.h new file mode 100644 index 00000000..d3a89035 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_STREAMS_TO_VECTOR_H +#define INCLUDED_GR_STREAMS_TO_VECTOR_H + +#include + +class gr_streams_to_vector; +typedef boost::shared_ptr gr_streams_to_vector_sptr; + +gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t item_size, size_t nstreams); + + +/*! + * \brief convert N streams of items to 1 stream of vector length N + * \ingroup block + */ +class gr_streams_to_vector : public gr_sync_block +{ + friend gr_streams_to_vector_sptr + gr_make_streams_to_vector (size_t item_size, size_t nstreams); + + protected: + gr_streams_to_vector (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAMS_TO_VECTOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_streams_to_vector.i b/gnuradio-core/src/lib/general/gr_streams_to_vector.i new file mode 100644 index 00000000..a69c2e5a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,streams_to_vector) + +gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t itemsize, size_t nstreams); + +class gr_streams_to_vector : public gr_sync_block +{ + protected: + gr_streams_to_vector (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_sub_XX.cc.t b/gnuradio-core/src/lib/general/gr_sub_XX.cc.t new file mode 100644 index 00000000..2cfdc6e9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sub_XX.cc.t @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return @SPTR_NAME@ (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + if (ninputs == 1){ // negate + for (int i = 0; i < noutput_items; i++) + *optr++ = (@O_TYPE@) -((@I_TYPE@ *) input_items[0])[i]; + } + + else { + for (int i = 0; i < noutput_items; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc -= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_sub_XX.h.t b/gnuradio-core/src/lib/general/gr_sub_XX.h.t new file mode 100644 index 00000000..025c077a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sub_XX.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 - input_1 - ...) + * \ingroup block + * + * Subtract across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_sub_XX.i.t b/gnuradio-core/src/lib/general/gr_sub_XX.i.t new file mode 100644 index 00000000..8479aad6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sub_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/general/gr_sync_block.cc b/gnuradio-core/src/lib/general/gr_sync_block.cc new file mode 100644 index 00000000..57b6c556 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_block.cc @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_sync_block::gr_sync_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : gr_block(name, input_signature, output_signature) +{ + set_fixed_rate(true); +} + + +void +gr_sync_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items); +} + +int +gr_sync_block::fixed_rate_noutput_to_ninput(int noutput_items) +{ + return noutput_items + history() - 1; +} + +int +gr_sync_block::fixed_rate_ninput_to_noutput(int ninput_items) +{ + return std::max(0, ninput_items - (int)history() + 1); +} + +int +gr_sync_block::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r); + return r; +} diff --git a/gnuradio-core/src/lib/general/gr_sync_block.h b/gnuradio-core/src/lib/general/gr_sync_block.h new file mode 100644 index 00000000..b4a2d008 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_block.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SYNC_BLOCK_H +#define INCLUDED_GR_SYNC_BLOCK_H + +#include + +/*! + * \brief synchronous 1:1 input to output with history + * \ingroup block + * + * Override work to provide the signal processing implementation. + */ +class gr_sync_block : public gr_block +{ + protected: + + gr_sync_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + public: + + /*! + * \brief just like gr_block::general_work, only this arranges to call consume_each for you + * + * The user must override work to define the signal processing code + */ + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) = 0; + + + // gr_sync_block overrides these to assist work + 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); + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); +}; + +#endif /* INCLUDED_GR_SYNC_BLOCK_H */ diff --git a/gnuradio-core/src/lib/general/gr_sync_block.i b/gnuradio-core/src/lib/general/gr_sync_block.i new file mode 100644 index 00000000..c078a8b8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_block.i @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +class gr_sync_block : public gr_block +{ + protected: + + gr_sync_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); +}; diff --git a/gnuradio-core/src/lib/general/gr_sync_decimator.cc b/gnuradio-core/src/lib/general/gr_sync_decimator.cc new file mode 100644 index 00000000..4b168a5d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_decimator.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_sync_decimator::gr_sync_decimator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned decimation) + : gr_sync_block (name, input_signature, output_signature) +{ + set_decimation (decimation); +} + +void +gr_sync_decimator::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); +} + +int +gr_sync_decimator::fixed_rate_noutput_to_ninput(int noutput_items) +{ + return noutput_items * decimation() + history() - 1; +} + +int +gr_sync_decimator::fixed_rate_ninput_to_noutput(int ninput_items) +{ + return std::max(0, ninput_items - (int)history() + 1) / decimation(); +} + +int +gr_sync_decimator::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r * decimation ()); + return r; +} + diff --git a/gnuradio-core/src/lib/general/gr_sync_decimator.h b/gnuradio-core/src/lib/general/gr_sync_decimator.h new file mode 100644 index 00000000..6cdd35a4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_decimator.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SYNC_DECIMATOR_H +#define INCLUDED_GR_SYNC_DECIMATOR_H + +#include + +/*! + * \brief synchronous N:1 input to output with history + * \ingroup block + * + * Override work to provide the signal processing implementation. + */ +class gr_sync_decimator : public gr_sync_block +{ + private: + unsigned d_decimation; + + protected: + + gr_sync_decimator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned decimation); + public: + + unsigned decimation () const { return d_decimation; } + void set_decimation (unsigned decimation) + { + d_decimation = decimation; + set_relative_rate (1.0 / decimation); + } + + // gr_sync_decimator overrides these to assist work + 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); + + // derived classes should override work + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); +}; + + +#endif /* INCLUDED_GR_SYNC_DECIMATOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_sync_decimator.i b/gnuradio-core/src/lib/general/gr_sync_decimator.i new file mode 100644 index 00000000..d9f6483a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_decimator.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_sync_decimator : public gr_sync_block +{ + protected: + + gr_sync_decimator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned decimation); +}; diff --git a/gnuradio-core/src/lib/general/gr_sync_interpolator.cc b/gnuradio-core/src/lib/general/gr_sync_interpolator.cc new file mode 100644 index 00000000..024d7e78 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_interpolator.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_sync_interpolator::gr_sync_interpolator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned interpolation) + : gr_sync_block (name, input_signature, output_signature) +{ + set_interpolation (interpolation); +} + +void +gr_sync_interpolator::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); +} + +int +gr_sync_interpolator::fixed_rate_noutput_to_ninput(int noutput_items) +{ + return noutput_items / interpolation() + history() - 1; +} + +int +gr_sync_interpolator::fixed_rate_ninput_to_noutout(int ninput_items) +{ + return std::max(0, ninput_items - (int)history() + 1) * interpolation(); +} + +int +gr_sync_interpolator::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r / interpolation ()); + return r; +} + + diff --git a/gnuradio-core/src/lib/general/gr_sync_interpolator.h b/gnuradio-core/src/lib/general/gr_sync_interpolator.h new file mode 100644 index 00000000..914ea8e5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_interpolator.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SYNC_INTERPOLATOR_H +#define INCLUDED_GR_SYNC_INTERPOLATOR_H + +#include + +/*! + * \brief synchronous 1:N input to output with history + * \ingroup block + * + * Override work to provide the signal processing implementation. + */ +class gr_sync_interpolator : public gr_sync_block +{ + private: + unsigned d_interpolation; + + protected: + gr_sync_interpolator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned interpolation); + public: + + unsigned interpolation () const { return d_interpolation; } + void set_interpolation (unsigned interpolation) + { + d_interpolation = interpolation; + set_relative_rate (1.0 * interpolation); + set_output_multiple (interpolation); + } + + // gr_sync_interpolator overrides these to assist work + 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); + + // derived classes should override work + + int fixed_rate_ninput_to_noutout(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); +}; + + +#endif /* INCLUDED_GR_SYNC_INTERPOLATOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_sync_interpolator.i b/gnuradio-core/src/lib/general/gr_sync_interpolator.i new file mode 100644 index 00000000..9b69d334 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_interpolator.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_sync_interpolator : public gr_sync_block +{ + protected: + + gr_sync_interpolator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned interpolation); +}; diff --git a/gnuradio-core/src/lib/general/gr_test.cc b/gnuradio-core/src/lib/general/gr_test.cc new file mode 100644 index 00000000..17263f49 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.cc @@ -0,0 +1,176 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_test_sptr gr_make_test (const std::string &name, + int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type) +{ + return gr_test_sptr (new gr_test (name, min_inputs,max_inputs,sizeof_input_item, + min_outputs,max_outputs,sizeof_output_item, + history,output_multiple,relative_rate,fixed_rate,cons_type, prod_type)); +} + + gr_test::gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type): gr_block (name, + gr_make_io_signature (min_inputs, max_inputs, sizeof_input_item), + gr_make_io_signature (min_outputs, max_outputs, sizeof_output_item)), + d_sizeof_input_item(sizeof_input_item), + d_sizeof_output_item(sizeof_output_item), + d_check_topology(true), + d_consume_type(cons_type), + d_min_consume(0), + d_max_consume(0), + d_produce_type(prod_type), + d_min_produce(0), + d_max_produce(0) + { + set_history(history); + set_output_multiple(output_multiple); + set_relative_rate(relative_rate); + set_fixed_rate(fixed_rate); + } + +int +gr_test::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //touch all inputs and outputs to detect segfaults + unsigned ninputs = input_items.size (); + unsigned noutputs= output_items.size(); + for (unsigned i = 0; i < ninputs; i++) + { + char * in=(char *)input_items[i]; + if (ninput_items[i]< (int)(noutput_items+history())) + { + std::cerr << "ERROR: ninput_items[" << i << "] < noutput_items+history()" << std::endl; + std::cerr << "ninput_items[" << i << "] = " << ninput_items[i] << std::endl; + std::cerr << "noutput_items+history() = " << noutput_items+history() << std::endl; + std::cerr << "noutput_items = " << noutput_items << std::endl; + std::cerr << "history() = " << history() << std::endl; + throw std::runtime_error ("gr_test"); + } else + { + for (int j=0;j +#include +#include "gr_test_types.h" + +class gr_test; +typedef boost::shared_ptr gr_test_sptr; + +// public constructor +gr_test_sptr gr_make_test (const std::string &name=std::string("gr_test"), + int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + +/*! + * \brief Test class for testing runtime system (setting up buffers and such.) + * \ingroup block + * + * This block does not do any usefull actual data processing. + * It just exposes setting all standard block parameters using the contructor or public methods. + * + * This block can be usefull when testing the runtime system. + * You can force this block to have a large history, decimation + * factor and/or large output_multiple. + * The runtime system should detect this and create large enough buffers + * all through the signal chain. + * + */ + + + + +class gr_test : public gr_block { + + public: + + ~gr_test (){} + +int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + // ---------------------------------------------------------------- + // override these to define your behavior + // ---------------------------------------------------------------- + + /*! + * \brief Estimate input requirements given output request + * + * \param noutput_items number of output items to produce + * \param ninput_items_required number of input items required on each input stream + * + * Given a request to product \p noutput_items, estimate the number of + * data items required on each input stream. The estimate doesn't have + * to be exact, but should be close. + */ + void forecast (int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = (int)((double)noutput_items / relative_rate()) + (int)history(); + } + + + /*! + * \brief Force check topology to return true or false. + * + * \param check_topology value to return when check_topology is called (true or false) + * default check_topology returns true + * + */ + void set_check_topology (bool check_topology){ d_check_topology=check_topology;} + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + bool check_topology (int ninputs, int noutputs) { return d_check_topology;} + + // ---------------------------------------------------------------- + /* + * The following two methods provide special case info to the + * scheduler in the event that a block has a fixed input to output + * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator + * override these. If you're fixed rate, subclass one of those. + */ + /*! + * \brief Given ninput samples, return number of output samples that will be produced. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + int fixed_rate_ninput_to_noutput(int ninput) { return (int)((double)ninput/relative_rate()); } + + /*! + * \brief Given noutput samples, return number of input samples required to produce noutput. + * N.B. this is only defined if fixed_rate returns true. + */ + int fixed_rate_noutput_to_ninput(int noutput) { return (int)((double)noutput*relative_rate()); } + + /*! + * \brief Set if fixed rate should return true. + * N.B. This is normally a private method but we make it available here as public. + */ + void set_fixed_rate_public(bool fixed_rate){ set_fixed_rate(fixed_rate);} + + /*! + * \brief Set the consume pattern. + * + * \param cons_type which consume pattern to use + */ + void set_consume_type (gr_consume_type_t cons_type) { d_consume_type=cons_type;} + + /*! + * \brief Set the consume limit. + * + * \param limit min or maximum items to consume (depending on consume_type) + */ + void set_consume_limit (unsigned int limit) { d_min_consume=limit; d_max_consume=limit;} + + /*! + * \brief Set the produce pattern. + * + * \param prod_type which produce pattern to use + */ + void set_produce_type (gr_produce_type_t prod_type) { d_produce_type=prod_type;} + + /*! + * \brief Set the produce limit. + * + * \param limit min or maximum items to produce (depending on produce_type) + */ + void set_produce_limit (unsigned int limit) { d_min_produce=limit; d_max_produce=limit;} + + // ---------------------------------------------------------------------------- + + + + protected: + unsigned int d_sizeof_input_item; + unsigned int d_sizeof_output_item; + bool d_check_topology; + char d_temp; + gr_consume_type_t d_consume_type; + int d_min_consume; + int d_max_consume; + gr_produce_type_t d_produce_type; + int d_min_produce; + int d_max_produce; + gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); + + + + friend gr_test_sptr gr_make_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); +}; + + + +#endif /* INCLUDED_GR_TEST_H */ diff --git a/gnuradio-core/src/lib/general/gr_test.i b/gnuradio-core/src/lib/general/gr_test.i new file mode 100644 index 00000000..e6f922c0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.i @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,test); + + +class gr_test; +typedef boost::shared_ptr gr_test_sptr; + + +// public constructor +gr_test_sptr gr_make_test (const std::string &name=std::string("gr_test"), + int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + + +class gr_test : public gr_block { + + public: + + ~gr_test (); + void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + void set_check_topology (bool check_topology); + bool check_topology (int ninputs, int noutputs); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void set_fixed_rate_public(bool fixed_rate); + void set_consume_type (gr_consume_type_t cons_type); + void set_consume_limit (unsigned int limit); + void set_produce_type (gr_produce_type_t prod_type); + void set_produce_limit (unsigned int limit); + + protected: + gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); + +}; + + + diff --git a/gnuradio-core/src/lib/general/gr_test_types.h b/gnuradio-core/src/lib/general/gr_test_types.h new file mode 100644 index 00000000..92fe3f74 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test_types.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_TEST_TYPES_H +#define INCLUDED_GR_TEST_TYPES_H + +typedef enum { + CONSUME_NOUTPUT_ITEMS=0, + CONSUME_NOUTPUT_ITEMS_LIMIT_MAX=1, + CONSUME_NOUTPUT_ITEMS_LIMIT_MIN=2, + CONSUME_ALL_AVAILABLE=3, + CONSUME_ALL_AVAILABLE_LIMIT_MAX=4, + /*CONSUME_ALL_AVAILABLE_LIMIT_MIN=5,*/ + CONSUME_ZERO=6, + CONSUME_ONE=7, + CONSUME_MINUS_ONE=8 + } gr_consume_type_t; + +typedef enum { + PRODUCE_NOUTPUT_ITEMS=0, + PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX=1, + /*PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN=2,*/ + PRODUCE_ZERO=6, + PRODUCE_ONE=7, + PRODUCE_MINUS_ONE=8 + } gr_produce_type_t; + +#endif /* INCLUDED_GR_TEST_TYPES_H */ diff --git a/gnuradio-core/src/lib/general/gr_threshold_ff.cc b/gnuradio-core/src/lib/general/gr_threshold_ff.cc new file mode 100644 index 00000000..4041f467 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_threshold_ff_sptr +gr_make_threshold_ff (float lo, float hi, float initial_state) +{ + return gr_threshold_ff_sptr (new gr_threshold_ff (lo, hi, initial_state)); +} + +gr_threshold_ff::gr_threshold_ff (float lo, float hi, float initial_state) + : gr_sync_block ("threshold_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_lo (lo), d_hi (hi), d_last_state (initial_state) +{ +} + +int +gr_threshold_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + + for(int i=0; i d_hi) { + out[i] = 1.0; + d_last_state = 1.0; + } else if (in[i] < d_lo) { + out[i] = 0.0; + d_last_state = 0.0; + } else + out[i] = d_last_state; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_threshold_ff.h b/gnuradio-core/src/lib/general/gr_threshold_ff.h new file mode 100644 index 00000000..30ca67f5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_THRESHOLD_FF_H +#define INCLUDED_GR_THRESHOLD_FF_H + +#include + +class gr_threshold_ff; +typedef boost::shared_ptr gr_threshold_ff_sptr; + +gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state=0); + +/*! + * \brief + * \ingroup block + */ +class gr_threshold_ff : public gr_sync_block +{ + friend gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state); + + float d_lo,d_hi; // the constant + float d_last_state; + gr_threshold_ff (float lo, float hi, float initial_state); + + public: + float lo () const { return d_lo; } + void set_lo (float lo) { d_lo = lo; } + float hi () const { return d_hi; } + void set_hi (float hi) { d_hi = hi; } + float last_state () const { return d_last_state; } + void set_last_state (float last_state) { d_last_state = last_state; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_threshold_ff.i b/gnuradio-core/src/lib/general/gr_threshold_ff.i new file mode 100644 index 00000000..2fcf1dea --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,threshold_ff); + +gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state=0); + +class gr_threshold_ff : public gr_sync_block +{ + private: + gr_threshold_ff (float lo, float hi, float initial_state); + + public: + float lo () const { return d_lo; } + void set_lo (float lo) { d_lo = lo; } + float hi () const { return d_hi; } + void set_hi (float hi) { d_hi = hi; } + float last_state () const { return d_last_state; } + void set_last_state (float last_state) { d_last_state = last_state; } +}; diff --git a/gnuradio-core/src/lib/general/gr_throttle.cc b/gnuradio-core/src/lib/general/gr_throttle.cc new file mode 100644 index 00000000..9fbf23ed --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.cc @@ -0,0 +1,109 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif + + +#ifdef HAVE_NANOSLEEP +void +gr_nanosleep(struct timespec *ts) +{ + struct timespec *req = ts; + struct timespec rem; + int r = nanosleep(req, &rem); + while (r < 0 && errno == EINTR){ + req = &rem; + r = nanosleep(req, &rem); + } + if (r < 0) + perror ("gr_nanosleep"); +} +#endif + +gr_throttle_sptr +gr_make_throttle(size_t itemsize, double samples_per_sec) +{ + return gr_throttle_sptr(new gr_throttle(itemsize, samples_per_sec)); +} + +gr_throttle::gr_throttle(size_t itemsize, double samples_per_sec) + : gr_sync_block("throttle", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_samples_per_sec(samples_per_sec), + d_total_samples(0) +{ +#ifdef HAVE_GETTIMEOFDAY + gettimeofday(&d_start, 0); +#endif +} + +gr_throttle::~gr_throttle() +{ +} + +int +gr_throttle::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]; + char *out = (char *) output_items[0]; + +#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_NANOSLEEP) + // + // If our average sample rate exceeds our target sample rate, + // delay long enough to reduce to our target rate. + // + struct timeval now; + gettimeofday(&now, 0); + long t_usec = now.tv_usec - d_start.tv_usec; + long t_sec = now.tv_sec - d_start.tv_sec; + double t = (double)t_sec + (double)t_usec * 1e-6; + if (t < 1e-6) // avoid unlikely divide by zero + t = 1e-6; + + double actual_samples_per_sec = d_total_samples / t; + if (actual_samples_per_sec > d_samples_per_sec){ // need to delay + double delay = d_total_samples / d_samples_per_sec - t; + struct timespec ts; + ts.tv_sec = (time_t)floor(delay); + ts.tv_nsec = (long)((delay - floor(delay)) * 1e9); + gr_nanosleep(&ts); + } +#endif + + memcpy(out, in, noutput_items * d_itemsize); + d_total_samples += noutput_items; + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_throttle.h b/gnuradio-core/src/lib/general/gr_throttle.h new file mode 100644 index 00000000..c926a405 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_THROTTLE_H +#define INCLUDED_GR_THROTTLE_H + +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +class gr_throttle; +typedef boost::shared_ptr gr_throttle_sptr; + + +gr_throttle_sptr gr_make_throttle(size_t itemsize, double samples_per_sec); + +/*! + * \brief throttle flow of samples such that the average rate does not exceed samples_per_sec. + * \ingroup block + * + * input: one stream of itemsize; output: one stream of itemsize + */ +class gr_throttle : public gr_sync_block +{ + friend gr_throttle_sptr gr_make_throttle(size_t itemsize, double samples_per_sec); + size_t d_itemsize; + double d_samples_per_sec; + double d_total_samples; +#ifdef HAVE_SYS_TIME_H + struct timeval d_start; +#endif + + gr_throttle(size_t itemsize, double samples_per_sec); + +public: + ~gr_throttle(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_THROTTLE_H */ diff --git a/gnuradio-core/src/lib/general/gr_throttle.i b/gnuradio-core/src/lib/general/gr_throttle.i new file mode 100644 index 00000000..eb237b35 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,throttle); + +gr_throttle_sptr gr_make_throttle (size_t itemsize, double samples_per_sec); + +class gr_throttle : public gr_sync_block +{ + gr_throttle (size_t itemsize, double samples_per_sec); +}; diff --git a/gnuradio-core/src/lib/general/gr_uchar_to_float.cc b/gnuradio-core/src/lib/general/gr_uchar_to_float.cc new file mode 100644 index 00000000..e162d777 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_uchar_to_float_sptr +gr_make_uchar_to_float () +{ + return gr_uchar_to_float_sptr (new gr_uchar_to_float ()); +} + +gr_uchar_to_float::gr_uchar_to_float () + : gr_sync_block ("gr_uchar_to_float", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (float))) +{ +} + +int +gr_uchar_to_float::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]; + float *out = (float *) output_items[0]; + + gri_uchar_to_float (in, out, noutput_items); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_uchar_to_float.h b/gnuradio-core/src/lib/general/gr_uchar_to_float.h new file mode 100644 index 00000000..7de55726 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_UCHAR_TO_FLOAT_H +#define INCLUDED_GR_UCHAR_TO_FLOAT_H + +#include + +class gr_uchar_to_float; +typedef boost::shared_ptr gr_uchar_to_float_sptr; + +gr_uchar_to_float_sptr +gr_make_uchar_to_float (); + +/*! + * \brief Convert stream of unsigned chars to a stream of float + * \ingroup converter + */ + +class gr_uchar_to_float : public gr_sync_block +{ + friend gr_uchar_to_float_sptr gr_make_uchar_to_float (); + gr_uchar_to_float (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_UCHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_uchar_to_float.i b/gnuradio-core/src/lib/general/gr_uchar_to_float.i new file mode 100644 index 00000000..4b7e8bce --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,uchar_to_float) + +gr_uchar_to_float_sptr gr_make_uchar_to_float (); + +class gr_uchar_to_float : public gr_sync_block +{ + gr_uchar_to_float (); +}; diff --git a/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc new file mode 100644 index 00000000..399bc111 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (unsigned k) +{ + return gr_unpack_k_bits_bb_sptr (new gr_unpack_k_bits_bb (k)); +} + + +gr_unpack_k_bits_bb::gr_unpack_k_bits_bb (unsigned k) + : gr_sync_interpolator ("unpack_k_bits_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char)), + k), + d_k (k) +{ + if (d_k == 0) + throw std::out_of_range ("interpolation must be > 0"); +} + +gr_unpack_k_bits_bb::~gr_unpack_k_bits_bb () +{ +} + +int +gr_unpack_k_bits_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + int n = 0; + for (unsigned int i = 0; i < noutput_items/d_k; i++){ + unsigned int t = in[i]; + for (int j = d_k - 1; j >= 0; j--) + out[n++] = (t >> j) & 0x01; + } + + assert(n == noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h new file mode 100644 index 00000000..38a8bc1a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_UNPACK_K_BITS_BB_H +#define INCLUDED_GR_UNPACK_K_BITS_BB_H + +#include + +class gr_unpack_k_bits_bb; +typedef boost::shared_ptr gr_unpack_k_bits_bb_sptr; +gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (unsigned k); + +class gr_unpack_k_bits_bb; + +/*! + * \brief Converts a byte with k relevent bits to k output bytes with 1 bit in the LSB + */ +class gr_unpack_k_bits_bb : public gr_sync_interpolator +{ + private: + friend gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (unsigned k); + + gr_unpack_k_bits_bb (unsigned k); + + unsigned d_k; // number of relevent bits to unpack into k output bytes + + public: + ~gr_unpack_k_bits_bb (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.i b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.i new file mode 100644 index 00000000..eb6bda9d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,unpack_k_bits_bb) + +gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (int k); + +class gr_unpack_k_bits_bb : public gr_sync_interpolator +{ + private: + gr_unpack_k_bits_bb (int k); + + public: + ~gr_unpack_k_bits_bb (); +}; diff --git a/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t new file mode 100644 index 00000000..7d5d72e6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include +#include + +static const unsigned int BITS_PER_TYPE = sizeof(@O_TYPE@) * 8; + + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness) +{ + return @SPTR_NAME@ + (new @NAME@ (bits_per_chunk,endianness)); +} + +@NAME@::@NAME@ (unsigned int bits_per_chunk, + gr_endianness_t endianness) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, -1, sizeof (@O_TYPE@))), + d_bits_per_chunk(bits_per_chunk),d_endianness(endianness),d_index(0) +{ + assert (bits_per_chunk <= BITS_PER_TYPE); + assert (bits_per_chunk > 0); + + set_relative_rate (bits_per_chunk/(1.0 * BITS_PER_TYPE)); +} + +void +@NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + int input_required = (int) ceil( (d_index+noutput_items * 1.0 * BITS_PER_TYPE)/d_bits_per_chunk); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + } +} + +unsigned int +get_bit_be1 (const @I_TYPE@ *in_vector,unsigned int bit_addr, unsigned int bits_per_chunk) { + unsigned int byte_addr = (int)bit_addr/bits_per_chunk; + @I_TYPE@ x = in_vector[byte_addr]; + unsigned int residue = bit_addr - byte_addr * bits_per_chunk; + //printf("Bit addr %d byte addr %d residue %d val %d\n",bit_addr,byte_addr,residue,(x>>(bits_per_chunk-1-residue))&1); + return (x >> (bits_per_chunk-1-residue))&1; +} + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + 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 + + //assert((ninput_items[m]-d_index)*d_bits_per_chunk >= noutput_items*BITS_PER_TYPE); + + switch(d_endianness){ + + case GR_MSB_FIRST: + for(int i=0;i>1)| (get_bit_be1(in,d_index,d_bits_per_chunk)<<(BITS_PER_TYPE-1)); + d_index++; + } + out[i] = tmp; + } + break; + + default: + assert(0); + } + } + + consume_each ((int)(d_index/d_bits_per_chunk)); + d_index = d_index%d_bits_per_chunk; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.h.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.h.t new file mode 100644 index 00000000..8d8c14d2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.h.t @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +/*! + * \brief Convert a stream of unpacked bytes or shorts into a stream of packed bytes or shorts. + * \ingroup block + * + * input: stream of @I_TYPE@; output: stream of @O_TYPE@ + * + * This is the inverse of gr_packed_to_unpacked_XX. + * + * The low \p bits_per_chunk bits are extracted from each input byte or short. + * These bits are then packed densely into the output bytes or shorts, such that + * all 8 or 16 bits of the output bytes or shorts are filled with valid input bits. + * The right thing is done if bits_per_chunk is not a power of two. + * + * The combination of gr_packed_to_unpacked_XX followed by + * gr_chunks_to_symbols_Xf or gr_chunks_to_symbols_Xc handles the + * general case of mapping from a stream of bytes or shorts into arbitrary float + * or complex symbols. + * + * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, + * \sa gr_packed_to_unpacked_ss, gr_unpacked_to_packed_ss, + * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. + * \sa gr_chunks_to_symbols_sf, gr_chunks_to_symbols_sc. + */ +class @NAME@ : public gr_block +{ + friend @SPTR_NAME@ + gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + unsigned int d_bits_per_chunk; + gr_endianness_t d_endianness; + unsigned int d_index; + + 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); + + bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.i.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.i.t new file mode 100644 index 00000000..7fdcb5d7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +class @NAME@ : public gr_block +{ + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); +}; diff --git a/gnuradio-core/src/lib/general/gr_vco.h b/gnuradio-core/src/lib/general/gr_vco.h new file mode 100644 index 00000000..3c35bdff --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_VCO_H_ +#define _GR_VCO_H_ + + +#include +#include +#include +#include + +/*! + * \brief base class template for Voltage Controlled Oscillator (VCO) + */ + +//FIXME Eventually generalize this to fixed point + +template +class gr_vco { +public: + gr_vco () : d_phase (0) {} + + virtual ~gr_vco () {} + + // radians + void set_phase (double angle) { + d_phase = angle; + } + + void adjust_phase (double delta_phase) { + d_phase += delta_phase; + if (fabs (d_phase) > M_PI){ + + while (d_phase > M_PI) + d_phase -= 2*M_PI; + + while (d_phase < -M_PI) + d_phase += 2*M_PI; + } + } + + double get_phase () const { return d_phase; } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const; + + // compute cos or sin for current phase angle + float cos () const { return std::cos (d_phase); } + float sin () const { return std::sin (d_phase); } + + // compute a block at a time + void cos (float *output, const float *input, int noutput_items, double k, double ampl = 1.0); + +protected: + double d_phase; +}; + +template +void +gr_vco::sincos (float *sinx, float *cosx) const +{ + gr_sincosf (d_phase, sinx, cosx); +} + +template +void +gr_vco::cos (float *output, const float *input, int noutput_items, double k, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = cos() * ampl; + adjust_phase(input[i] * k); + } +} +#endif /* _GR_VCO_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_vco_f.cc b/gnuradio-core/src/lib/general/gr_vco_f.cc new file mode 100644 index 00000000..7421e4ec --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_vco_f_sptr +gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude) +{ + return gr_vco_f_sptr(new gr_vco_f(sampling_rate, sensitivity, amplitude)); +} + + +gr_vco_f::gr_vco_f(double sampling_rate, double sensitivity, double amplitude) + : gr_sync_block("vco_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_sampling_rate(sampling_rate), d_sensitivity(sensitivity), d_amplitude(amplitude), + d_k(d_sensitivity/d_sampling_rate) +{ +} + +int +gr_vco_f::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *input = (const float *)input_items[0]; + float *output = (float *)output_items[0]; + + d_vco.cos(output, input, noutput_items, d_k, d_amplitude); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vco_f.h b/gnuradio-core/src/lib/general/gr_vco_f.h new file mode 100644 index 00000000..2872d387 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_VCO_F_H +#define INCLUDED_GR_VCO_F_H + +#include +#include + +class gr_vco_f; +typedef boost::shared_ptr gr_vco_f_sptr; + +/*! + * \brief VCO - Voltage controlled oscillator + * + * \param sampling_rate sampling rate (Hz) + * \param sensitivity units are radians/sec/volt + * \param amplitude output amplitude + */ +gr_vco_f_sptr gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude); + +/*! + * \brief VCO - Voltage controlled oscillator + * \ingroup block + * + * input: float stream of control voltages; output: float oscillator output + */ +class gr_vco_f : public gr_sync_block +{ + friend gr_vco_f_sptr gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude); + + /*! + * \brief VCO - Voltage controlled oscillator + * + * \param sampling_rate sampling rate (Hz) + * \param sensitivity units are radians/sec/volt + * \param amplitude output amplitude + */ + gr_vco_f(double sampling_rate, double sensitivity, double amplitude); + + double d_sampling_rate; + double d_sensitivity; + double d_amplitude; + double d_k; + gr_fxpt_vco d_vco; + +public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_VCO_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_vco_f.i b/gnuradio-core/src/lib/general/gr_vco_f.i new file mode 100644 index 00000000..d3447450 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.i @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,vco_f); + +/*! + * \brief VCO - Voltage controlled oscillator + * + * \param sampling_rate sampling rate (Hz) + * \param sensitivity units are radians/sec/volt + * \param amplitude output amplitude + */ +gr_vco_f_sptr gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude); + + +class gr_vco_f : public gr_sync_block { + private: + gr_vco_f(double sampling_rate, double sensitivity, double amplitude); +}; diff --git a/gnuradio-core/src/lib/general/gr_vector_sink_X.cc.t b/gnuradio-core/src/lib/general/gr_vector_sink_X.cc.t new file mode 100644 index 00000000..5e99a928 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_sink_X.cc.t @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include <@NAME@.h> +#include +#include + + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@TYPE@)), + gr_make_io_signature (0, 0, 0)) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *iptr = (@TYPE@ *) input_items[0]; + for (int i = 0; i < noutput_items; i++) + d_data.push_back (iptr[i]); + + return noutput_items; +} + + +@NAME@_sptr +gr_make_@BASE_NAME@ () +{ + return @NAME@_sptr (new @NAME@ ()); +} + +std::vector<@TYPE@> +@NAME@::data () const +{ + return d_data; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_sink_X.h.t b/gnuradio-core/src/lib/general/gr_vector_sink_X.h.t new file mode 100644 index 00000000..e549f1fb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_sink_X.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +@NAME@_sptr +gr_make_@BASE_NAME@ (); + + +/*! + * \brief @TYPE@ sink that writes to a vector + * \ingroup sink + */ + +class @NAME@ : public gr_sync_block { + friend @NAME@_sptr gr_make_@BASE_NAME@ (); + std::vector<@TYPE@> d_data; + @NAME@ (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + std::vector<@TYPE@> data () const; +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_vector_sink_X.i.t b/gnuradio-core/src/lib/general/gr_vector_sink_X.i.t new file mode 100644 index 00000000..d10636cf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_sink_X.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (); + + public: + std::vector<@TYPE@> data () const; +}; + diff --git a/gnuradio-core/src/lib/general/gr_vector_source_X.cc.t b/gnuradio-core/src/lib/general/gr_vector_source_X.cc.t new file mode 100644 index 00000000..4ec2dd8b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_source_X.cc.t @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include <@NAME@.h> +#include +#include + + +@NAME@::@NAME@ (const std::vector<@TYPE@> &data, bool repeat) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_data (data), + d_repeat (repeat), + d_offset (0) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *optr = (@TYPE@ *) output_items[0]; + + if (d_repeat){ + unsigned int size = d_data.size (); + unsigned int offset = d_offset; + + if (size == 0) + return -1; + + for (int i = 0; i < noutput_items; i++){ + optr[i] = d_data[offset++]; + if (offset >= size) + offset = 0; + } + d_offset = offset; + return noutput_items; + } + + else { + if (d_offset >= d_data.size ()) + return -1; // Done! + + unsigned n = std::min ((unsigned) d_data.size () - d_offset, + (unsigned) noutput_items); + for (unsigned i = 0; i < n; i++) + optr[i] = d_data[d_offset + i]; + + d_offset += n; + return n; + } +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat) +{ + return @NAME@_sptr (new @NAME@ (data, repeat)); +} + diff --git a/gnuradio-core/src/lib/general/gr_vector_source_X.h.t b/gnuradio-core/src/lib/general/gr_vector_source_X.h.t new file mode 100644 index 00000000..631ab867 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_source_X.h.t @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief source of @TYPE@'s that gets its data from a vector + * \ingroup source + */ + +class @NAME@ : public gr_sync_block { + friend @NAME@_sptr + gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false); + + std::vector<@TYPE@> d_data; + bool d_repeat; + unsigned int d_offset; + + @NAME@ (const std::vector<@TYPE@> &data, bool repeat); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat); + +#endif diff --git a/gnuradio-core/src/lib/general/gr_vector_source_X.i.t b/gnuradio-core/src/lib/general/gr_vector_source_X.i.t new file mode 100644 index 00000000..f3b98c62 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_source_X.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false); + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (const std::vector<@TYPE@> &data); +}; diff --git a/gnuradio-core/src/lib/general/gr_vector_to_stream.cc b/gnuradio-core/src/lib/general/gr_vector_to_stream.cc new file mode 100644 index 00000000..130f9613 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block) +{ + return gr_vector_to_stream_sptr (new gr_vector_to_stream (item_size, nitems_per_block)); +} + +gr_vector_to_stream::gr_vector_to_stream (size_t item_size, size_t nitems_per_block) + : gr_sync_interpolator ("vector_to_stream", + gr_make_io_signature (1, 1, item_size * nitems_per_block), + gr_make_io_signature (1, 1, item_size), + nitems_per_block) +{ +} + +int +gr_vector_to_stream::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t block_size = output_signature()->sizeof_stream_item (0); + + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + memcpy (out, in, noutput_items * block_size); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_to_stream.h b/gnuradio-core/src/lib/general/gr_vector_to_stream.h new file mode 100644 index 00000000..5efff733 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_VECTOR_TO_STREAM_H +#define INCLUDED_GR_VECTOR_TO_STREAM_H + +#include + +class gr_vector_to_stream; +typedef boost::shared_ptr gr_vector_to_stream_sptr; + +gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block); + + +/*! + * \brief convert a stream of blocks of nitems_per_block items into a stream of items + * \ingroup block + */ +class gr_vector_to_stream : public gr_sync_interpolator +{ + friend gr_vector_to_stream_sptr + gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block); + + protected: + gr_vector_to_stream (size_t item_size, size_t nitems_per_block); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_VECTOR_TO_STREAM_H */ diff --git a/gnuradio-core/src/lib/general/gr_vector_to_stream.i b/gnuradio-core/src/lib/general/gr_vector_to_stream.i new file mode 100644 index 00000000..66ae1739 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,vector_to_stream) + +gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t itemsize, size_t nitems_per_block); + +class gr_vector_to_stream : public gr_sync_decimator +{ + protected: + gr_vector_to_stream (size_t itemsize, size_t nitems_per_block); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_vector_to_streams.cc b/gnuradio-core/src/lib/general/gr_vector_to_streams.cc new file mode 100644 index 00000000..4a3f110e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.cc @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t item_size, size_t nstreams) +{ + return gr_vector_to_streams_sptr (new gr_vector_to_streams (item_size, nstreams)); +} + +gr_vector_to_streams::gr_vector_to_streams (size_t item_size, size_t nstreams) + : gr_sync_block ("vector_to_streams", + gr_make_io_signature (1, 1, nstreams * item_size), + gr_make_io_signature (nstreams, nstreams, item_size)) +{ +} + +int +gr_vector_to_streams::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = output_signature()->sizeof_stream_item(0); + int nstreams = output_items.size(); + + const char *in = (const char *) input_items[0]; + char **outv = (char **) &output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(outv[j], in, item_size); + outv[j] += item_size; + in += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_to_streams.h b/gnuradio-core/src/lib/general/gr_vector_to_streams.h new file mode 100644 index 00000000..ae13fae4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_VECTOR_TO_STREAMS_H +#define INCLUDED_GR_VECTOR_TO_STREAMS_H + +#include + +class gr_vector_to_streams; +typedef boost::shared_ptr gr_vector_to_streams_sptr; + +gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t item_size, size_t nstreams); + + +/*! + * \brief Convert 1 stream of vectors of length N to N streams of items + * \ingroup block + */ +class gr_vector_to_streams : public gr_sync_block +{ + friend gr_vector_to_streams_sptr + gr_make_vector_to_streams (size_t item_size, size_t nstreams); + + protected: + gr_vector_to_streams (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_VECTOR_TO_STREAMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_vector_to_streams.i b/gnuradio-core/src/lib/general/gr_vector_to_streams.i new file mode 100644 index 00000000..7444d0d6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,vector_to_streams) + +gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t itemsize, size_t nstreams); + +class gr_vector_to_streams : public gr_sync_block +{ + protected: + gr_vector_to_streams (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gri_add_const_ss.h b/gnuradio-core/src/lib/general/gri_add_const_ss.h new file mode 100644 index 00000000..49fddb68 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_add_const_ss.h @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_ADD_CONST_SS_H +#define INCLUDED_GRI_ADD_CONST_SS_H + +/*! + * \brief Low-level, high-speed add_const_ss primitive + * + * copy src to dst adding konst + */ + +void +gri_add_const_ss (short *dst, const short *src, int nshorts, short konst); + + +#endif /* _INCLUDED_GRI_ADD_CONST_SS_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc b/gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc new file mode 100644 index 00000000..f94db30e --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +void +gri_add_const_ss (short *dst, const short *src, int nshorts, short konst) +{ + static const int STRIDE = 8; + + int i; + + for (i = 0; i < nshorts - (STRIDE - 1); i += STRIDE){ + dst[i + 0] = src[i + 0] + konst; + dst[i + 1] = src[i + 1] + konst; + dst[i + 2] = src[i + 2] + konst; + dst[i + 3] = src[i + 3] + konst; + dst[i + 4] = src[i + 4] + konst; + dst[i + 5] = src[i + 5] + konst; + dst[i + 6] = src[i + 6] + konst; + dst[i + 7] = src[i + 7] + konst; + } + + for (; i < nshorts; i++) + dst[i] = src[i] + konst; +} diff --git a/gnuradio-core/src/lib/general/gri_agc.h b/gnuradio-core/src/lib/general/gri_agc.h new file mode 100644 index 00000000..eaaed8c3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRI_AGC_H_ +#define _GRI_AGC_H_ + +#include + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + +class gri_agc { + + public: + gri_agc (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0) + : _rate(rate), _reference(reference), _gain(gain), _max_gain(max_gain) {}; + + float rate () const { return _rate; } + float reference () const { return _reference; } + float gain () const { return _gain; } + float max_gain () const { return _max_gain; } + + void set_rate (float rate) { _rate = rate; } + void set_reference (float reference) { _reference = reference; } + void set_gain (float gain) { _gain = gain; } + void set_max_gain (float max_gain) { _max_gain = max_gain; } + + float scale (float input){ + float output = input * _gain; + _gain += (_reference - fabsf (output)) * _rate; + if (_max_gain > 0.0 && _gain > _max_gain) + _gain = _max_gain; + return output; + } + + void scaleN (float output[], const float input[], unsigned n){ + for (unsigned i = 0; i < n; i++) + output[i] = scale (input[i]); + } + + protected: + float _rate; // adjustment rate + float _reference; // reference value + float _gain; // current gain + float _max_gain; // maximum gain +}; + +#endif /* _GRI_AGC_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_agc.i b/gnuradio-core/src/lib/general/gri_agc.i new file mode 100644 index 00000000..0bdbd404 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + + +class gri_agc { + + public: + gri_agc (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0); + }; diff --git a/gnuradio-core/src/lib/general/gri_agc_cc.h b/gnuradio-core/src/lib/general/gri_agc_cc.h new file mode 100644 index 00000000..5cdd4e46 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_cc.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRI_AGC_CC_H_ +#define _GRI_AGC_CC_H_ + +#include + +/*! + * \brief high performance Automatic Gain Control class + * + * For Power the absolute value of the complex number is used. + */ + +class gri_agc_cc { + + public: + gri_agc_cc (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0) + : _rate(rate), _reference(reference), _gain(gain), _max_gain(max_gain) {}; + + float rate () const { return _rate; } + float reference () const { return _reference; } + float gain () const { return _gain; } + float max_gain() const { return _max_gain; } + + void set_rate (float rate) { _rate = rate; } + void set_reference (float reference) { _reference = reference; } + void set_gain (float gain) { _gain = gain; } + void set_max_gain(float max_gain) { _max_gain = max_gain; } + + gr_complex scale (gr_complex input){ + gr_complex output = input * _gain; + _gain += (_reference - sqrt(output.real()*output.real()+output.imag()*output.imag())) * _rate; //use abs or cabs to get approximation by absolute value, + //note that abs is computationally more intensive then norm for a complex number + if (_max_gain > 0.0 && _gain > _max_gain) + _gain = _max_gain; + return output; + } + + void scaleN (gr_complex output[], const gr_complex input[], unsigned n){ + for (unsigned i = 0; i < n; i++) + output[i] = scale (input[i]); + } + + protected: + float _rate; // adjustment rate + float _reference; // reference value + float _gain; // current gain + float _max_gain; // max allowable gain +}; + +#endif /* _GRI_AGC_CC_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_agc_cc.i b/gnuradio-core/src/lib/general/gri_agc_cc.i new file mode 100644 index 00000000..70c1baa7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_cc.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +/*! + * \brief high performance Automatic Gain Control class + * + * For Power the absolute value of the complex number is used. + */ + + +class gri_agc_cc { + + public: + gri_agc_cc (float rate = 1e-4, float reference = 1.0, float gain = 1.0, float max_gain = 0.0); + float rate (); + float reference (); + float gain (); + float max_gain (); + }; diff --git a/gnuradio-core/src/lib/general/gri_char_to_float.cc b/gnuradio-core/src/lib/general/gri_char_to_float.cc new file mode 100644 index 00000000..ca02ca27 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_char_to_float.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +void +gri_char_to_float (const char *in, float *out, int nsamples) +{ + while (nsamples >= 4){ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out += 4; + in += 4; + nsamples -= 4; + } + + while (nsamples-- > 0) + *out++ = *in++; +} diff --git a/gnuradio-core/src/lib/general/gri_char_to_float.h b/gnuradio-core/src/lib/general/gri_char_to_float.h new file mode 100644 index 00000000..7aa38d02 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_char_to_float.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_CHAR_TO_FLOAT_H +#define INCLUDED_GRI_CHAR_TO_FLOAT_H + +/* + * convert array of chars to floats + */ +void gri_char_to_float (const char *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_CHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gri_debugger_hook.cc b/gnuradio-core/src/lib/general/gri_debugger_hook.cc new file mode 100644 index 00000000..35e138aa --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_debugger_hook.cc @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +void +gri_debugger_hook () +{ + // nop. set a breakpoint here +} diff --git a/gnuradio-core/src/lib/general/gri_debugger_hook.h b/gnuradio-core/src/lib/general/gri_debugger_hook.h new file mode 100644 index 00000000..612b7c59 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_debugger_hook.h @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_DEBUGGER_HOOK_H +#define INCLUDED_GRI_DEBUGGER_HOOK_H + +void gri_debugger_hook (); + +#endif /* INCLUDED_GRI_DEBUGGER_HOOK_H */ diff --git a/gnuradio-core/src/lib/general/gri_fft.cc b/gnuradio-core/src/lib/general/gri_fft.cc new file mode 100644 index 00000000..30b01271 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_fft.cc @@ -0,0 +1,229 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static char * +wisdom_filename () +{ + static char *filename = ".gr_fftw_wisdom"; + + char *home = getenv ("HOME"); + if (home){ + char *p = new char[strlen (home) + strlen (filename) + 2]; + strcpy (p, home); + strcat (p, "/"); + strcat (p, filename); + return p; + } + return 0; +} + +static void +gri_fftw_import_wisdom () +{ + 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, "gri_fftw: can't import wisdom from %s\n", filename); + } + } + delete [] filename; +} + +static void +gri_fftw_export_wisdom () +{ + char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "w"); + if (fp != 0){ + fftwf_export_wisdom_to_file (fp); + fclose (fp); + } + else { + fprintf (stderr, "gri_fftw: "); + perror (filename); + } + delete [] filename; +} + +// ---------------------------------------------------------------- + +gri_fft_complex::gri_fft_complex (int fft_size, bool forward) +{ + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gri_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"); + } + + // 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. + + gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_1d (fft_size, + reinterpret_cast(d_inbuf), + reinterpret_cast(d_outbuf), + forward ? FFTW_FORWARD : FFTW_BACKWARD, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gri_fft_complex: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_1d failed"); + } + gri_fftw_export_wisdom (); // store new wisdom to disk +} + +gri_fft_complex::~gri_fft_complex () +{ + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_complex::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + +// ---------------------------------------------------------------- + +gri_fft_real_fwd::gri_fft_real_fwd (int fft_size) +{ + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gri_fftw: 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"); + } + + // 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. + + gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_r2c_1d (fft_size, + d_inbuf, + reinterpret_cast(d_outbuf), + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gri_fft_real_fwd: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed"); + } + gri_fftw_export_wisdom (); // store new wisdom to disk +} + +gri_fft_real_fwd::~gri_fft_real_fwd () +{ + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_real_fwd::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + +// ---------------------------------------------------------------- + +gri_fft_real_rev::gri_fft_real_rev (int fft_size) +{ + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gri_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 = (float *) fftwf_malloc (sizeof (float) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + // 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. + + gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_c2r_1d (fft_size, + reinterpret_cast(d_inbuf), + d_outbuf, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gri_fft_real_rev: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed"); + } + gri_fftw_export_wisdom (); // store new wisdom to disk +} + +gri_fft_real_rev::~gri_fft_real_rev () +{ + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_real_rev::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + diff --git a/gnuradio-core/src/lib/general/gri_fft.h b/gnuradio-core/src/lib/general/gri_fft.h new file mode 100644 index 00000000..50347748 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_fft.h @@ -0,0 +1,122 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRI_FFT_H_ +#define _GRI_FFT_H_ + +/* + * Wrappers for FFTW single precision 1d dft + */ + +#include + +/*! + * \brief FFT: complex in, complex out + */ + +class gri_fft_complex { + int d_fft_size; + gr_complex *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + +public: + gri_fft_complex (int fft_size, bool forward = true); + virtual ~gri_fft_complex (); + + /* + * These return pointers to buffers owned by gri_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; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +/*! + * \brief FFT: real in, complex out + */ +class gri_fft_real_fwd { + int d_fft_size; + float *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + +public: + gri_fft_real_fwd (int fft_size); + virtual ~gri_fft_real_fwd (); + + /* + * These return pointers to buffers owned by gri_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; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +/*! + * \brief FFT: complex in, float out + */ +class gri_fft_real_rev { + int d_fft_size; + gr_complex *d_inbuf; + float *d_outbuf; + void *d_plan; + +public: + gri_fft_real_rev (int fft_size); + virtual ~gri_fft_real_rev (); + + /* + * These return pointers to buffers owned by gri_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; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gri_float_to_char.cc b/gnuradio-core/src/lib/general/gri_float_to_char.cc new file mode 100644 index 00000000..b94c5344 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_char.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define _ISOC9X_SOURCE +#include +#include + +static const int MIN_CHAR = -128; +static const int MAX_CHAR = 127; + + +void +gri_float_to_char (const float *in, char *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + long int r = (long int) rint (in[i]); + if (r < MIN_CHAR) + r = MIN_CHAR; + else if (r > MAX_CHAR) + r = MAX_CHAR; + out[i] = r; + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_char.h b/gnuradio-core/src/lib/general/gri_float_to_char.h new file mode 100644 index 00000000..8891ac1a --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_char.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_FLOAT_TO_CHAR_H +#define INCLUDED_GRI_FLOAT_TO_CHAR_H + +/*! + * convert array of floats to chars with rounding and saturation. + */ +void gri_float_to_char (const float *in, char *out, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_CHAR_H */ + diff --git a/gnuradio-core/src/lib/general/gri_float_to_short.cc b/gnuradio-core/src/lib/general/gri_float_to_short.cc new file mode 100644 index 00000000..b2910616 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_short.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define _ISOC9X_SOURCE +#include +#include + +static const int MIN_SHORT = -32768; +static const int MAX_SHORT = 32767; + + +void +gri_float_to_short (const float *in, short *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + long int r = (long int) rint (in[i]); + if (r < MIN_SHORT) + r = MIN_SHORT; + else if (r > MAX_SHORT) + r = MAX_SHORT; + out[i] = r; + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_short.h b/gnuradio-core/src/lib/general/gri_float_to_short.h new file mode 100644 index 00000000..e13b61d5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_short.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_FLOAT_TO_SHORT_H +#define INCLUDED_GRI_FLOAT_TO_SHORT_H + +/*! + * convert array of floats to shorts with rounding and saturation. + */ +void gri_float_to_short (const float *in, short *out, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_SHORT_H */ + diff --git a/gnuradio-core/src/lib/general/gri_float_to_uchar.cc b/gnuradio-core/src/lib/general/gri_float_to_uchar.cc new file mode 100644 index 00000000..8281a967 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_uchar.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define _ISOC9X_SOURCE +#include +#include + +static const int MIN_UCHAR = 0; +static const int MAX_UCHAR = 255; + + +void +gri_float_to_uchar (const float *in, unsigned char *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + long int r = (long int) rint (in[i]); + if (r < MIN_UCHAR) + r = MIN_UCHAR; + else if (r > MAX_UCHAR) + r = MAX_UCHAR; + out[i] = r; + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_uchar.h b/gnuradio-core/src/lib/general/gri_float_to_uchar.h new file mode 100644 index 00000000..fbde8c51 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_uchar.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_FLOAT_TO_UCHAR_H +#define INCLUDED_GRI_FLOAT_TO_UCHAR_H + +/*! + * convert array of floats to unsigned chars with rounding and saturation. + */ +void gri_float_to_uchar (const float *in, unsigned char *out, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_UCHAR_H */ + diff --git a/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc new file mode 100644 index 00000000..56e3c39a --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +void +gri_interleaved_short_to_complex (const short *in, + gr_complex *out, int nsamples) +{ + assert (nsamples % 2 == 0); + + for (int i = 0; i < nsamples/2; i++){ + out[i] = gr_complex (in[i*2 + 0], in[i*2 + 1]); + } +} diff --git a/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h new file mode 100644 index 00000000..3a0fc3de --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_H +#define INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_H + +#include + +/* + * convert array of interleaved shorts to complex. + * the shorts contains real, imaginary, real, imaginary... + * nsamples is the number of shorts; it must be even. + */ +void gri_interleaved_short_to_complex (const short *in, gr_complex *out, int nsamples); + +#endif /* INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_H */ + + diff --git a/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h b/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h new file mode 100644 index 00000000..561ba6c5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_LFSR_15_1_0_H +#define INCLUDED_GRI_LFSR_15_1_0_H + +/*! + * \brief Linear Feedback Shift Register using primitive polynomial x^15 + x + 1 + * + * Generates a maximal length pseudo-random sequence of length 2^15 - 1 bits. + */ + +class gri_lfsr_15_1_0 { + unsigned long d_sr; // shift register + + public: + + gri_lfsr_15_1_0 () { reset (); } + + void reset () { d_sr = 0x7fff; } + + int next_bit (){ + d_sr = ((((d_sr >> 1) ^ d_sr) & 0x1) << 14) | (d_sr >> 1); + return d_sr & 0x1; + } + + int next_byte (){ + int v = 0; + for (int i = 0; i < 8; i++){ + v >>= 1; + if (next_bit ()) + v |= 0x80; + } + return v; + } +}; + +#endif /* INCLUDED_GRI_LFSR_15_1_0_H */ diff --git a/gnuradio-core/src/lib/general/gri_lfsr_32k.h b/gnuradio-core/src/lib/general/gri_lfsr_32k.h new file mode 100644 index 00000000..653223e6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr_32k.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_LFSR_32k_H +#define INCLUDED_GRI_LFSR_32k_H + +#include + +/*! + * \brief generate pseudo-random sequence of length 32768 bits. + * + * This is based on gri_lfsr_15_1_0 with an extra 0 added at the end + * of the sequence. + */ + +class gri_lfsr_32k { + gri_lfsr_15_1_0 d_lfsr; + unsigned int d_count; + + public: + gri_lfsr_32k () { reset (); } + + void reset (){ + d_lfsr.reset (); + d_count = 0; + } + + int next_bit (){ + if (d_count == 32767){ + d_count = 0; + return 0; + } + d_count++; + return d_lfsr.next_bit (); + } + + int next_byte (){ + int v = 0; + for (int i = 0; i < 8; i++){ + v >>= 1; + if (next_bit ()) + v |= 0x80; + } + return v; + } + + int next_short (){ + int v = 0; + for (int i = 0; i < 16; i++){ + v >>= 1; + if (next_bit ()) + v |= 0x8000; + } + return v; + } + +}; + +#endif /* INCLUDED_GRI_LFSR_32k_H */ diff --git a/gnuradio-core/src/lib/general/gri_short_to_float.cc b/gnuradio-core/src/lib/general/gri_short_to_float.cc new file mode 100644 index 00000000..f6beb456 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_short_to_float.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +void +gri_short_to_float (const short *in, float *out, int nsamples) +{ + while (nsamples >= 4){ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out += 4; + in += 4; + nsamples -= 4; + } + + while (nsamples-- > 0) + *out++ = *in++; +} diff --git a/gnuradio-core/src/lib/general/gri_short_to_float.h b/gnuradio-core/src/lib/general/gri_short_to_float.h new file mode 100644 index 00000000..1abd0dd5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_short_to_float.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_SHORT_TO_FLOAT_H +#define INCLUDED_GRI_SHORT_TO_FLOAT_H + +/* + * convert array of shorts to floats + */ +void gri_short_to_float (const short *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_SHORT_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gri_uchar_to_float.cc b/gnuradio-core/src/lib/general/gri_uchar_to_float.cc new file mode 100644 index 00000000..8a5f87a5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_uchar_to_float.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +void +gri_uchar_to_float (const unsigned char *in, float *out, int nsamples) +{ + while (nsamples >= 4){ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out += 4; + in += 4; + nsamples -= 4; + } + + while (nsamples-- > 0) + *out++ = *in++; +} diff --git a/gnuradio-core/src/lib/general/gri_uchar_to_float.h b/gnuradio-core/src/lib/general/gri_uchar_to_float.h new file mode 100644 index 00000000..50646e46 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_uchar_to_float.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_UCHAR_TO_FLOAT_H +#define INCLUDED_GRI_UCHAR_TO_FLOAT_H + +/* + * convert array of unsigned chars to floats + */ +void gri_uchar_to_float (const unsigned char *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_UCHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/malloc16.c b/gnuradio-core/src/lib/general/malloc16.c new file mode 100644 index 00000000..2cc6135e --- /dev/null +++ b/gnuradio-core/src/lib/general/malloc16.c @@ -0,0 +1,46 @@ +/* Wrapper functions for malloc/free that force 16-byte alignment + * See http://perso.club-internet.fr/matmac/sourcesc.htm + + * Copyright 2001 Phil Karn, KA9Q + * May be used under the terms of the GNU Public License (GPL) + */ + +#include "malloc16.h" +#include + +void *malloc16Align(int size){ + void *p; + void **p1; + + if((p = malloc(size+31)) == NULL) + return NULL; + + /* Round up to next 16-byte boundary */ + p1 = (void **)(((long)p + 31) & (~15)); + + /* Stash actual start of block just before ptr we return */ + p1[-1] = p; + + /* Return 16-byte aligned address */ + return (void *)p1; +} + +void *calloc16Align(size_t nmemb,size_t size){ + int nbytes; + void *p; + + nbytes = nmemb*size; + if((p = malloc16Align(nbytes)) == NULL) + return NULL; + + memset(p,0,nbytes); + return p; +} + +void free16Align(void *p){ + + if(p != NULL){ + /* Retrieve pointer to actual start of block and free it */ + free(((void **)p)[-1]); + } +} diff --git a/gnuradio-core/src/lib/general/malloc16.h b/gnuradio-core/src/lib/general/malloc16.h new file mode 100644 index 00000000..0376ec56 --- /dev/null +++ b/gnuradio-core/src/lib/general/malloc16.h @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void *malloc16Align(int size); +void *calloc16Align(size_t nmemb,size_t size); +void free16Align(void *p); + +#ifdef __cplusplus +} +#endif diff --git a/gnuradio-core/src/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc new file mode 100644 index 00000000..1fa2b935 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_general.cc @@ -0,0 +1,47 @@ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include +#include +#include +#include +#include +#include + +CppUnit::TestSuite * +qa_general::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("general"); + + s->addTest (qa_gr_firdes::suite ()); + s->addTest (qa_gr_circular_file::suite ()); + s->addTest (qa_gr_fxpt::suite ()); + s->addTest (qa_gr_fxpt_nco::suite ()); + s->addTest (qa_gr_fxpt_vco::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/general/qa_general.h b/gnuradio-core/src/lib/general/qa_general.h new file mode 100644 index 00000000..6bf57df6 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_general.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_GENERAL_H_ +#define _QA_GENERAL_H_ + +#include + +//! collect all the tests for the gr directory + +class qa_general { + public: + //! return suite of tests for all of gr directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_GENERAL_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gr_circular_file.cc b/gnuradio-core/src/lib/general/qa_gr_circular_file.cc new file mode 100644 index 00000000..adfa33cb --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_circular_file.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include + +static const char *test_file = "qa_gr_circular_file.data"; +static const int BUFFER_SIZE = 8192; +static const int NWRITE = 8192 * 9 / 8; + +void +qa_gr_circular_file::t1 () +{ +#ifdef HAVE_MMAP + gr_circular_file *cf_writer; + gr_circular_file *cf_reader; + + // write the data... + + cf_writer = new gr_circular_file (test_file, true, BUFFER_SIZE * sizeof (short)); + + short sd; + for (int i = 0; i < NWRITE; i++){ + sd = i; + cf_writer->write (&sd, sizeof (sd)); + } + + delete cf_writer; + + // now read it back... + + cf_reader = new gr_circular_file (test_file); + for (int i = 0; i < BUFFER_SIZE; i++){ + int n = cf_reader->read (&sd, sizeof (sd)); + CPPUNIT_ASSERT_EQUAL ((int) sizeof (sd), n); + CPPUNIT_ASSERT_EQUAL (NWRITE - BUFFER_SIZE + i, (int) sd); + } + + int n = cf_reader->read (&sd, sizeof (sd)); + CPPUNIT_ASSERT_EQUAL (0, n); + + delete cf_reader; + unlink (test_file); +#endif // HAVE_MMAP +} + diff --git a/gnuradio-core/src/lib/general/qa_gr_circular_file.h b/gnuradio-core/src/lib/general/qa_gr_circular_file.h new file mode 100644 index 00000000..45ebfd8e --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_circular_file.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_CIRCULAR_FILE_H_ +#define _QA_GR_CIRCULAR_FILE_H_ + +#include +#include + +class qa_gr_circular_file : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_circular_file); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GR_CIRCULAR_FILE_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gr_firdes.cc b/gnuradio-core/src/lib/general/qa_gr_firdes.cc new file mode 100644 index 00000000..072bcb68 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_firdes.cc @@ -0,0 +1,344 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +using std::vector; + +static void +print_taps (std::ostream &s, vector &v) +{ + + for (unsigned int i = 0; i < v.size (); i++){ + printf ("tap[%2d] = %16.7e\n", i, v[i]); + } +} + +static void +check_symmetry (vector &v) +{ + int n = v.size (); + int m = n / 2; + + for (int i = 0; i < m; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (v[i], v[n - i - 1], 1e-9); +} + +const static float t1_exp[53] = { + -9.0525491e-04, + 2.0713841e-04, + 1.2388536e-03, + 2.9683491e-04, + -1.7744775e-03, + -1.3599906e-03, + 2.2031884e-03, + 3.2744040e-03, + -1.8868084e-03, + -5.9935520e-03, + 6.4301129e-18, + 8.9516686e-03, + 4.2178580e-03, + -1.0998557e-02, + -1.1173409e-02, + 1.0455756e-02, + 2.0686293e-02, + -5.2032238e-03, + -3.1896964e-02, + -7.4998410e-03, + 4.3362070e-02, + 3.2502845e-02, + -5.3328082e-02, + -8.5621715e-02, + 6.0117975e-02, + 3.1128189e-01, + 4.3769023e-01, + 3.1128189e-01, + 6.0117975e-02, + -8.5621715e-02, + -5.3328082e-02, + 3.2502845e-02, + 4.3362070e-02, + -7.4998410e-03, + -3.1896964e-02, + -5.2032238e-03, + 2.0686293e-02, + 1.0455756e-02, + -1.1173409e-02, + -1.0998557e-02, + 4.2178580e-03, + 8.9516686e-03, + 6.4301129e-18, + -5.9935520e-03, + -1.8868084e-03, + 3.2744040e-03, + 2.2031884e-03, + -1.3599906e-03, + -1.7744775e-03, + 2.9683491e-04, + 1.2388536e-03, + 2.0713841e-04, + -9.0525491e-04 +}; + +const static float t2_exp[53] = { + 9.0380036e-04, + -2.0680559e-04, + -1.2368630e-03, + -2.9635796e-04, + 1.7716263e-03, + 1.3578053e-03, + -2.1996482e-03, + -3.2691427e-03, + 1.8837767e-03, + 5.9839217e-03, + -6.4197810e-18, + -8.9372853e-03, + -4.2110807e-03, + 1.0980885e-02, + 1.1155456e-02, + -1.0438956e-02, + -2.0653054e-02, + 5.1948633e-03, + 3.1845711e-02, + 7.4877902e-03, + -4.3292396e-02, + -3.2450620e-02, + 5.3242393e-02, + 8.5484132e-02, + -6.0021374e-02, + -3.1078172e-01, + 5.6184036e-01, + -3.1078172e-01, + -6.0021374e-02, + 8.5484132e-02, + 5.3242393e-02, + -3.2450620e-02, + -4.3292396e-02, + 7.4877902e-03, + 3.1845711e-02, + 5.1948633e-03, + -2.0653054e-02, + -1.0438956e-02, + 1.1155456e-02, + 1.0980885e-02, + -4.2110807e-03, + -8.9372853e-03, + -6.4197810e-18, + 5.9839217e-03, + 1.8837767e-03, + -3.2691427e-03, + -2.1996482e-03, + 1.3578053e-03, + 1.7716263e-03, + -2.9635796e-04, + -1.2368630e-03, + -2.0680559e-04, + 9.0380036e-04 +}; + +const static float t3_exp[107] = { + -1.8970841e-06, + -7.1057165e-04, + 5.4005696e-04, + 4.6233178e-04, + 2.0572044e-04, + 3.5209916e-04, + -1.4098573e-03, + 1.1279077e-04, + -6.2994129e-04, + 1.1450432e-03, + 1.3637283e-03, + -6.4360141e-04, + 3.6509900e-04, + -3.2864159e-03, + 7.0192874e-04, + 3.7524730e-04, + 2.0256115e-03, + 3.0641893e-03, + -3.6618244e-03, + 7.5592739e-05, + -5.5586505e-03, + 2.3849572e-03, + 4.0114378e-03, + 1.6636450e-03, + 4.7835698e-03, + -1.0191196e-02, + -3.8158931e-04, + -5.5551580e-03, + 5.3901658e-03, + 1.1366769e-02, + -3.0000482e-03, + 4.9341680e-03, + -2.0093076e-02, + 5.5752542e-17, + 1.2093617e-03, + 8.6089745e-03, + 2.2382140e-02, + -1.6854567e-02, + 1.6913920e-03, + -3.1222520e-02, + 3.2711059e-03, + 2.2604836e-02, + 8.1451107e-03, + 3.7583180e-02, + -5.2293688e-02, + -8.0551542e-03, + -4.0092729e-02, + 1.5582236e-02, + 9.7452506e-02, + -1.6183170e-02, + 8.3281815e-02, + -2.8196752e-01, + -1.0965768e-01, + 5.2867508e-01, + -1.0965768e-01, + -2.8196752e-01, + 8.3281815e-02, + -1.6183170e-02, + 9.7452506e-02, + 1.5582236e-02, + -4.0092729e-02, + -8.0551542e-03, + -5.2293688e-02, + 3.7583180e-02, + 8.1451107e-03, + 2.2604836e-02, + 3.2711059e-03, + -3.1222520e-02, + 1.6913920e-03, + -1.6854567e-02, + 2.2382140e-02, + 8.6089745e-03, + 1.2093617e-03, + 5.5752542e-17, + -2.0093076e-02, + 4.9341680e-03, + -3.0000482e-03, + 1.1366769e-02, + 5.3901658e-03, + -5.5551580e-03, + -3.8158931e-04, + -1.0191196e-02, + 4.7835698e-03, + 1.6636450e-03, + 4.0114378e-03, + 2.3849572e-03, + -5.5586505e-03, + 7.5592739e-05, + -3.6618244e-03, + 3.0641893e-03, + 2.0256115e-03, + 3.7524730e-04, + 7.0192874e-04, + -3.2864159e-03, + 3.6509900e-04, + -6.4360141e-04, + 1.3637283e-03, + 1.1450432e-03, + -6.2994129e-04, + 1.1279077e-04, + -1.4098573e-03, + 3.5209916e-04, + 2.0572044e-04, + 4.6233178e-04, + 5.4005696e-04, + -7.1057165e-04, + -1.8970841e-06 +}; + + +void +qa_gr_firdes::t1 () +{ + vector taps = + gr_firdes::low_pass ( 1.0, + 8000, + 1750, + 500, + gr_firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size () << endl; + // print_taps (cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t1_exp), taps.size ()); + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t1_exp[i], taps[i], 1e-9); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t2 () +{ + vector taps = + gr_firdes::high_pass ( 1.0, + 8000, + 1750, + 500, + gr_firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size () << endl; + // print_taps (cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t2_exp), taps.size ()); + + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t2_exp[i], taps[i], 1e-9); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t3 () +{ + vector taps = + gr_firdes::band_pass ( 1.0, + 20e6, + 5.75e6 - (5.28e6/2), + 5.75e6 + (5.28e6/2), + 0.62e6, + gr_firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size () << endl; + // print_taps (cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t3_exp), taps.size ()); + + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t3_exp[i], taps[i], 1e-7); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t4 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_firdes.h b/gnuradio-core/src/lib/general/qa_gr_firdes.h new file mode 100644 index 00000000..8fb4d5a3 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_firdes.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_FIRDES_H_ +#define _QA_GR_FIRDES_H_ + +#include +#include + +class qa_gr_firdes : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_firdes); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + void t2 (); + void t3 (); + void t4 (); + +}; + + +#endif /* _QA_GR_FIRDES_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt.cc b/gnuradio-core/src/lib/general/qa_gr_fxpt.cc new file mode 100644 index 00000000..6cd582ad --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt.cc @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +static const float SIN_COS_TOLERANCE = 1e-5; + +void +qa_gr_fxpt::t0 () +{ + CPPUNIT_ASSERT_DOUBLES_EQUAL (M_PI/2, gr_fxpt::fixed_to_float (0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, gr_fxpt::fixed_to_float (0x00000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (-M_PI, gr_fxpt::fixed_to_float (0x80000000), SIN_COS_TOLERANCE); + + if (0){ + /* + * These are disabled because of some precision issues. + * + * Different compilers seem to have different opinions on whether + * the calulations are done single or double (or extended) + * precision. Any of the answers are fine for our real purpose, but + * sometimes the answer is off by a few bits at the bottom. + * Hence, the disabled check. + */ + CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x40000000, gr_fxpt::float_to_fixed (M_PI/2)); + CPPUNIT_ASSERT_EQUAL ((gr_int32) 0, gr_fxpt::float_to_fixed (0)); + CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x80000000, gr_fxpt::float_to_fixed (-M_PI)); + } +} + +void +qa_gr_fxpt::t1 () +{ + + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x00000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x20000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 1, gr_fxpt::sin (0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x60000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x7fffffff), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000001), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (-1, gr_fxpt::sin (-0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (-0.707106781, gr_fxpt::sin (-0x20000000), SIN_COS_TOLERANCE); + + + for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ + float expected = sin (p); + float actual = gr_fxpt::sin (gr_fxpt::float_to_fixed (p)); + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE); + } +} + +void +qa_gr_fxpt::t2 () +{ + for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ + float expected = cos (p); + float actual = gr_fxpt::cos (gr_fxpt::float_to_fixed (p)); + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE); + } +} + +void +qa_gr_fxpt::t3 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt.h b/gnuradio-core/src/lib/general/qa_gr_fxpt.h new file mode 100644 index 00000000..a21be5cc --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_QA_GR_FXPT_H +#define INCLUDED_QA_GR_FXPT_H + + +#include +#include + +class qa_gr_fxpt : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fxpt); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_FXPT_H */ + + diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc new file mode 100644 index 00000000..5b774fb8 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +static const float SIN_COS_TOLERANCE = 1e-5; + +//static const float SIN_COS_FREQ = 5003; +static const float SIN_COS_FREQ = 4096; + +static const int SIN_COS_BLOCK_SIZE = 100000; + +static double max_d(double a, double b) +{ + return fabs(a) > fabs(b) ? a : b; +} + +void +qa_gr_fxpt_nco::t0 () +{ + gr_nco ref_nco; + gr_fxpt_nco new_nco; + double max_error = 0, max_phase_error = 0; + + ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + float ref_sin = ref_nco.sin (); + float new_sin = new_nco.sin (); + //printf ("i = %6d\n", i); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_sin, new_sin, SIN_COS_TOLERANCE); + + max_error = max_d (max_error, ref_sin-new_sin); + + float ref_cos = ref_nco.cos (); + float new_cos = new_nco.cos (); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE); + + max_error = max_d (max_error, ref_cos-new_cos); + + ref_nco.step (); + new_nco.step (); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE); + + max_phase_error = max_d (max_phase_error, ref_nco.get_phase()-new_nco.get_phase()); + } + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); +} + +void +qa_gr_fxpt_nco::t1 () +{ + gr_nco ref_nco; + gr_fxpt_nco new_nco; + gr_complex ref_block[SIN_COS_BLOCK_SIZE]; + gr_complex new_block[SIN_COS_BLOCK_SIZE]; + double max_error = 0; + + ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); + + ref_nco.sincos ((gr_complex*)ref_block, SIN_COS_BLOCK_SIZE); + new_nco.sincos ((gr_complex*)new_block, SIN_COS_BLOCK_SIZE); + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].real(), new_block[i].real(), SIN_COS_TOLERANCE); + max_error = max_d (max_error, ref_block[i].real()-new_block[i].real()); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].imag(), new_block[i].imag(), SIN_COS_TOLERANCE); + max_error = max_d (max_error, ref_block[i].imag()-new_block[i].imag()); + } + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE); + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); +} + +void +qa_gr_fxpt_nco::t2 () +{ +} + +void +qa_gr_fxpt_nco::t3 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h new file mode 100644 index 00000000..3d0c84a0 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_QA_GR_FXPT_NCO_H +#define INCLUDED_QA_GR_FXPT_NCO_H + + +#include +#include + +class qa_gr_fxpt_nco : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fxpt_nco); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_FXPT_NCO_H */ + + diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc new file mode 100644 index 00000000..70c2da36 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +static const float SIN_COS_TOLERANCE = 1e-5; + +static const float SIN_COS_K = 0.42; +static const float SIN_COS_AMPL = 0.8; + +static const int SIN_COS_BLOCK_SIZE = 100000; + +static double max_d(double a, double b) +{ + return fabs(a) > fabs(b) ? a : b; +} + +void +qa_gr_fxpt_vco::t0 () +{ + gr_vco ref_vco; + gr_fxpt_vco new_vco; + double max_error = 0, max_phase_error = 0; + float input[SIN_COS_BLOCK_SIZE]; + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + input[i] = sin(i); + } + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + float ref_cos = ref_vco.cos (); + float new_cos = new_vco.cos (); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE); + + max_error = max_d (max_error, ref_cos-new_cos); + + ref_vco.adjust_phase (input[i]); + new_vco.adjust_phase (input[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); + + max_phase_error = max_d (max_phase_error, ref_vco.get_phase()-new_vco.get_phase()); + } + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); +} + + +void +qa_gr_fxpt_vco::t1 () +{ + gr_vco ref_vco; + gr_fxpt_vco new_vco; + float ref_block[SIN_COS_BLOCK_SIZE]; + float new_block[SIN_COS_BLOCK_SIZE]; + float input[SIN_COS_BLOCK_SIZE]; + double max_error = 0; + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + input[i] = sin(i); + } + + ref_vco.cos (ref_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); + new_vco.cos (new_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i], new_block[i], SIN_COS_TOLERANCE); + max_error = max_d (max_error, ref_block[i]-new_block[i]); + } + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, ref_vco.get_phase()-new_vco.get_phase()); +} + +void +qa_gr_fxpt_vco::t2 () +{ +} + +void +qa_gr_fxpt_vco::t3 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h new file mode 100644 index 00000000..80ea0253 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_QA_GR_FXPT_VCO_H +#define INCLUDED_QA_GR_FXPT_VCO_H + + +#include +#include + +class qa_gr_fxpt_vco : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fxpt_vco); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_FXPT_VCO_H */ + + diff --git a/gnuradio-core/src/lib/general/random.h b/gnuradio-core/src/lib/general/random.h new file mode 100644 index 00000000..816aca34 --- /dev/null +++ b/gnuradio-core/src/lib/general/random.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _RANDOM_H_ +#define _RANDOM_H_ + +// we use this because some systems (solaris) define RAND_MAX as 32767 + +static const int RANDOM_MAX = 2147483647; + +#include + +#endif // _RANDOM_H_ diff --git a/gnuradio-core/src/lib/general/sine_table.h b/gnuradio-core/src/lib/general/sine_table.h new file mode 100644 index 00000000..69834943 --- /dev/null +++ b/gnuradio-core/src/lib/general/sine_table.h @@ -0,0 +1,1025 @@ + // max_error = 2.353084136763606e-06 + { 2.925817799165007e-09, 7.219194364267018e-09 }, + { 2.925707643778599e-09, 2.526699001579799e-07 }, + { 2.925487337153070e-09, 1.191140162167675e-06 }, + { 2.925156887582842e-09, 3.284585035595589e-06 }, + { 2.924716307509151e-09, 6.994872605695784e-06 }, + { 2.924165613519592e-09, 1.278374920658798e-05 }, + { 2.923504826347475e-09, 2.111280464718590e-05 }, + { 2.922733970871080e-09, 3.244343744537165e-05 }, + { 2.921853076112655e-09, 4.723682007436170e-05 }, + { 2.920862175237416e-09, 6.595386421935634e-05 }, + { 2.919761305552202e-09, 8.905518605213658e-05 }, + { 2.918550508504146e-09, 1.170010715193098e-04 }, + { 2.917229829679050e-09, 1.502514416517192e-04 }, + { 2.915799318799769e-09, 1.892658178912071e-04 }, + { 2.914259029724184e-09, 2.345032874456615e-04 }, + { 2.912609020443340e-09, 2.864224686607020e-04 }, + { 2.910849353079123e-09, 3.454814764261432e-04 }, + { 2.908980093882049e-09, 4.121378876027343e-04 }, + { 2.907001313228646e-09, 4.868487064877691e-04 }, + { 2.904913085618902e-09, 5.700703303049837e-04 }, + { 2.902715489673383e-09, 6.622585147355725e-04 }, + { 2.900408608130373e-09, 7.638683394782519e-04 }, + { 2.897992527842612e-09, 8.753541738578119e-04 }, + { 2.895467339774186e-09, 9.971696424604937e-04 }, + { 2.892833138996999e-09, 1.129767590823255e-03 }, + { 2.890090024687216e-09, 1.273600051161478e-03 }, + { 2.887238100121550e-09, 1.429118208142094e-03 }, + { 2.884277472673313e-09, 1.596772364709564e-03 }, + { 2.881208253808507e-09, 1.777011907950626e-03 }, + { 2.878030559081432e-09, 1.970285275029487e-03 }, + { 2.874744508130554e-09, 2.177039919152579e-03 }, + { 2.871350224673798e-09, 2.397722275614272e-03 }, + { 2.867847836504030e-09, 2.632777727878843e-03 }, + { 2.864237475484149e-09, 2.882650573737405e-03 }, + { 2.860519277542297e-09, 3.147783991507308e-03 }, + { 2.856693382666432e-09, 3.428620006328931e-03 }, + { 2.852759934899389e-09, 3.725599456482154e-03 }, + { 2.848719082333207e-09, 4.039161959812243e-03 }, + { 2.844570977103752e-09, 4.369745880190706e-03 }, + { 2.840315775384800e-09, 4.717788294077374e-03 }, + { 2.835953637382310e-09, 5.083724957128360e-03 }, + { 2.831484727328322e-09, 5.467990270896617e-03 }, + { 2.826909213474759e-09, 5.871017249604038e-03 }, + { 2.822227268087134e-09, 6.293237486988512e-03 }, + { 2.817439067438018e-09, 6.735081123237729e-03 }, + { 2.812544791800534e-09, 7.196976811989608e-03 }, + { 2.807544625441273e-09, 7.679351687456759e-03 }, + { 2.802438756613836e-09, 8.182631331563162e-03 }, + { 2.797227377551135e-09, 8.707239741274575e-03 }, + { 2.791910684458716e-09, 9.253599295902304e-03 }, + { 2.786488877507140e-09, 9.822130724578715e-03 }, + { 2.780962160824228e-09, 1.041325307382490e-02 }, + { 2.775330742487884e-09, 1.102738367513773e-02 }, + { 2.769594834517682e-09, 1.166493811278924e-02 }, + { 2.763754652867477e-09, 1.232633019159818e-02 }, + { 2.757810417416620e-09, 1.301197190494069e-02 }, + { 2.751762351962413e-09, 1.372227340270610e-02 }, + { 2.745610684210923e-09, 1.445764295952962e-02 }, + { 2.739355645769094e-09, 1.521848694296229e-02 }, + { 2.732997472135539e-09, 1.600520978188769e-02 }, + { 2.726536402691907e-09, 1.681821393496225e-02 }, + { 2.719972680693777e-09, 1.765789985920713e-02 }, + { 2.713306553261610e-09, 1.852466597868779e-02 }, + { 2.706538271371373e-09, 1.941890865333146e-02 }, + { 2.699668089844909e-09, 2.034102214787814e-02 }, + { 2.692696267340880e-09, 2.129139860085272e-02 }, + { 2.685623066344263e-09, 2.227042799383416e-02 }, + { 2.678448753157212e-09, 2.327849812064098e-02 }, + { 2.671173597888530e-09, 2.431599455681316e-02 }, + { 2.663797874443630e-09, 2.538330062913108e-02 }, + { 2.656321860514457e-09, 2.648079738524795e-02 }, + { 2.648745837568575e-09, 2.760886356354952e-02 }, + { 2.641070090839117e-09, 2.876787556300114e-02 }, + { 2.633294909313421e-09, 2.995820741329835e-02 }, + { 2.625420585722845e-09, 3.118023074495535e-02 }, + { 2.617447416531143e-09, 3.243431475972608e-02 }, + { 2.609375701923643e-09, 3.372082620101990e-02 }, + { 2.601205745795833e-09, 3.504012932452527e-02 }, + { 2.592937855741933e-09, 3.639258586895711e-02 }, + { 2.584572343043400e-09, 3.777855502693250e-02 }, + { 2.576109522656942e-09, 3.919839341605197e-02 }, + { 2.567549713203028e-09, 4.065245505002102e-02 }, + { 2.558893236953688e-09, 4.214109131001403e-02 }, + { 2.550140419820252e-09, 4.366465091617666e-02 }, + { 2.541291591341445e-09, 4.522347989919473e-02 }, + { 2.532347084670572e-09, 4.681792157215026e-02 }, + { 2.523307236563343e-09, 4.844831650239501e-02 }, + { 2.514172387364900e-09, 5.011500248369893e-02 }, + { 2.504942880997064e-09, 5.181831450849345e-02 }, + { 2.495619064945627e-09, 5.355858474024022e-02 }, + { 2.486201290246928e-09, 5.533614248606705e-02 }, + { 2.476689911475047e-09, 5.715131416942842e-02 }, + { 2.467085286727668e-09, 5.900442330315692e-02 }, + { 2.457387777613798e-09, 6.089579046229943e-02 }, + { 2.447597749239101e-09, 6.282573325755320e-02 }, + { 2.437715570192557e-09, 6.479456630859221e-02 }, + { 2.427741612532542e-09, 6.680260121764925e-02 }, + { 2.417676251773166e-09, 6.885014654319160e-02 }, + { 2.407519866869294e-09, 7.093750777401114e-02 }, + { 2.397272840203310e-09, 7.306498730310884e-02 }, + { 2.386935557569868e-09, 7.523288440214027e-02 }, + { 2.376508408161815e-09, 7.744149519577415e-02 }, + { 2.365991784555363e-09, 7.969111263635709e-02 }, + { 2.355386082695641e-09, 8.198202647865405e-02 }, + { 2.344691701881232e-09, 8.431452325495814e-02 }, + { 2.333909044749407e-09, 8.668888625021409e-02 }, + { 2.323038517261246e-09, 8.910539547731611e-02 }, + { 2.312080528685971e-09, 9.156432765274414e-02 }, + { 2.301035491585642e-09, 9.406595617227698e-02 }, + { 2.289903821799651e-09, 9.661055108691619e-02 }, + { 2.278685938428940e-09, 9.919837907903295e-02 }, + { 2.267382263820762e-09, 1.018297034385580e-01 }, + { 2.255993223551837e-09, 1.045047840397028e-01 }, + { 2.244519246413220e-09, 1.072238773174577e-01 }, + { 2.232960764393620e-09, 1.099872362446146e-01 }, + { 2.221318212663309e-09, 1.127951103088245e-01 }, + { 2.209592029557811e-09, 1.156477454898748e-01 }, + { 2.197782656561395e-09, 1.185453842371912e-01 }, + { 2.185890538290176e-09, 1.214882654476019e-01 }, + { 2.173916122475606e-09, 1.244766244431883e-01 }, + { 2.161859859947797e-09, 1.275106929493488e-01 }, + { 2.149722204618256e-09, 1.305906990731841e-01 }, + { 2.137503613462743e-09, 1.337168672820376e-01 }, + { 2.125204546504321e-09, 1.368894183821595e-01 }, + { 2.112825466795944e-09, 1.401085694976751e-01 }, + { 2.100366840402933e-09, 1.433745340497602e-01 }, + { 2.087829136385612e-09, 1.466875217359607e-01 }, + { 2.075212826781308e-09, 1.500477385098620e-01 }, + { 2.062518386587093e-09, 1.534553865607503e-01 }, + { 2.049746293741359e-09, 1.569106642937665e-01 }, + { 2.036897029106193e-09, 1.604137663100403e-01 }, + { 2.023971076449323e-09, 1.639648833871233e-01 }, + { 2.010968922425217e-09, 1.675642024598467e-01 }, + { 1.997891056557933e-09, 1.712119066008896e-01 }, + { 1.984737971221581e-09, 1.749081750021970e-01 }, + { 1.971510161622434e-09, 1.786531829561379e-01 }, + { 1.958208125780130e-09, 1.824471018371070e-01 }, + { 1.944832364508511e-09, 1.862900990834311e-01 }, + { 1.931383381397782e-09, 1.901823381790926e-01 }, + { 1.917861682794392e-09, 1.941239786363039e-01 }, + { 1.904267777782611e-09, 1.981151759777950e-01 }, + { 1.890602178165317e-09, 2.021560817195309e-01 }, + { 1.876865398444616e-09, 2.062468433536743e-01 }, + { 1.863057955802572e-09, 2.103876043317229e-01 }, + { 1.849180370081465e-09, 2.145785040479915e-01 }, + { 1.835233163764673e-09, 2.188196778231083e-01 }, + { 1.821216861956509e-09, 2.231112568880342e-01 }, + { 1.807131992362945e-09, 2.274533683680190e-01 }, + { 1.792979085271234e-09, 2.318461352671018e-01 }, + { 1.778758673530482e-09, 2.362896764525300e-01 }, + { 1.764471292530943e-09, 2.407841066397789e-01 }, + { 1.750117480184598e-09, 2.453295363773890e-01 }, + { 1.735697776904342e-09, 2.499260720324433e-01 }, + { 1.721212725583874e-09, 2.545738157760434e-01 }, + { 1.706662871577097e-09, 2.592728655691494e-01 }, + { 1.692048762677849e-09, 2.640233151485341e-01 }, + { 1.677370949099090e-09, 2.688252540131204e-01 }, + { 1.662629983452104e-09, 2.736787674105404e-01 }, + { 1.647826420726167e-09, 2.785839363237506e-01 }, + { 1.632960818266680e-09, 2.835408374583758e-01 }, + { 1.618033735755429e-09, 2.885495432295704e-01 }, + { 1.603045735188609e-09, 2.936101217498361e-01 }, + { 1.587997380855918e-09, 2.987226368167127e-01 }, + { 1.572889239319430e-09, 3.038871479007593e-01 }, + { 1.557721879392051e-09, 3.091037101339017e-01 }, + { 1.542495872116447e-09, 3.143723742978435e-01 }, + { 1.527211790743024e-09, 3.196931868130269e-01 }, + { 1.511870210708909e-09, 3.250661897274744e-01 }, + { 1.496471709615926e-09, 3.304914207062036e-01 }, + { 1.481016867208896e-09, 3.359689130207621e-01 }, + { 1.465506265353924e-09, 3.414986955389885e-01 }, + { 1.449940488016384e-09, 3.470807927151147e-01 }, + { 1.434320121238994e-09, 3.527152245800635e-01 }, + { 1.418645753119802e-09, 3.584020067320109e-01 }, + { 1.402917973789838e-09, 3.641411503272979e-01 }, + { 1.387137375391042e-09, 3.699326620714776e-01 }, + { 1.371304552054134e-09, 3.757765442106153e-01 }, + { 1.355420099875958e-09, 3.816727945230153e-01 }, + { 1.339484616897137e-09, 3.876214063110671e-01 }, + { 1.323498703079580e-09, 3.936223683933865e-01 }, + { 1.307462960283922e-09, 3.996756650972121e-01 }, + { 1.291377992246768e-09, 4.057812762511174e-01 }, + { 1.275244404558188e-09, 4.119391771778626e-01 }, + { 1.259062804638585e-09, 4.181493386877248e-01 }, + { 1.242833801715929e-09, 4.244117270719281e-01 }, + { 1.226558006803155e-09, 4.307263040962509e-01 }, + { 1.210236032674760e-09, 4.370930269951803e-01 }, + { 1.193868493843725e-09, 4.435118484661861e-01 }, + { 1.177456006538695e-09, 4.499827166641340e-01 }, + { 1.160999188680582e-09, 4.565055751961679e-01 }, + { 1.144498659859216e-09, 4.630803631168164e-01 }, + { 1.127955041310214e-09, 4.697070149232604e-01 }, + { 1.111368955891417e-09, 4.763854605510119e-01 }, + { 1.094741028059551e-09, 4.831156253697562e-01 }, + { 1.078071883846871e-09, 4.898974301794375e-01 }, + { 1.061362150836978e-09, 4.967307912069362e-01 }, + { 1.044612458142151e-09, 5.036156201023686e-01 }, + { 1.027823436378632e-09, 5.105518239364775e-01 }, + { 1.010995717643647e-09, 5.175393051975563e-01 }, + { 9.941299354913699e-10, 5.245779617890562e-01 }, + { 9.772267249089968e-10, 5.316676870274011e-01 }, + { 9.602867222926046e-10, 5.388083696401416e-01 }, + { 9.433105654240147e-10, 5.459998937639375e-01 }, + { 9.262988934458084e-10, 5.532421389435711e-01 }, + { 9.092523468378193e-10, 5.605349801305876e-01 }, + { 8.921715673928355e-10, 5.678782876825250e-01 }, + { 8.750571981926701e-10, 5.752719273622372e-01 }, + { 8.579098835836508e-10, 5.827157603377209e-01 }, + { 8.407302691522673e-10, 5.902096431821322e-01 }, + { 8.235190017016133e-10, 5.977534278737073e-01 }, + { 8.062767292259225e-10, 6.053469617967722e-01 }, + { 7.890041008871165e-10, 6.129900877421282e-01 }, + { 7.717017669898175e-10, 6.206826439083659e-01 }, + { 7.543703789572603e-10, 6.284244639030392e-01 }, + { 7.370105893063053e-10, 6.362153767444958e-01 }, + { 7.196230516231919e-10, 6.440552068636356e-01 }, + { 7.022084205389746e-10, 6.519437741060674e-01 }, + { 6.847673517046416e-10, 6.598808937346672e-01 }, + { 6.673005017664976e-10, 6.678663764322770e-01 }, + { 6.498085283416530e-10, 6.759000283046127e-01 }, + { 6.322920899929834e-10, 6.839816508836737e-01 }, + { 6.147518462045659e-10, 6.921110411311926e-01 }, + { 5.971884573565851e-10, 7.002879914425926e-01 }, + { 5.796025847007168e-10, 7.085122896509806e-01 }, + { 5.619948903351406e-10, 7.167837190315758e-01 }, + { 5.443660371796048e-10, 7.251020583063744e-01 }, + { 5.267166889504394e-10, 7.334670816491009e-01 }, + { 5.090475101356742e-10, 7.418785586903696e-01 }, + { 4.913591659698399e-10, 7.503362545232619e-01 }, + { 4.736523224091392e-10, 7.588399297089872e-01 }, + { 4.559276461062478e-10, 7.673893402829834e-01 }, + { 4.381858043851147e-10, 7.759842377612828e-01 }, + { 4.204274652161870e-10, 7.846243691469355e-01 }, + { 4.026532971908398e-10, 7.933094769370790e-01 }, + { 3.848639694963359e-10, 8.020392991300200e-01 }, + { 3.670601518910503e-10, 8.108135692324444e-01 }, + { 3.492425146784233e-10, 8.196320162675177e-01 }, + { 3.314117286825031e-10, 8.284943647824689e-01 }, + { 3.135684652223755e-10, 8.374003348569865e-01 }, + { 2.957133960867535e-10, 8.463496421118015e-01 }, + { 2.778471935089361e-10, 8.553419977173513e-01 }, + { 2.599705301412391e-10, 8.643771084029740e-01 }, + { 2.420840790301135e-10, 8.734546764660205e-01 }, + { 2.241885135902046e-10, 8.825743997817682e-01 }, + { 2.062845075795238e-10, 8.917359718130367e-01 }, + { 1.883727350736140e-10, 9.009390816205823e-01 }, + { 1.704538704408269e-10, 9.101834138731877e-01 }, + { 1.525285883160648e-10, 9.194686488588080e-01 }, + { 1.345975635762696e-10, 9.287944624950824e-01 }, + { 1.166614713141648e-10, 9.381605263410157e-01 }, + { 9.872098681369190e-11, 9.475665076080466e-01 }, + { 8.077678552380464e-11, 9.570120691722380e-01 }, + { 6.282954303364090e-11, 9.664968695860140e-01 }, + { 4.487993504668797e-11, 9.760205630906909e-01 }, + { 2.692863735553042e-11, 9.855827996289697e-01 }, + { 8.976325816439114e-12, 9.951832248577780e-01 }, + { -8.976323676304494e-12, 1.004821480161519e+00 }, + { -2.692863521550168e-11, 1.014497202665280e+00 }, + { -4.487993290681805e-11, 1.024210025248670e+00 }, + { -6.282954089398273e-11, 1.033959576559617e+00 }, + { -8.077678338451706e-11, 1.043745481028715e+00 }, + { -9.872098467477489e-11, 1.053567358883467e+00 }, + { -1.166614691757772e-10, 1.063424826163223e+00 }, + { -1.345975614383584e-10, 1.073317494734013e+00 }, + { -1.525285861788948e-10, 1.083244972303963e+00 }, + { -1.704538683042922e-10, 1.093206862438572e+00 }, + { -1.883727329379793e-10, 1.103202764576806e+00 }, + { -2.062845054446831e-10, 1.113232274046796e+00 }, + { -2.241885114563697e-10, 1.123294982082432e+00 }, + { -2.420840768973375e-10, 1.133390475839767e+00 }, + { -2.599705280096278e-10, 1.143518338413855e+00 }, + { -2.778471913784365e-10, 1.153678148855860e+00 }, + { -2.957133939575774e-10, 1.163869482190458e+00 }, + { -3.135684630945758e-10, 1.174091909433296e+00 }, + { -3.314117265561857e-10, 1.184344997608959e+00 }, + { -3.492425125535882e-10, 1.194628309769018e+00 }, + { -3.670601497678034e-10, 1.204941405010466e+00 }, + { -3.848639673748360e-10, 1.215283838494269e+00 }, + { -4.026532950710339e-10, 1.225655161464298e+00 }, + { -4.204274630982869e-10, 1.236054921266445e+00 }, + { -4.381858022691734e-10, 1.246482661367958e+00 }, + { -4.559276439922654e-10, 1.256937921377146e+00 }, + { -4.736523202972214e-10, 1.267420237063216e+00 }, + { -4.913591638600925e-10, 1.277929140376502e+00 }, + { -5.090475080282032e-10, 1.288464159468706e+00 }, + { -5.267166868452449e-10, 1.299024818713528e+00 }, + { -5.443660350768455e-10, 1.309610638727845e+00 }, + { -5.619948882348695e-10, 1.320221136392390e+00 }, + { -5.796025826029868e-10, 1.330855824873457e+00 }, + { -5.971884552615020e-10, 1.341514213644420e+00 }, + { -6.147518441122357e-10, 1.352195808507556e+00 }, + { -6.322920879034590e-10, 1.362900111616144e+00 }, + { -6.498085262549874e-10, 1.373626621496939e+00 }, + { -6.673004996827436e-10, 1.384374833072571e+00 }, + { -6.847673496239581e-10, 1.395144237684605e+00 }, + { -7.022084184613616e-10, 1.405934323116231e+00 }, + { -7.196230495488082e-10, 1.416744573616104e+00 }, + { -7.370105872352039e-10, 1.427574469921397e+00 }, + { -7.543703768894941e-10, 1.438423489281758e+00 }, + { -7.717017649255453e-10, 1.449291105483472e+00 }, + { -7.890040988262324e-10, 1.460176788873383e+00 }, + { -8.062767271686383e-10, 1.471080006383765e+00 }, + { -8.235189996479819e-10, 1.482000221556656e+00 }, + { -8.407302671024475e-10, 1.492936894569018e+00 }, + { -8.579098815375368e-10, 1.503889482257845e+00 }, + { -8.750571961505266e-10, 1.514857438145604e+00 }, + { -8.921715653546624e-10, 1.525840212465756e+00 }, + { -9.092523448036167e-10, 1.536837252188703e+00 }, + { -9.262988914157881e-10, 1.547848001047890e+00 }, + { -9.433105633981766e-10, 1.558871899565883e+00 }, + { -9.602867202711075e-10, 1.569908385081254e+00 }, + { -9.772267228916820e-10, 1.580956891774897e+00 }, + { -9.941299334786078e-10, 1.592016850697478e+00 }, + { -1.010995715635332e-09, 1.603087689796053e+00 }, + { -1.027823434374870e-09, 1.614168833942028e+00 }, + { -1.044612456143047e-09, 1.625259704958335e+00 }, + { -1.061362148842745e-09, 1.636359721647526e+00 }, + { -1.078071881857297e-09, 1.647468299819543e+00 }, + { -1.094741026074900e-09, 1.658584852320419e+00 }, + { -1.111368953911690e-09, 1.669708789060341e+00 }, + { -1.127955039335462e-09, 1.680839517042381e+00 }, + { -1.144498657889600e-09, 1.691976440391624e+00 }, + { -1.160999186716154e-09, 1.703118960383971e+00 }, + { -1.177456004579561e-09, 1.714266475475616e+00 }, + { -1.193868491889832e-09, 1.725418381332405e+00 }, + { -1.210236030726319e-09, 1.736574070859850e+00 }, + { -1.226558004860220e-09, 1.747732934232508e+00 }, + { -1.242833799778447e-09, 1.758894358924547e+00 }, + { -1.259062802706714e-09, 1.770057729740021e+00 }, + { -1.275244402631982e-09, 1.781222428842935e+00 }, + { -1.291377990326492e-09, 1.792387835788660e+00 }, + { -1.307462958369363e-09, 1.803553327553897e+00 }, + { -1.323498701170897e-09, 1.814718278568759e+00 }, + { -1.339484614994490e-09, 1.825882060747428e+00 }, + { -1.355420097979292e-09, 1.837044043519582e+00 }, + { -1.371304550163662e-09, 1.848203593862598e+00 }, + { -1.387137373506711e-09, 1.859360076332671e+00 }, + { -1.402917971911754e-09, 1.870512853097495e+00 }, + { -1.418645751248018e-09, 1.881661283967967e+00 }, + { -1.434320119373722e-09, 1.892804726431080e+00 }, + { -1.449940486157623e-09, 1.903942535681972e+00 }, + { -1.465506263501516e-09, 1.915074064656886e+00 }, + { -1.481016865363264e-09, 1.926198664066737e+00 }, + { -1.496471707776859e-09, 1.937315682428795e+00 }, + { -1.511870208876724e-09, 1.948424466101625e+00 }, + { -1.527211788917509e-09, 1.959524359317042e+00 }, + { -1.542495870297867e-09, 1.970614704215133e+00 }, + { -1.557721877580406e-09, 1.981694840876775e+00 }, + { -1.572889237514880e-09, 1.992764107358707e+00 }, + { -1.587997379058514e-09, 2.003821839726753e+00 }, + { -1.603045733398246e-09, 2.014867372090665e+00 }, + { -1.618033733972424e-09, 2.025900036638798e+00 }, + { -1.632960816490822e-09, 2.036919163671778e+00 }, + { -1.647826418957721e-09, 2.047924081638631e+00 }, + { -1.662629981691070e-09, 2.058914117170269e+00 }, + { -1.677370947345626e-09, 2.069888595116115e+00 }, + { -1.692048760931849e-09, 2.080846838577820e+00 }, + { -1.706662869838827e-09, 2.091788168946183e+00 }, + { -1.721212723853279e-09, 2.102711905935372e+00 }, + { -1.735697775181424e-09, 2.113617367619504e+00 }, + { -1.750117478469621e-09, 2.124503870468520e+00 }, + { -1.764471290823748e-09, 2.135370729383332e+00 }, + { -1.778758671831281e-09, 2.146217257733207e+00 }, + { -1.792979083579974e-09, 2.157042767390815e+00 }, + { -1.807131990679890e-09, 2.167846568770014e+00 }, + { -1.821216860281448e-09, 2.178627970860822e+00 }, + { -1.835233162097977e-09, 2.189386281268046e+00 }, + { -1.849180368423027e-09, 2.200120806246095e+00 }, + { -1.863057954152340e-09, 2.210830850737588e+00 }, + { -1.876865396802907e-09, 2.221515718409926e+00 }, + { -1.890602176531920e-09, 2.232174711691990e+00 }, + { -1.904267776157843e-09, 2.242807131812679e+00 }, + { -1.917861681178094e-09, 2.253412278837029e+00 }, + { -1.931383379790273e-09, 2.263989451705295e+00 }, + { -1.944832362909578e-09, 2.274537948269257e+00 }, + { -1.958208124189984e-09, 2.285057065331676e+00 }, + { -1.971510160041235e-09, 2.295546098682665e+00 }, + { -1.984737969649064e-09, 2.306004343138794e+00 }, + { -1.997891054994522e-09, 2.316431092581699e+00 }, + { -2.010968920870647e-09, 2.326825639994779e+00 }, + { -2.023971074903858e-09, 2.337187277503834e+00 }, + { -2.036897027569834e-09, 2.347515296413520e+00 }, + { -2.049746292214264e-09, 2.357808987247877e+00 }, + { -2.062518385069210e-09, 2.368067639787542e+00 }, + { -2.075212825272584e-09, 2.378290543109652e+00 }, + { -2.087829134886364e-09, 2.388476985626922e+00 }, + { -2.100366838912949e-09, 2.398626255125417e+00 }, + { -2.112825465315542e-09, 2.408737638805759e+00 }, + { -2.125204545033289e-09, 2.418810423320288e+00 }, + { -2.137503612001452e-09, 2.428843894814472e+00 }, + { -2.149722203166389e-09, 2.438837338964302e+00 }, + { -2.161859858505829e-09, 2.448790041018174e+00 }, + { -2.173916121043380e-09, 2.458701285834241e+00 }, + { -2.185890536867478e-09, 2.468570357921585e+00 }, + { -2.197782655148702e-09, 2.478396541480230e+00 }, + { -2.209592028154913e-09, 2.488179120439544e+00 }, + { -2.221318211270522e-09, 2.497917378500214e+00 }, + { -2.232960763010574e-09, 2.507610599172123e+00 }, + { -2.244519245040444e-09, 2.517258065817044e+00 }, + { -2.255993222189014e-09, 2.526859061686102e+00 }, + { -2.267382262468209e-09, 2.536412869962689e+00 }, + { -2.278685937086658e-09, 2.545918773800664e+00 }, + { -2.289903820467374e-09, 2.555376056366064e+00 }, + { -2.301035490263848e-09, 2.564784000877677e+00 }, + { -2.312080527374447e-09, 2.574141890646339e+00 }, + { -2.323038515960257e-09, 2.583449009117307e+00 }, + { -2.333909043458635e-09, 2.592704639909166e+00 }, + { -2.344691700601153e-09, 2.601908066856634e+00 }, + { -2.355386081425938e-09, 2.611058574048749e+00 }, + { -2.365991783296513e-09, 2.620155445872768e+00 }, + { -2.376508406913500e-09, 2.629197967052127e+00 }, + { -2.386935556332088e-09, 2.638185422689490e+00 }, + { -2.397272838976436e-09, 2.647117098307332e+00 }, + { -2.407519865653114e-09, 2.655992279887846e+00 }, + { -2.417676250567891e-09, 2.664810253915885e+00 }, + { -2.427741611338014e-09, 2.673570307418169e+00 }, + { -2.437715569009093e-09, 2.682271728006635e+00 }, + { -2.447597748066437e-09, 2.690913803917100e+00 }, + { -2.457387776452357e-09, 2.699495824053297e+00 }, + { -2.467085285577292e-09, 2.708017078025636e+00 }, + { -2.476689910335470e-09, 2.716476856194105e+00 }, + { -2.486201289118733e-09, 2.724874449709689e+00 }, + { -2.495619063828443e-09, 2.733209150554255e+00 }, + { -2.504942879891263e-09, 2.741480251583985e+00 }, + { -2.514172386270163e-09, 2.749687046568741e+00 }, + { -2.523307235480146e-09, 2.757828830235740e+00 }, + { -2.532347083598520e-09, 2.765904898308531e+00 }, + { -2.541291590280960e-09, 2.773914547551261e+00 }, + { -2.550140418771202e-09, 2.781857075807392e+00 }, + { -2.558893235915887e-09, 2.789731782043156e+00 }, + { -2.567549712176927e-09, 2.797537966388929e+00 }, + { -2.576109521642196e-09, 2.805274930179221e+00 }, + { -2.584572342040407e-09, 2.812941975996573e+00 }, + { -2.592937854750428e-09, 2.820538407710556e+00 }, + { -2.601205744816134e-09, 2.828063530521908e+00 }, + { -2.609375700955458e-09, 2.835516651001539e+00 }, + { -2.617447415574869e-09, 2.842897077134583e+00 }, + { -2.625420584778350e-09, 2.850204118359573e+00 }, + { -2.633294908380520e-09, 2.857437085611509e+00 }, + { -2.641070089918234e-09, 2.864595291363663e+00 }, + { -2.648745836659391e-09, 2.871678049666939e+00 }, + { -2.656321859617343e-09, 2.878684676194483e+00 }, + { -2.663797873558322e-09, 2.885614488280000e+00 }, + { -2.671173597015318e-09, 2.892466804962122e+00 }, + { -2.678448752295859e-09, 2.899240947023252e+00 }, + { -2.685623065495139e-09, 2.905936237033475e+00 }, + { -2.692696266503800e-09, 2.912551999389617e+00 }, + { -2.699668089019767e-09, 2.919087560358171e+00 }, + { -2.706538270558513e-09, 2.925542248116882e+00 }, + { -2.713306552460767e-09, 2.931915392794031e+00 }, + { -2.719972679905295e-09, 2.938206326512581e+00 }, + { -2.726536401915442e-09, 2.944414383428562e+00 }, + { -2.732997471371516e-09, 2.950538899775061e+00 }, + { -2.739355645017194e-09, 2.956579213900666e+00 }, + { -2.745610683471516e-09, 2.962534666313284e+00 }, + { -2.751762351235315e-09, 2.968404599718795e+00 }, + { -2.757810416701751e-09, 2.974188359063684e+00 }, + { -2.763754652165128e-09, 2.979885291576143e+00 }, + { -2.769594833827588e-09, 2.985494746805227e+00 }, + { -2.775330741810390e-09, 2.991016076664491e+00 }, + { -2.780962160159068e-09, 2.996448635469842e+00 }, + { -2.786488876854607e-09, 3.001791779983262e+00 }, + { -2.791910683818570e-09, 3.007044869450794e+00 }, + { -2.797227376923695e-09, 3.012207265645876e+00 }, + { -2.802438755998943e-09, 3.017278332907412e+00 }, + { -2.807544624838820e-09, 3.022257438182037e+00 }, + { -2.812544791210840e-09, 3.027143951064684e+00 }, + { -2.817439066860792e-09, 3.031937243837070e+00 }, + { -2.822227267522746e-09, 3.036636691510884e+00 }, + { -2.826909212922864e-09, 3.041241671864994e+00 }, + { -2.831484726789317e-09, 3.045751565488710e+00 }, + { -2.835953636855826e-09, 3.050165755818853e+00 }, + { -2.840315774871260e-09, 3.054483629182857e+00 }, + { -2.844570976602957e-09, 3.058704574835744e+00 }, + { -2.848719081844986e-09, 3.062827985002047e+00 }, + { -2.852759934424164e-09, 3.066853254915581e+00 }, + { -2.856693382203833e-09, 3.070779782857041e+00 }, + { -2.860519277092708e-09, 3.074606970196721e+00 }, + { -2.864237475047239e-09, 3.078334221430809e+00 }, + { -2.867847836080156e-09, 3.081960944223928e+00 }, + { -2.871350224262603e-09, 3.085486549445314e+00 }, + { -2.874744507732462e-09, 3.088910451211251e+00 }, + { -2.878030558696270e-09, 3.092232066921130e+00 }, + { -2.881208253436038e-09, 3.095450817298478e+00 }, + { -2.884277472313999e-09, 3.098566126429974e+00 }, + { -2.887238099774968e-09, 3.101577421802070e+00 }, + { -2.890090024353816e-09, 3.104484134342861e+00 }, + { -2.892833138676371e-09, 3.107285698457308e+00 }, + { -2.895467339466766e-09, 3.109981552069083e+00 }, + { -2.897992527547963e-09, 3.112571136655481e+00 }, + { -2.900408607848946e-09, 3.115053897289195e+00 }, + { -2.902715489404992e-09, 3.117429282673042e+00 }, + { -2.904913085363323e-09, 3.119696745180238e+00 }, + { -2.907001312986328e-09, 3.121855740892224e+00 }, + { -2.908980093652563e-09, 3.123905729634218e+00 }, + { -2.910849352862924e-09, 3.125846175016163e+00 }, + { -2.912609020239985e-09, 3.127676544466606e+00 }, + { -2.914259029534118e-09, 3.129396309273659e+00 }, + { -2.915799318622574e-09, 3.131004944618667e+00 }, + { -2.917229829515169e-09, 3.132501929616775e+00 }, + { -2.918550508353347e-09, 3.133886747350606e+00 }, + { -2.919761305414294e-09, 3.135158884909254e+00 }, + { -2.920862175112829e-09, 3.136317833424958e+00 }, + { -2.921853076000972e-09, 3.137363088107359e+00 }, + { -2.922733970772719e-09, 3.138294148283254e+00 }, + { -2.923504826262027e-09, 3.139110517429204e+00 }, + { -2.924165613447473e-09, 3.139811703211207e+00 }, + { -2.924716307449950e-09, 3.140397217517018e+00 }, + { -2.925156887536978e-09, 3.140866576495489e+00 }, + { -2.925487337120335e-09, 3.141219300588825e+00 }, + { -2.925707643758784e-09, 3.141454914570261e+00 }, + { -2.925817799158535e-09, 3.141572947579352e+00 }, + { -2.925817799171455e-09, 3.141572933154836e+00 }, + { -2.925707643798390e-09, 3.141454409272987e+00 }, + { -2.925487337185779e-09, 3.141216918378770e+00 }, + { -2.925156887628892e-09, 3.140860007424112e+00 }, + { -2.924716307568119e-09, 3.140383227898687e+00 }, + { -2.924165613591896e-09, 3.139786135867868e+00 }, + { -2.923504826432903e-09, 3.139068292003385e+00 }, + { -2.922733970969412e-09, 3.138229261619561e+00 }, + { -2.921853076224321e-09, 3.137268614707029e+00 }, + { -2.920862175361976e-09, 3.136185925964038e+00 }, + { -2.919761305690083e-09, 3.134980774833275e+00 }, + { -2.918550508654911e-09, 3.133652745531368e+00 }, + { -2.917229829843137e-09, 3.132201427085629e+00 }, + { -2.915799318976726e-09, 3.130626413363146e+00 }, + { -2.914259029914435e-09, 3.128927303107136e+00 }, + { -2.912609020646661e-09, 3.127103699965947e+00 }, + { -2.910849353295315e-09, 3.125155212527586e+00 }, + { -2.908980094111509e-09, 3.123081454351802e+00 }, + { -2.907001313470937e-09, 3.120882043999591e+00 }, + { -2.904913085874448e-09, 3.118556605068443e+00 }, + { -2.902715489941767e-09, 3.116104766219928e+00 }, + { -2.900408608411958e-09, 3.113526161214776e+00 }, + { -2.897992528137022e-09, 3.110820428940251e+00 }, + { -2.895467340081818e-09, 3.107987213444579e+00 }, + { -2.892833139317615e-09, 3.105026163964191e+00 }, + { -2.890090025020589e-09, 3.101936934956479e+00 }, + { -2.887238100468092e-09, 3.098719186130021e+00 }, + { -2.884277473032614e-09, 3.095372582472161e+00 }, + { -2.881208254180937e-09, 3.091896794282404e+00 }, + { -2.878030559466594e-09, 3.088291497198199e+00 }, + { -2.874744508528832e-09, 3.084556372228054e+00 }, + { -2.871350225084755e-09, 3.080691105776848e+00 }, + { -2.867847836928063e-09, 3.076695389678615e+00 }, + { -2.864237475921086e-09, 3.072568921221621e+00 }, + { -2.860519277991847e-09, 3.068311403179147e+00 }, + { -2.856693383129018e-09, 3.063922543837792e+00 }, + { -2.852759935374575e-09, 3.059402057023109e+00 }, + { -2.848719082821403e-09, 3.054749662130841e+00 }, + { -2.844570977604520e-09, 3.049965084150782e+00 }, + { -2.840315775898525e-09, 3.045048053697736e+00 }, + { -2.835953637908582e-09, 3.039998307034967e+00 }, + { -2.831484727867511e-09, 3.034815586104635e+00 }, + { -2.826909214026628e-09, 3.029499638550941e+00 }, + { -2.822227268651470e-09, 3.024050217748861e+00 }, + { -2.817439068015245e-09, 3.018467082830179e+00 }, + { -2.812544792390175e-09, 3.012749998707001e+00 }, + { -2.807544626043751e-09, 3.006898736100911e+00 }, + { -2.802438757228650e-09, 3.000913071564665e+00 }, + { -2.797227378178760e-09, 2.994792787510961e+00 }, + { -2.791910685098702e-09, 2.988537672233504e+00 }, + { -2.786488878159805e-09, 2.982147519935565e+00 }, + { -2.780962161489413e-09, 2.975622130750641e+00 }, + { -2.775330743165298e-09, 2.968961310769028e+00 }, + { -2.769594835207775e-09, 2.962164872061613e+00 }, + { -2.763754653569747e-09, 2.955232632701135e+00 }, + { -2.757810418131543e-09, 2.948164416789036e+00 }, + { -2.751762352689432e-09, 2.940960054474719e+00 }, + { -2.745610684950541e-09, 2.933619381982341e+00 }, + { -2.739355646520809e-09, 2.926142241629213e+00 }, + { -2.732997472899722e-09, 2.918528481852205e+00 }, + { -2.726536403468318e-09, 2.910777957226018e+00 }, + { -2.719972681482232e-09, 2.902890528487386e+00 }, + { -2.713306554062453e-09, 2.894866062556452e+00 }, + { -2.706538272184154e-09, 2.886704432555728e+00 }, + { -2.699668090670078e-09, 2.878405517834426e+00 }, + { -2.692696268177908e-09, 2.869969203985464e+00 }, + { -2.685623067193599e-09, 2.861395382869544e+00 }, + { -2.678448754018380e-09, 2.852683952631486e+00 }, + { -2.671173598761847e-09, 2.843834817723832e+00 }, + { -2.663797875328991e-09, 2.834847888922988e+00 }, + { -2.656321861411517e-09, 2.825723083350459e+00 }, + { -2.648745838477759e-09, 2.816460324492298e+00 }, + { -2.641070091759922e-09, 2.807059542215146e+00 }, + { -2.633294910246296e-09, 2.797520672788269e+00 }, + { -2.625420586667340e-09, 2.787843658897949e+00 }, + { -2.617447417487602e-09, 2.778028449668942e+00 }, + { -2.609375702891616e-09, 2.768075000678399e+00 }, + { -2.601205746775692e-09, 2.757983273976943e+00 }, + { -2.592937856733464e-09, 2.747753238101915e+00 }, + { -2.584572344046340e-09, 2.737384868096553e+00 }, + { -2.576109523671634e-09, 2.726878145526201e+00 }, + { -2.567549714229129e-09, 2.716233058492422e+00 }, + { -2.558893237991435e-09, 2.705449601651722e+00 }, + { -2.550140420869302e-09, 2.694527776227857e+00 }, + { -2.541291592402089e-09, 2.683467590030445e+00 }, + { -2.532347085742440e-09, 2.672269057466213e+00 }, + { -2.523307237646751e-09, 2.660932199557362e+00 }, + { -2.514172388459584e-09, 2.649457043952206e+00 }, + { -2.504942882102813e-09, 2.637843624941622e+00 }, + { -2.495619066062810e-09, 2.626091983472908e+00 }, + { -2.486201291375123e-09, 2.614202167160335e+00 }, + { -2.476689912614465e-09, 2.602174230302269e+00 }, + { -2.467085287878098e-09, 2.590008233889805e+00 }, + { -2.457387778775451e-09, 2.577704245623143e+00 }, + { -2.447597750411553e-09, 2.565262339920002e+00 }, + { -2.437715571376127e-09, 2.552682597931055e+00 }, + { -2.427741613727123e-09, 2.539965107548168e+00 }, + { -2.417676252978335e-09, 2.527109963417675e+00 }, + { -2.407519868085581e-09, 2.514117266951687e+00 }, + { -2.397272841430131e-09, 2.500987126335739e+00 }, + { -2.386935558807595e-09, 2.487719656543254e+00 }, + { -2.376508409410024e-09, 2.474314979341178e+00 }, + { -2.365991785814531e-09, 2.460773223303822e+00 }, + { -2.355386083965131e-09, 2.447094523817833e+00 }, + { -2.344691703161363e-09, 2.433279023095734e+00 }, + { -2.333909046040126e-09, 2.419326870180582e+00 }, + { -2.323038518562289e-09, 2.405238220956597e+00 }, + { -2.312080529997549e-09, 2.391013238157397e+00 }, + { -2.301035492907384e-09, 2.376652091371587e+00 }, + { -2.289903823131822e-09, 2.362154957053137e+00 }, + { -2.278685939771276e-09, 2.347522018525197e+00 }, + { -2.267382265173420e-09, 2.332753465990296e+00 }, + { -2.255993224914501e-09, 2.317849496533128e+00 }, + { -2.244519247786155e-09, 2.302810314130351e+00 }, + { -2.232960765776561e-09, 2.287636129652823e+00 }, + { -2.221318214056095e-09, 2.272327160873552e+00 }, + { -2.209592030960763e-09, 2.256883632472565e+00 }, + { -2.197782657974034e-09, 2.241305776039511e+00 }, + { -2.185890539712767e-09, 2.225593830081461e+00 }, + { -2.173916123907886e-09, 2.209748040023618e+00 }, + { -2.161859861389976e-09, 2.193768658216360e+00 }, + { -2.149722206070124e-09, 2.177655943935795e+00 }, + { -2.137503614923981e-09, 2.161410163388424e+00 }, + { -2.125204547975352e-09, 2.145031589714984e+00 }, + { -2.112825468276292e-09, 2.128520502989477e+00 }, + { -2.100366841892917e-09, 2.111877190225612e+00 }, + { -2.087829137884807e-09, 2.095101945374541e+00 }, + { -2.075212828290086e-09, 2.078195069329960e+00 }, + { -2.062518388104923e-09, 2.061156869925600e+00 }, + { -2.049746295268559e-09, 2.043987661939897e+00 }, + { -2.036897030642658e-09, 2.026687767092888e+00 }, + { -2.023971077994576e-09, 2.009257514048162e+00 }, + { -2.010968923979840e-09, 1.991697238413571e+00 }, + { -1.997891058121344e-09, 1.974007282737320e+00 }, + { -1.984737972794098e-09, 1.956187996511354e+00 }, + { -1.971510163203686e-09, 1.938239736166060e+00 }, + { -1.958208127370276e-09, 1.920162865072273e+00 }, + { -1.944832366107339e-09, 1.901957753535934e+00 }, + { -1.931383383005451e-09, 1.883624778799427e+00 }, + { -1.917861684410531e-09, 1.865164325035177e+00 }, + { -1.904267779407432e-09, 1.846576783346324e+00 }, + { -1.890602179798714e-09, 1.827862551760622e+00 }, + { -1.876865400086483e-09, 1.809022035228338e+00 }, + { -1.863057957452539e-09, 1.790055645617624e+00 }, + { -1.849180371740008e-09, 1.770963801711725e+00 }, + { -1.835233165431475e-09, 1.751746929201178e+00 }, + { -1.821216863631569e-09, 1.732405460681919e+00 }, + { -1.807131994045840e-09, 1.712939835648088e+00 }, + { -1.792979086962494e-09, 1.693350500488565e+00 }, + { -1.778758675229683e-09, 1.673637908477153e+00 }, + { -1.764471294238191e-09, 1.653802519770021e+00 }, + { -1.750117481899733e-09, 1.633844801396848e+00 }, + { -1.735697778626995e-09, 1.613765227254186e+00 }, + { -1.721212727314574e-09, 1.593564278099856e+00 }, + { -1.706662873315474e-09, 1.573242441540939e+00 }, + { -1.692048764423848e-09, 1.552800212030258e+00 }, + { -1.677370950852395e-09, 1.532238090855187e+00 }, + { -1.662629985213192e-09, 1.511556586131055e+00 }, + { -1.647826422494560e-09, 1.490756212788764e+00 }, + { -1.632960820042537e-09, 1.469837492568651e+00 }, + { -1.618033737538645e-09, 1.448800954008929e+00 }, + { -1.603045736978760e-09, 1.427647132435469e+00 }, + { -1.587997382653428e-09, 1.406376569953373e+00 }, + { -1.572889241124034e-09, 1.384989815432507e+00 }, + { -1.557721881203696e-09, 1.363487424499449e+00 }, + { -1.542495873934815e-09, 1.341869959524515e+00 }, + { -1.527211792568486e-09, 1.320137989611176e+00 }, + { -1.511870212541253e-09, 1.298292090581491e+00 }, + { -1.496471711454994e-09, 1.276332844965754e+00 }, + { -1.481016869054634e-09, 1.254260841988828e+00 }, + { -1.465506267206068e-09, 1.232076677556547e+00 }, + { -1.449940489875303e-09, 1.209780954243628e+00 }, + { -1.434320123104372e-09, 1.187374281276747e+00 }, + { -1.418645754991533e-09, 1.164857274523495e+00 }, + { -1.402917975667710e-09, 1.142230556475749e+00 }, + { -1.387137377275425e-09, 1.119494756236361e+00 }, + { -1.371304553944712e-09, 1.096650509501278e+00 }, + { -1.355420101772623e-09, 1.073698458546610e+00 }, + { -1.339484618799891e-09, 1.050639252211352e+00 }, + { -1.323498704988051e-09, 1.027473545880543e+00 }, + { -1.307462962198534e-09, 1.004202001471034e+00 }, + { -1.291377994167204e-09, 9.808252874104182e-01 }, + { -1.275244406484394e-09, 9.573440786237052e-01 }, + { -1.259062806570190e-09, 9.337590565128454e-01 }, + { -1.242833803653464e-09, 9.100709089414796e-01 }, + { -1.226558008746195e-09, 8.862803302125812e-01 }, + { -1.210236034623253e-09, 8.623880210538113e-01 }, + { -1.193868495797618e-09, 8.383946885959868e-01 }, + { -1.177456008497777e-09, 8.143010463544786e-01 }, + { -1.160999190645010e-09, 7.901078142102129e-01 }, + { -1.144498661828833e-09, 7.658157183877095e-01 }, + { -1.127955043284965e-09, 7.414254914366063e-01 }, + { -1.111368957870986e-09, 7.169378722095157e-01 }, + { -1.094741030044308e-09, 6.923536058430697e-01 }, + { -1.078071885836393e-09, 6.676734437331688e-01 }, + { -1.061362152831423e-09, 6.428981435165511e-01 }, + { -1.044612460141255e-09, 6.180284690466404e-01 }, + { -1.027823438382183e-09, 5.930651903718045e-01 }, + { -1.010995719652015e-09, 5.680090837138436e-01 }, + { -9.941299375042378e-10, 5.428609314418970e-01 }, + { -9.772267269262058e-10, 5.176215220520872e-01 }, + { -9.602867243141016e-10, 4.922916501421032e-01 }, + { -9.433105674499058e-10, 4.668721163885412e-01 }, + { -9.262988954758817e-10, 4.413637275202624e-01 }, + { -9.092523488719689e-10, 4.157672962958654e-01 }, + { -8.921715694311144e-10, 3.900836414778084e-01 }, + { -8.750572002347607e-10, 3.643135878065193e-01 }, + { -8.579098856296589e-10, 3.384579659762392e-01 }, + { -8.407302712022458e-10, 3.125176126069478e-01 }, + { -8.235190037551917e-10, 2.864933702193017e-01 }, + { -8.062767312831008e-10, 2.603860872080448e-01 }, + { -7.890041029479477e-10, 2.341966178147619e-01 }, + { -7.717017690542486e-10, 2.079258220999725e-01 }, + { -7.543703810250266e-10, 1.815745659161734e-01 }, + { -7.370105913774597e-10, 1.551437208801425e-01 }, + { -7.196230536974697e-10, 1.286341643433767e-01 }, + { -7.022084226165876e-10, 1.020467793657360e-01 }, + { -6.847673537853251e-10, 7.538245468350446e-02 }, + { -6.673005038502516e-10, 4.864208468284503e-02 }, + { -6.498085304282128e-10, 2.182656936863137e-02 }, + { -6.322920920826137e-10, -5.063185663820913e-03 }, + { -6.147518482969490e-10, -3.202626926150343e-02 }, + { -5.971884594516681e-10, -5.906176474160862e-02 }, + { -5.796025867984469e-10, -8.616874992366363e-02 }, + { -5.619948924353588e-10, -1.133462971605448e-01 }, + { -5.443660392823640e-10, -1.405934733692621e-01 }, + { -5.267166910556339e-10, -1.679093400638023e-01 }, + { -5.090475122431451e-10, -1.952929533862739e-01 }, + { -4.913591680795342e-10, -2.227433641394564e-01 }, + { -4.736523245210571e-10, -2.502596178194491e-01 }, + { -4.559276482202303e-10, -2.778407546490776e-01 }, + { -4.381858065011618e-10, -3.054858096104932e-01 }, + { -4.204274673340870e-10, -3.331938124792702e-01 }, + { -4.026532993105397e-10, -3.609637878577768e-01 }, + { -3.848639716178888e-10, -3.887947552098022e-01 }, + { -3.670601540142443e-10, -4.166857288948674e-01 }, + { -3.492425168032583e-10, -4.446357182029681e-01 }, + { -3.314117308088734e-10, -4.726437273896633e-01 }, + { -3.135684673501752e-10, -5.007087557112619e-01 }, + { -2.957133982159296e-10, -5.288297974607742e-01 }, + { -2.778471956393828e-10, -5.570058420037128e-01 }, + { -2.599705322729564e-10, -5.852358738143247e-01 }, + { -2.420840811628366e-10, -6.135188725122560e-01 }, + { -2.241885157240923e-10, -6.418538128986450e-01 }, + { -2.062845097142585e-10, -6.702396649949099e-01 }, + { -1.883727372093546e-10, -6.986753940779493e-01 }, + { -1.704538725773087e-10, -7.271599607197149e-01 }, + { -1.525285904532877e-10, -7.556923208240308e-01 }, + { -1.345975657140748e-10, -7.842714256651911e-01 }, + { -1.166614734526054e-10, -8.128962219265712e-01 }, + { -9.872098895260891e-11, -8.415656517393372e-01 }, + { -8.077678766314517e-11, -8.702786527215916e-01 }, + { -6.282954517324612e-11, -8.990341580176152e-01 }, + { -4.487993718655790e-11, -9.278310963373758e-01 }, + { -2.692863949561210e-11, -9.566683919968972e-01 }, + { -8.976327956520795e-12, -9.855449649582175e-01 }, + { 8.976321536169872e-12, -1.014459730869357e+00 }, + { 2.692863307547294e-11, -1.043411601105914e+00 }, + { 4.487993076694813e-11, -1.072399482811314e+00 }, + { 6.282953875437751e-11, -1.101422278938424e+00 }, + { 8.077678124517653e-11, -1.130478888291020e+00 }, + { 9.872098253591082e-11, -1.159568205565684e+00 }, + { 1.166614670373367e-10, -1.188689121393192e+00 }, + { 1.345975593005002e-10, -1.217840522381901e+00 }, + { 1.525285840416718e-10, -1.247021291159495e+00 }, + { 1.704538661678104e-10, -1.276230306415868e+00 }, + { 1.883727308022916e-10, -1.305466442946703e+00 }, + { 2.062845033098954e-10, -1.334728571696106e+00 }, + { 2.241885093225349e-10, -1.364015559800721e+00 }, + { 2.420840747645085e-10, -1.393326270633325e+00 }, + { 2.599705258779635e-10, -1.422659563847049e+00 }, + { 2.778471892479898e-10, -1.452014295419243e+00 }, + { 2.957133918284542e-10, -1.481389317696831e+00 }, + { 3.135684609667761e-10, -1.510783479440191e+00 }, + { 3.314117244297624e-10, -1.540195625869043e+00 }, + { 3.492425104288060e-10, -1.569624598707558e+00 }, + { 3.670601476445565e-10, -1.599069236228850e+00 }, + { 3.848639652533361e-10, -1.628528373302631e+00 }, + { 4.026532929512281e-10, -1.658000841439269e+00 }, + { 4.204274609803869e-10, -1.687485468837799e+00 }, + { 4.381858001531792e-10, -1.716981080430596e+00 }, + { 4.559276418782829e-10, -1.746486497931567e+00 }, + { 4.736523181853565e-10, -1.776000539882225e+00 }, + { 4.913591617503452e-10, -1.805522021699094e+00 }, + { 5.090475059206794e-10, -1.835049755721194e+00 }, + { 5.267166847401562e-10, -1.864582551257262e+00 }, + { 5.443660329740862e-10, -1.894119214633676e+00 }, + { 5.619948861345454e-10, -1.923658549242818e+00 }, + { 5.796025805053097e-10, -1.953199355591180e+00 }, + { 5.971884531664190e-10, -1.982740431347091e+00 }, + { 6.147518420199055e-10, -2.012280571390674e+00 }, + { 6.322920858139346e-10, -2.041818567861395e+00 }, + { 6.498085241682158e-10, -2.071353210208005e+00 }, + { 6.673004975990425e-10, -2.100883285238127e+00 }, + { 6.847673475432746e-10, -2.130407577166309e+00 }, + { 7.022084163838545e-10, -2.159924867664933e+00 }, + { 7.196230474743716e-10, -2.189433935913779e+00 }, + { 7.370105851640495e-10, -2.218933558650552e+00 }, + { 7.543703748217808e-10, -2.248422510220072e+00 }, + { 7.717017628611672e-10, -2.277899562625407e+00 }, + { 7.890040967654542e-10, -2.307363485579104e+00 }, + { 8.062767251113011e-10, -2.336813046552684e+00 }, + { 8.235189975944034e-10, -2.366247010829556e+00 }, + { 8.407302650525749e-10, -2.395664141553858e+00 }, + { 8.579098794915287e-10, -2.425063199784153e+00 }, + { 8.750571941082773e-10, -2.454442944543319e+00 }, + { 8.921715633164894e-10, -2.483802132872044e+00 }, + { 9.092523427695200e-10, -2.513139519878584e+00 }, + { 9.262988893857148e-10, -2.542453858792682e+00 }, + { 9.433105613723914e-10, -2.571743901017465e+00 }, + { 9.602867182493987e-10, -2.601008396180870e+00 }, + { 9.772267208744730e-10, -2.630246092190425e+00 }, + { 9.941299314658458e-10, -2.659455735283526e+00 }, + { 1.010995713627070e-09, -2.688636070081818e+00 }, + { 1.027823432371055e-09, -2.717785839644439e+00 }, + { 1.044612454143997e-09, -2.746903785521352e+00 }, + { 1.061362146848353e-09, -2.775988647805256e+00 }, + { 1.078071879867828e-09, -2.805039165187255e+00 }, + { 1.094741024090249e-09, -2.834054075009077e+00 }, + { 1.111368951931856e-09, -2.863032113318052e+00 }, + { 1.127955037360817e-09, -2.891972014920939e+00 }, + { 1.144498655920037e-09, -2.920872513436805e+00 }, + { 1.160999184751779e-09, -2.949732341353290e+00 }, + { 1.177456002620215e-09, -2.978550230079517e+00 }, + { 1.193868489936097e-09, -3.007324910002949e+00 }, + { 1.210236028777826e-09, -3.036055110540183e+00 }, + { 1.226558002917232e-09, -3.064739560196251e+00 }, + { 1.242833797841123e-09, -3.093376986616735e+00 }, + { 1.259062800774685e-09, -3.121966116643377e+00 }, + { 1.275244400705935e-09, -3.150505676371791e+00 }, + { 1.291377988406056e-09, -3.178994391202159e+00 }, + { 1.307462956454857e-09, -3.207430985899192e+00 }, + { 1.323498699262108e-09, -3.235814184645077e+00 }, + { 1.339484613091842e-09, -3.264142711097884e+00 }, + { 1.355420096082785e-09, -3.292415288443373e+00 }, + { 1.371304548273191e-09, -3.320630639454825e+00 }, + { 1.387137371622433e-09, -3.348787486547389e+00 }, + { 1.402917970033511e-09, -3.376884551834256e+00 }, + { 1.418645749376393e-09, -3.404920557184582e+00 }, + { 1.434320117508396e-09, -3.432894224276359e+00 }, + { 1.449940484298756e-09, -3.460804274656981e+00 }, + { 1.465506261649108e-09, -3.488649429796768e+00 }, + { 1.481016863517580e-09, -3.516428411149154e+00 }, + { 1.496471705937951e-09, -3.544139940202303e+00 }, + { 1.511870207044433e-09, -3.571782738540999e+00 }, + { 1.527211787092206e-09, -3.599355527901174e+00 }, + { 1.542495868479076e-09, -3.626857030226671e+00 }, + { 1.557721875768920e-09, -3.654285967729458e+00 }, + { 1.572889235710329e-09, -3.681641062941412e+00 }, + { 1.587997377261005e-09, -3.708921038776707e+00 }, + { 1.603045731607830e-09, -3.736124618586623e+00 }, + { 1.618033732189314e-09, -3.763250526218862e+00 }, + { 1.632960814715177e-09, -3.790297486071938e+00 }, + { 1.647826417189275e-09, -3.817264223155802e+00 }, + { 1.662629979930247e-09, -3.844149463148589e+00 }, + { 1.677370945591844e-09, -3.870951932452996e+00 }, + { 1.692048759186008e-09, -3.897670358257890e+00 }, + { 1.706662868100504e-09, -3.924303468590212e+00 }, + { 1.721212722122685e-09, -3.950849992378278e+00 }, + { 1.735697773458400e-09, -3.977308659506432e+00 }, + { 1.750117476754591e-09, -4.003678200876669e+00 }, + { 1.764471289116712e-09, -4.029957348461003e+00 }, + { 1.778758670132079e-09, -4.056144835364877e+00 }, + { 1.792979081888926e-09, -4.082239395882965e+00 }, + { 1.807131988996465e-09, -4.108239765556996e+00 }, + { 1.821216858606652e-09, -4.134144681236933e+00 }, + { 1.835233160431175e-09, -4.159952881133585e+00 }, + { 1.849180366764537e-09, -4.185663104882633e+00 }, + { 1.863057952502055e-09, -4.211274093599509e+00 }, + { 1.876865395161145e-09, -4.236784589940537e+00 }, + { 1.890602174898734e-09, -4.262193338157148e+00 }, + { 1.904267774533022e-09, -4.287499084158302e+00 }, + { 1.917861679562008e-09, -4.312700575567174e+00 }, + { 1.931383378182392e-09, -4.337796561778708e+00 }, + { 1.944832361310856e-09, -4.362785794021793e+00 }, + { 1.958208122599839e-09, -4.387667025411434e+00 }, + { 1.971510158459931e-09, -4.412439011013396e+00 }, + { 1.984737968076495e-09, -4.437100507898339e+00 }, + { 1.997891053431005e-09, -4.461650275204912e+00 }, + { 2.010968919316289e-09, -4.486087074191693e+00 }, + { 2.023971073358447e-09, -4.510409668301784e+00 }, + { 2.036897026033634e-09, -4.534616823217992e+00 }, + { 2.049746290686799e-09, -4.558707306921882e+00 }, + { 2.062518383551274e-09, -4.582679889754607e+00 }, + { 2.075212823764071e-09, -4.606533344469879e+00 }, + { 2.087829133387063e-09, -4.630266446298172e+00 }, + { 2.100366837422912e-09, -4.653877973001258e+00 }, + { 2.112825463835087e-09, -4.677366704934605e+00 }, + { 2.125204543562522e-09, -4.700731425099899e+00 }, + { 2.137503610540056e-09, -4.723970919208608e+00 }, + { 2.149722201714786e-09, -4.747083975738060e+00 }, + { 2.161859857063438e-09, -4.770069385989595e+00 }, + { 2.173916119610994e-09, -4.792925944149308e+00 }, + { 2.185890535445098e-09, -4.815652447340950e+00 }, + { 2.197782653735957e-09, -4.838247695689436e+00 }, + { 2.209592026751962e-09, -4.860710492376411e+00 }, + { 2.221318209877576e-09, -4.883039643700314e+00 }, + { 2.232960761627846e-09, -4.905233959130168e+00 }, + { 2.244519243667616e-09, -4.927292251368517e+00 }, + { 2.255993220826402e-09, -4.949213336406265e+00 }, + { 2.267382261115285e-09, -4.970996033581527e+00 }, + { 2.278685935744269e-09, -4.992639165639563e+00 }, + { 2.289903819135414e-09, -5.014141558784778e+00 }, + { 2.301035488942000e-09, -5.035502042744443e+00 }, + { 2.312080526062763e-09, -5.056719450823151e+00 }, + { 2.323038514659161e-09, -5.077792619963239e+00 }, + { 2.333909042168180e-09, -5.098720390796817e+00 }, + { 2.344691699320969e-09, -5.119501607709159e+00 }, + { 2.355386080156553e-09, -5.140135118892792e+00 }, + { 2.365991782037187e-09, -5.160619776404897e+00 }, + { 2.376508405665132e-09, -5.180954436227641e+00 }, + { 2.386935555094626e-09, -5.201137958319343e+00 }, + { 2.397272837749508e-09, -5.221169206676762e+00 }, + { 2.407519864436774e-09, -5.241047049389645e+00 }, + { 2.417676249362563e-09, -5.260770358700167e+00 }, + { 2.427741610143750e-09, -5.280338011053974e+00 }, + { 2.437715567825576e-09, -5.299748887163106e+00 }, + { 2.447597746894037e-09, -5.319001872058887e+00 }, + { 2.457387775290440e-09, -5.338095855149190e+00 }, + { 2.467085284426756e-09, -5.357029730277389e+00 }, + { 2.476689909196263e-09, -5.375802395772283e+00 }, + { 2.486201287990485e-09, -5.394412754510426e+00 }, + { 2.495619062711154e-09, -5.412859713968929e+00 }, + { 2.504942878785408e-09, -5.431142186284682e+00 }, + { 2.514172385175743e-09, -5.449259088303476e+00 }, + { 2.523307234396791e-09, -5.467209341642627e+00 }, + { 2.532347082526785e-09, -5.484991872743321e+00 }, + { 2.541291589219998e-09, -5.502605612925014e+00 }, + { 2.550140417722072e-09, -5.520049498445633e+00 }, + { 2.558893234878378e-09, -5.537322470548212e+00 }, + { 2.567549711150773e-09, -5.554423475524196e+00 }, + { 2.576109520627371e-09, -5.571351464763084e+00 }, + { 2.584572341037361e-09, -5.588105394812198e+00 }, + { 2.592937853759161e-09, -5.604684227423386e+00 }, + { 2.601205743836355e-09, -5.621086929615246e+00 }, + { 2.609375699987564e-09, -5.637312473723475e+00 }, + { 2.617447414618146e-09, -5.653359837454964e+00 }, + { 2.625420583833750e-09, -5.669228003945694e+00 }, + { 2.633294907447937e-09, -5.684915961806963e+00 }, + { 2.641070088997271e-09, -5.700422705186584e+00 }, + { 2.648745835750128e-09, -5.715747233817712e+00 }, + { 2.656321858720176e-09, -5.730888553077074e+00 }, + { 2.663797872673252e-09, -5.745845674030161e+00 }, + { 2.671173596142054e-09, -5.760617613492118e+00 }, + { 2.678448751434797e-09, -5.775203394076705e+00 }, + { 2.685623064645538e-09, -5.789602044248679e+00 }, + { 2.692696265666640e-09, -5.803812598380606e+00 }, + { 2.699668088194915e-09, -5.817834096797069e+00 }, + { 2.706538269745573e-09, -5.831665585834668e+00 }, + { 2.713306551659817e-09, -5.845306117889361e+00 }, + { 2.719972679116734e-09, -5.858754751472542e+00 }, + { 2.726536401139295e-09, -5.872010551255358e+00 }, + { 2.732997470607439e-09, -5.885072588127400e+00 }, + { 2.739355644265558e-09, -5.897939939244211e+00 }, + { 2.745610682731633e-09, -5.910611688078208e+00 }, + { 2.751762350508137e-09, -5.923086924473290e+00 }, + { 2.757810415987146e-09, -5.935364744687794e+00 }, + { 2.763754651462700e-09, -5.947444251452243e+00 }, + { 2.769594833137415e-09, -5.959324554015538e+00 }, + { 2.775330741132843e-09, -5.971004768198829e+00 }, + { 2.780962159494174e-09, -5.982484016437981e+00 }, + { 2.786488876202047e-09, -5.993761427840588e+00 }, + { 2.791910683178690e-09, -6.004836138231525e+00 }, + { 2.797227376295779e-09, -6.015707290202086e+00 }, + { 2.802438755383971e-09, -6.026374033162623e+00 }, + { 2.807544624236659e-09, -6.036835523383457e+00 }, + { 2.812544790621093e-09, -6.047090924050914e+00 }, + { 2.817439066283459e-09, -6.057139405311101e+00 }, + { 2.822227266958278e-09, -6.066980144322601e+00 }, + { 2.826909212371261e-09, -6.076612325295799e+00 }, + { 2.831484726250221e-09, -6.086035139548830e+00 }, + { 2.835953636329660e-09, -6.095247785550617e+00 }, + { 2.840315774357203e-09, -6.104249468967751e+00 }, + { 2.844570976102082e-09, -6.113039402715685e+00 }, + { 2.848719081357095e-09, -6.121616806996519e+00 }, + { 2.852759933948860e-09, -6.129980909353977e+00 }, + { 2.856693381741114e-09, -6.138130944714082e+00 }, + { 2.860519276643053e-09, -6.146066155436312e+00 }, + { 2.864237474610633e-09, -6.153785791350256e+00 }, + { 2.867847835656203e-09, -6.161289109809551e+00 }, + { 2.871350223851726e-09, -6.168575375732642e+00 }, + { 2.874744507333867e-09, -6.175643861647406e+00 }, + { 2.878030558310989e-09, -6.182493847739853e+00 }, + { 2.881208253063899e-09, -6.189124621889823e+00 }, + { 2.884277471954592e-09, -6.195535479723423e+00 }, + { 2.887238099428306e-09, -6.201725724651554e+00 }, + { 2.890090024020323e-09, -6.207694667918394e+00 }, + { 2.892833138356060e-09, -6.213441628635915e+00 }, + { 2.895467339159240e-09, -6.218965933835304e+00 }, + { 2.897992527253659e-09, -6.224266918505075e+00 }, + { 2.900408607567016e-09, -6.229343925633495e+00 }, + { 2.902715489136496e-09, -6.234196306254763e+00 }, + { 2.904913085108075e-09, -6.238823419482017e+00 }, + { 2.907001312743911e-09, -6.243224632557377e+00 }, + { 2.908980093422997e-09, -6.247399320887848e+00 }, + { 2.910849352646620e-09, -6.251346868091392e+00 }, + { 2.912609020036956e-09, -6.255066666028537e+00 }, + { 2.914259029343965e-09, -6.258558114851525e+00 }, + { 2.915799318445710e-09, -6.261820623039620e+00 }, + { 2.917229829350759e-09, -6.264853607438842e+00 }, + { 2.918550508202463e-09, -6.267656493305673e+00 }, + { 2.919761305276718e-09, -6.270228714337005e+00 }, + { 2.920862174988150e-09, -6.272569712717951e+00 }, + { 2.921853075889193e-09, -6.274678939154603e+00 }, + { 2.922733970674264e-09, -6.276555852917634e+00 }, + { 2.923504826176907e-09, -6.278199921870962e+00 }, + { 2.924165613375264e-09, -6.279610622518139e+00 }, + { 2.924716307391075e-09, -6.280787440034993e+00 }, + { 2.925156887490598e-09, -6.281729868306345e+00 }, + { 2.925487337087508e-09, -6.282437409966992e+00 }, + { 2.925707643739298e-09, -6.282909576428774e+00 }, + { 2.925817799151970e-09, -6.283145887925411e+00 }, diff --git a/gnuradio-core/src/lib/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am new file mode 100644 index 00000000..e390e134 --- /dev/null +++ b/gnuradio-core/src/lib/io/Makefile.am @@ -0,0 +1,96 @@ +# +# Copyright 2001,2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) + +noinst_LTLIBRARIES = libio.la + + +libio_la_SOURCES = \ + gr_file_sink.cc \ + gr_file_source.cc \ + gr_file_descriptor_sink.cc \ + gr_file_descriptor_source.cc \ + gr_message_sink.cc \ + gr_message_source.cc \ + gr_oscope_guts.cc \ + gr_oscope_sink_f.cc \ + gr_oscope_sink_x.cc \ + gri_logger.cc \ + i2c.cc \ + i2c_bitbang.cc \ + i2c_bbio.cc \ + i2c_bbio_pp.cc \ + microtune_4702.cc \ + microtune_4937.cc \ + microtune_4702_eval_board.cc \ + microtune_4937_eval_board.cc \ + microtune_xxxx.cc \ + microtune_xxxx_eval_board.cc \ + ppio.cc \ + ppio_ppdev.cc \ + sdr_1000.cc + +grinclude_HEADERS = \ + gr_file_sink.h \ + gr_file_source.h \ + gr_file_descriptor_sink.h \ + gr_file_descriptor_source.h \ + gr_message_sink.h \ + gr_message_source.h \ + gr_oscope_guts.h \ + gr_oscope_sink_f.h \ + gr_oscope_sink_x.h \ + gr_trigger_mode.h \ + gri_logger.h \ + i2c.h \ + i2c_bitbang.h \ + i2c_bbio.h \ + i2c_bbio_pp.h \ + microtune_4702.h \ + microtune_4937.h \ + microtune_4702_eval_board.h \ + microtune_4937_eval_board.h \ + microtune_eval_board_defs.h \ + microtune_xxxx.h \ + microtune_xxxx_eval_board.h \ + ppio.h \ + ppio_ppdev.h \ + sdr_1000.h + + +swiginclude_HEADERS = \ + io.i \ + gr_file_sink.i \ + gr_file_source.i \ + gr_file_descriptor_sink.i \ + gr_file_descriptor_source.i \ + gr_message_sink.i \ + gr_message_source.i \ + gr_oscope_sink.i \ + microtune_xxxx_eval_board.i \ + microtune_4702_eval_board.i \ + microtune_4937_eval_board.i \ + ppio.i \ + sdr_1000.i diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc new file mode 100644 index 00000000..6a0b1ca4 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +gr_file_descriptor_sink::gr_file_descriptor_sink (size_t itemsize, int fd) + : gr_sync_block ("file_descriptor_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_fd (fd) +{ +} + +gr_file_descriptor_sink_sptr +gr_make_file_descriptor_sink (size_t itemsize, int fd) +{ + return gr_file_descriptor_sink_sptr (new gr_file_descriptor_sink (itemsize, fd)); +} + +gr_file_descriptor_sink::~gr_file_descriptor_sink () +{ + close (d_fd); +} + +int +gr_file_descriptor_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char *) input_items[0]; + unsigned long byte_size = noutput_items * d_itemsize; + + while (byte_size > 0){ + ssize_t r; + + r = write (d_fd, inbuf, byte_size); + if (r == -1){ + if (errno == EINTR) + continue; + else { + perror ("gr_file_descriptor_sink"); + return -1; // indicate we're done + } + } + else { + byte_size -= r; + inbuf += r; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h new file mode 100644 index 00000000..a811ce70 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SINK_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SINK_H + +#include + +class gr_file_descriptor_sink; +typedef boost::shared_ptr gr_file_descriptor_sink_sptr; + +gr_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + +/*! + * \brief Write stream to file descriptor. + * \ingroup sink + */ + +class gr_file_descriptor_sink : public gr_sync_block +{ + friend gr_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + + private: + size_t d_itemsize; + int d_fd; + + protected: + gr_file_descriptor_sink (size_t itemsize, int fd); + + public: + ~gr_file_descriptor_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i new file mode 100644 index 00000000..e0581865 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,file_descriptor_sink) + +gr_file_descriptor_sink_sptr +gr_make_file_descriptor_sink (size_t itemsize, int fd); + +class gr_file_descriptor_sink : public gr_sync_block +{ + protected: + gr_file_descriptor_sink (size_t itemsize, int fd); + + public: + ~gr_file_descriptor_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc new file mode 100644 index 00000000..38b9da01 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc @@ -0,0 +1,146 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +gr_file_descriptor_source::gr_file_descriptor_source (size_t itemsize, + int fd, + bool repeat) + : gr_sync_block ("file_descriptor_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize (itemsize), d_fd (fd), d_repeat (repeat), + d_residue (new unsigned char[itemsize]), d_residue_len (0) +{ +} + +// public constructor that returns a shared_ptr + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat) +{ + return gr_file_descriptor_source_sptr ( + new gr_file_descriptor_source (itemsize, fd, repeat)); +} + +gr_file_descriptor_source::~gr_file_descriptor_source () +{ + close (d_fd); + delete [] d_residue; +} + +int +gr_file_descriptor_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items > 0); + + char *o = (char *) output_items[0]; + int nread = 0; + + while (1){ + int r = read_items (o, noutput_items - nread); + if (r == -1){ + if (errno == EINTR) + continue; + else { + perror ("file_descriptor_source[read]"); + return -1; + } + } + else if (r == 0){ // end of file + if (!d_repeat) + break; + else { + flush_residue (); + if (lseek (d_fd, 0, SEEK_SET) == -1){ + perror ("file_descriptor_source[lseek]"); + return -1; + } + } + } + else { + o += r * d_itemsize; + nread += r; + break; + } + } + + if (nread == 0) // EOF + return -1; + + return nread; +} + +int +gr_file_descriptor_source::read_items (char *buf, int nitems) +{ + assert (nitems > 0); + assert (d_residue_len < d_itemsize); + + int nbytes_read = 0; + + if (d_residue_len > 0){ + memcpy (buf, d_residue, d_residue_len); + nbytes_read = d_residue_len; + d_residue_len = 0; + } + + int r = read (d_fd, buf + nbytes_read, nitems * d_itemsize - nbytes_read); + if (r <= 0){ + handle_residue (buf, nbytes_read); + return r; + } + + r = handle_residue (buf, r + nbytes_read); + + if (r == 0) // block until we get something + return read_items (buf, nitems); + + return r; +} + +int +gr_file_descriptor_source::handle_residue (char *buf, int nbytes_read) +{ + assert (nbytes_read >= 0); + int nitems_read = nbytes_read / d_itemsize; + d_residue_len = nbytes_read % d_itemsize; + if (d_residue_len > 0){ + // fprintf (stderr, "handle_residue: %d\n", d_residue_len); + memcpy (d_residue, buf + nbytes_read - d_residue_len, d_residue_len); + } + return nitems_read; +} diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.h b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h new file mode 100644 index 00000000..9f678dcf --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H + +#include + +class gr_file_descriptor_source; +typedef boost::shared_ptr gr_file_descriptor_source_sptr; + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat = false); + +/*! + * \brief Read stream from file descriptor. + * \ingroup source + */ + +class gr_file_descriptor_source : public gr_sync_block +{ + friend gr_file_descriptor_source_sptr + gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat); + private: + size_t d_itemsize; + int d_fd; + bool d_repeat; + + unsigned char *d_residue; + unsigned long d_residue_len; + + protected: + gr_file_descriptor_source (size_t itemsize, int fd, bool repeat); + + int read_items (char *buf, int nitems); + int handle_residue (char *buf, int nbytes_read); + void flush_residue () { d_residue_len = 0; } + + + public: + ~gr_file_descriptor_source (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.i b/gnuradio-core/src/lib/io/gr_file_descriptor_source.i new file mode 100644 index 00000000..ba9b3894 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,file_descriptor_source) + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat=false); + +class gr_file_descriptor_source : public gr_sync_block +{ + protected: + gr_file_descriptor_source (size_t itemsize, int fd, bool repeat); + + public: + ~gr_file_descriptor_source (); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_sink.cc b/gnuradio-core/src/lib/io/gr_file_sink.cc new file mode 100644 index 00000000..d22488bf --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_sink::gr_file_sink(size_t itemsize, const char *filename) + : gr_sync_block ("file_sink", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)), + d_itemsize(itemsize), d_fp(0), d_new_fp(0), d_updated(false) +{ + if (!open(filename)) + throw std::runtime_error ("can't open file"); +} + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename) +{ + return gr_file_sink_sptr (new gr_file_sink (itemsize, filename)); +} + +gr_file_sink::~gr_file_sink () +{ + close(); + if (d_fp){ + fclose((FILE *) d_fp); + d_fp = 0; + } +} + +bool +gr_file_sink::open(const char *filename) +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + // we use the open system call to get access to the O_LARGEFILE flag. + int fd; + if ((fd = ::open (filename, + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, 0664)) < 0){ + perror (filename); + return false; + } + + if (d_new_fp){ // if we've already got a new one open, close it + fclose((FILE *) d_new_fp); + d_new_fp = 0; + } + + if ((d_new_fp = fdopen (fd, "wb")) == NULL){ + perror (filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + } + + d_updated = true; + return d_new_fp != 0; +} + +void +gr_file_sink::close() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + if (d_new_fp){ + fclose((FILE *) d_new_fp); + d_new_fp = 0; + } + d_updated = true; +} + +int +gr_file_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char *) input_items[0]; + int nwritten = 0; + + if (d_updated){ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this block + if (d_fp) + fclose((FILE *)d_fp); + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } + + if (!d_fp) + return noutput_items; // drop output on the floor + + while (nwritten < noutput_items){ + int count = fwrite (inbuf, d_itemsize, noutput_items - nwritten, (FILE *) d_fp); + if (count == 0) // FIXME add error handling + break; + nwritten += count; + inbuf += count * d_itemsize; + } + return nwritten; +} diff --git a/gnuradio-core/src/lib/io/gr_file_sink.h b/gnuradio-core/src/lib/io/gr_file_sink.h new file mode 100644 index 00000000..9c11bf72 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_SINK_H +#define INCLUDED_GR_FILE_SINK_H + +#include +#include + +class gr_file_sink; +typedef boost::shared_ptr gr_file_sink_sptr; + +gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + +/*! + * \brief Write stream to file. + * \ingroup sink + */ + +class gr_file_sink : public gr_sync_block +{ + friend gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + + private: + size_t d_itemsize; + void *d_fp; // current FILE pointer + void *d_new_fp; // new FILE pointer + bool d_updated; // is there a new FILE pointer? + omni_mutex d_mutex; + + protected: + gr_file_sink(size_t itemsize, const char *filename); + + public: + ~gr_file_sink(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink.i b/gnuradio-core/src/lib/io/gr_file_sink.i new file mode 100644 index 00000000..ffcf02aa --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,file_sink) + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename); + +class gr_file_sink : public gr_sync_block +{ + protected: + gr_file_sink (size_t itemsize, const char *filename); + + public: + ~gr_file_sink (); + + /*! + * \brief open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief close current output file. + */ + void close(); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc new file mode 100644 index 00000000..2573a37e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.cc @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_source::gr_file_source (size_t itemsize, const char *filename, bool repeat) + : gr_sync_block ("file_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize (itemsize), d_fp (0), d_repeat (repeat) +{ + // we use "open" to use to the O_LARGEFILE flag + + int fd; + if ((fd = open (filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0){ + perror (filename); + throw std::runtime_error ("can't open file"); + } + + if ((d_fp = fdopen (fd, "rb")) == NULL){ + perror (filename); + throw std::runtime_error ("can't open file"); + } +} + +// public constructor that returns a shared_ptr + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat) +{ + return gr_file_source_sptr (new gr_file_source (itemsize, filename, repeat)); +} + +gr_file_source::~gr_file_source () +{ + fclose ((FILE *) d_fp); +} + +int +gr_file_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *o = (char *) output_items[0]; + int i; + int size = noutput_items; + + while (size) { + i = fread(o, d_itemsize, size, (FILE *) d_fp); + + size -= i; + o += i * d_itemsize; + + if (size == 0) // done + break; + + if (i > 0) // short read, try again + continue; + + // We got a zero from fread. This is either EOF or error. In + // any event, if we're in repeat mode, seek back to the beginning + // of the file and try again, else break + + if (!d_repeat) + break; + + if (fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) { + fprintf(stderr, "[%s] fseek failed\n", __FILE__); + exit(-1); + } + } + + if (size > 0){ // EOF or error + if (size == noutput_items) // we didn't read anything; say we're done + return -1; + return noutput_items - size; // else return partial result + } + + return noutput_items; +} + +bool +gr_file_source::seek (long seek_point, int whence) +{ + return fseek ((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; +} diff --git a/gnuradio-core/src/lib/io/gr_file_source.h b/gnuradio-core/src/lib/io/gr_file_source.h new file mode 100644 index 00000000..6b635c53 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_SOURCE_H +#define INCLUDED_GR_FILE_SOURCE_H + +#include + +class gr_file_source; +typedef boost::shared_ptr gr_file_source_sptr; + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat = false); + +/*! + * \brief Read stream from file + * \ingroup source + */ + +class gr_file_source : public gr_sync_block +{ + friend gr_file_source_sptr gr_make_file_source (size_t itemsize, + const char *filename, + bool repeat); + private: + size_t d_itemsize; + void *d_fp; + bool d_repeat; + + protected: + gr_file_source (size_t itemsize, const char *filename, bool repeat); + + public: + ~gr_file_source (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief seek file to \p seek_point relative to \p whence + * + * \param seek_point sample offset in file + * \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek) + */ + bool seek (long seek_point, int whence); +}; + +#endif /* INCLUDED_GR_FILE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_source.i b/gnuradio-core/src/lib/io/gr_file_source.i new file mode 100644 index 00000000..08fdfaf9 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.i @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +%constant int SEEK_SET = 0; /* Seek from beginning of file. */ +%constant int SEEK_CUR = 1; /* Seek from current position. */ +%constant int SEEK_END = 2; /* Seek from end of file. */ + + +GR_SWIG_BLOCK_MAGIC(gr,file_source) + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat=false); + +class gr_file_source : public gr_sync_block +{ + protected: + gr_file_source (size_t itemsize, const char *filename, bool repeat); + + public: + ~gr_file_source (); + + bool seek (long seek_point, int whence); +}; diff --git a/gnuradio-core/src/lib/io/gr_message_sink.cc b/gnuradio-core/src/lib/io/gr_message_sink.cc new file mode 100644 index 00000000..8a0784ec --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +// public constructor that returns a shared_ptr + +gr_message_sink_sptr +gr_make_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block) +{ + return gr_message_sink_sptr(new gr_message_sink(itemsize, msgq, dont_block)); +} + +gr_message_sink::gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block) + : gr_sync_block("message_sink", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)), + d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block) +{ +} + +gr_message_sink::~gr_message_sink() +{ +} + +int +gr_message_sink::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]; + + // if we'd block, drop the data on the floor and say everything is OK + if (d_dont_block && d_msgq->full_p()) + return noutput_items; + + // build a message to hold whatever we've got + gr_message_sptr msg = gr_make_message(0, // msg type + d_itemsize, // arg1 for other end + noutput_items, // arg2 for other end (redundant) + noutput_items * d_itemsize); // len of msg + memcpy(msg->msg(), in, noutput_items * d_itemsize); + + d_msgq->handle(msg); // send it + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_message_sink.h b/gnuradio-core/src/lib/io/gr_message_sink.h new file mode 100644 index 00000000..8011ab29 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_SINK_H +#define INCLUDED_GR_MESSAGE_SINK_H + +#include +#include +#include + +class gr_message_sink; +typedef boost::shared_ptr gr_message_sink_sptr; + +gr_message_sink_sptr gr_make_message_sink (size_t itemsize, + gr_msg_queue_sptr msgq, + bool dont_block); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink + */ +class gr_message_sink : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + bool d_dont_block; + + friend gr_message_sink_sptr + gr_make_message_sink(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + protected: + gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + public: + ~gr_message_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_sink.i b/gnuradio-core/src/lib/io/gr_message_sink.i new file mode 100644 index 00000000..ca73479c --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_sink); + +gr_message_sink_sptr gr_make_message_sink (size_t itemsize, + gr_msg_queue_sptr msgq, + bool dont_block); + +class gr_message_sink : public gr_sync_block +{ + protected: + gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + public: + ~gr_message_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_message_source.cc b/gnuradio-core/src/lib/io/gr_message_source.cc new file mode 100644 index 00000000..797433be --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.cc @@ -0,0 +1,104 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +// public constructor that returns a shared_ptr + +gr_message_source_sptr +gr_make_message_source(size_t itemsize, int msgq_limit) +{ + return gr_message_source_sptr(new gr_message_source(itemsize, msgq_limit)); +} + +gr_message_source::gr_message_source (size_t itemsize, int msgq_limit) + : gr_sync_block("message_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false) +{ +} + +gr_message_source::~gr_message_source() +{ +} + +int +gr_message_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nn = 0; + + while (nn < noutput_items){ + if (d_msg){ + // + // Consume whatever we can from the current message + // + int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize)); + memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize); + + nn += mm; + out += mm * d_itemsize; + d_msg_offset += mm * d_itemsize; + assert(d_msg_offset <= d_msg->length()); + + if (d_msg_offset == d_msg->length()){ + if (d_msg->type() == 1) // type == 1 sets EOF + d_eof = true; + d_msg.reset(); + } + } + else { + // + // No current message + // + if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got + break; + } + + if (d_eof) + return -1; + + d_msg = d_msgq->delete_head(); // block, waiting for a message + d_msg_offset = 0; + + if ((d_msg->length() % d_itemsize) != 0) + throw std::runtime_error("msg length is not a multiple of d_itemsize"); + } + } + + return nn; +} diff --git a/gnuradio-core/src/lib/io/gr_message_source.h b/gnuradio-core/src/lib/io/gr_message_source.h new file mode 100644 index 00000000..02060124 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_SOURCE_H +#define INCLUDED_GR_MESSAGE_SOURCE_H + +#include +#include +#include + +class gr_message_source; +typedef boost::shared_ptr gr_message_source_sptr; + +gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); + +/*! + * \brief Turn received messages into a stream + * \ingroup source + */ +class gr_message_source : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + gr_message_sptr d_msg; + unsigned d_msg_offset; + bool d_eof; + + friend gr_message_source_sptr + gr_make_message_source(size_t itemsize, int msgq_limit); + + protected: + gr_message_source (size_t itemsize, int msgq_limit); + + public: + ~gr_message_source (); + + gr_msg_queue_sptr msgq() const { return d_msgq; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_source.i b/gnuradio-core/src/lib/io/gr_message_source.i new file mode 100644 index 00000000..369112ef --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_source); + +gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); + +class gr_message_source : public gr_sync_block +{ + protected: + gr_message_source (size_t itemsize, int msgq_limit); + + public: + ~gr_message_source (); + + gr_msg_queue_sptr msgq() const; +}; diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.cc b/gnuradio-core/src/lib/io/gr_oscope_guts.cc new file mode 100644 index 00000000..6636fff1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.cc @@ -0,0 +1,382 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +static const int OUTPUT_RECORD_SIZE = 2048; // must be power of 2 + +static inline int +wrap_bi (int buffer_index) // wrap buffer index +{ + return buffer_index & (OUTPUT_RECORD_SIZE - 1); +} + +static inline int +incr_bi (int buffer_index) // increment buffer index +{ + return wrap_bi (buffer_index + 1); +} + +static inline int +decr_bi (int buffer_index) // decrement buffer index +{ + return wrap_bi (buffer_index - 1); +} + +gr_oscope_guts::gr_oscope_guts (int nchannels, double sample_rate, gr_msg_queue_sptr msgq) + : d_nchannels (nchannels), + d_msgq (msgq), + d_trigger_mode (gr_TRIG_POS_SLOPE), + d_trigger_channel (0), + d_sample_rate (sample_rate), + d_update_rate (20), + d_trigger_level (0), + d_obi (0), + d_state (LOOK_FOR_TRIGGER), + d_decimator_count (0), + d_decimator_count_init (1), + d_hold_off_count (0), + d_hold_off_count_init (0), + d_post_trigger_count (0), + d_post_trigger_count_init (OUTPUT_RECORD_SIZE/2), + d_prev_sample (0) +{ + if (d_nchannels > MAX_CHANNELS){ + fprintf (stderr, "gr_oscope_guts: too many channels. MAX_CHANNELS = %d\n", MAX_CHANNELS); + throw std::runtime_error ("too many channels"); + } + + for (int i = 0; i < MAX_CHANNELS; i++) + d_buffer[i] = 0; + + for (int i = 0; i < d_nchannels; i++) + d_buffer[i] = new float [OUTPUT_RECORD_SIZE]; + + update_rate_or_decimation_changed (); + enter_look_for_trigger (); +} + +gr_oscope_guts::~gr_oscope_guts () +{ + for (int i = 0; i < MAX_CHANNELS; i++) + delete [] d_buffer[i]; +} + +// MANIPULATORS + +// \p channel_data points to nchannels float values. These are the values +// for each channel at this sample time. + +void +gr_oscope_guts::process_sample (const float *channel_data) +{ + d_decimator_count--; + if (d_decimator_count > 0) + return; + + d_decimator_count = d_decimator_count_init; + + for (int i = 0; i < d_nchannels; i++) + d_buffer[i][d_obi] = channel_data[i]; // copy data into buffer + + int trigger = 0; + + switch (d_state){ + case HOLD_OFF: + d_hold_off_count--; + if (d_hold_off_count <= 0) + enter_look_for_trigger (); + break; + + case LOOK_FOR_TRIGGER: + trigger = found_trigger (d_buffer[d_trigger_channel][d_obi]); + if (trigger != 0){ + enter_post_trigger (); + if (trigger < 0) // previous sample was closer + d_post_trigger_count--; + } + break; + + case POST_TRIGGER: + d_post_trigger_count--; + if (d_post_trigger_count <= 0){ + write_output_records (); + enter_hold_off (); + } + break; + + default: + assert (0); + } + + d_obi = incr_bi (d_obi); +} + +/* + * Functions called on state entry + */ + +void +gr_oscope_guts::enter_hold_off () +{ + d_state = HOLD_OFF; + d_hold_off_count = d_hold_off_count_init; +} + +void +gr_oscope_guts::enter_look_for_trigger () +{ + d_state = LOOK_FOR_TRIGGER; + d_prev_sample = d_buffer[d_trigger_channel][d_obi]; +} + +void +gr_oscope_guts::enter_post_trigger () +{ + d_state = POST_TRIGGER; + d_post_trigger_count = d_post_trigger_count_init; +} + +// ---------------------------------------------------------------- +// returns 0 if no trigger found. +// returns +1 if this sample is the trigger point +// returns -1 if the previous sample is the trigger point + +int +gr_oscope_guts::found_trigger (float new_sample) +{ + float prev_sample = d_prev_sample; + d_prev_sample = new_sample; + bool trig; + + switch (d_trigger_mode){ + + case gr_TRIG_AUTO: // always trigger + return +1; + + case gr_TRIG_POS_SLOPE: + trig = prev_sample < d_trigger_level && new_sample >= d_trigger_level; + if (trig){ + if (fabs (prev_sample - d_trigger_level) < fabs (new_sample - d_trigger_level)) + return -1; + else + return +1; + } + return 0; + + case gr_TRIG_NEG_SLOPE: + trig = prev_sample > d_trigger_level && new_sample <= d_trigger_level; + if (trig){ + if (fabs (prev_sample - d_trigger_level) < fabs (new_sample - d_trigger_level)) + return -1; + else + return +1; + } + return 0; + + default: + assert (0); + return 0; + } +} + +// ---------------------------------------------------------------- +// write output records (duh!) + +void +gr_oscope_guts::write_output_records () +{ + // if the output queue if full, drop the data on the ground. + if (d_msgq->full_p()) + return; + + // Build a message to hold the output records + gr_message_sptr msg = + gr_make_message(0, // msg type + d_nchannels, // arg1 for other side + OUTPUT_RECORD_SIZE, // arg2 for other side + d_nchannels * OUTPUT_RECORD_SIZE * sizeof(float)); // sizeof payload + + float *out = (float *)msg->msg(); // get pointer to raw message buffer + + for (int ch = 0; ch < d_nchannels; ch++){ + // note that d_obi points at the oldest sample in the buffer + for (int i = 0; i < OUTPUT_RECORD_SIZE; i++) + out[i] = d_buffer[ch][wrap_bi(d_obi + i)]; + + out += OUTPUT_RECORD_SIZE; + } + + d_msgq->handle(msg); // send the msg +} + +// ---------------------------------------------------------------- + +bool +gr_oscope_guts::set_update_rate (double update_rate) +{ + d_update_rate = std::min (std::max (1./10., update_rate), d_sample_rate); + update_rate_or_decimation_changed (); + return true; +} + +bool +gr_oscope_guts::set_decimation_count (int decimator_count) +{ + decimator_count = std::max (1, decimator_count); + d_decimator_count_init = decimator_count; + update_rate_or_decimation_changed (); + return true; +} + +bool +gr_oscope_guts::set_sample_rate(double sample_rate) +{ + d_sample_rate = sample_rate; + return set_update_rate(update_rate()); +} + + +void +gr_oscope_guts::update_rate_or_decimation_changed () +{ + d_hold_off_count_init = + (int) rint (d_sample_rate / d_update_rate / d_decimator_count_init); +} + +bool +gr_oscope_guts::set_trigger_channel (int channel) +{ + if (channel >= 0 && channel < d_nchannels){ + d_trigger_channel = channel; + trigger_changed (); + return true; + } + + return false; +} + +bool +gr_oscope_guts::set_trigger_mode (gr_trigger_mode mode) +{ + switch (mode){ + case gr_TRIG_POS_SLOPE: + case gr_TRIG_NEG_SLOPE: + case gr_TRIG_AUTO: + d_trigger_mode = mode; + trigger_changed (); + return true; + } + return false; +} + +bool +gr_oscope_guts::set_trigger_level (double trigger_level) +{ + d_trigger_level = trigger_level; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_level_auto () +{ + // find the level 1/2 way between the min and the max + + float min_v = d_buffer[d_trigger_channel][0]; + float max_v = d_buffer[d_trigger_channel][0]; + + for (int i = 1; i < OUTPUT_RECORD_SIZE; i++){ + min_v = std::min (min_v, d_buffer[d_trigger_channel][i]); + max_v = std::max (max_v, d_buffer[d_trigger_channel][i]); + } + + d_trigger_level = (min_v + max_v) * 0.5; + trigger_changed (); + return true; +} + +void +gr_oscope_guts::trigger_changed () +{ + // d_prev_sample = d_buffer[d_trigger_channel][decr_bi(d_obi)]; + enter_look_for_trigger (); +} + +// ACCESSORS + +int +gr_oscope_guts::num_channels () const +{ + return d_nchannels; +} + +double +gr_oscope_guts::sample_rate () const +{ + return d_sample_rate; +} + +double +gr_oscope_guts::update_rate () const +{ + return d_update_rate; +} + +int +gr_oscope_guts::get_decimation_count () const +{ + return d_decimator_count_init; +} + +int +gr_oscope_guts::get_trigger_channel () const +{ + return d_trigger_channel; +} + +gr_trigger_mode +gr_oscope_guts::get_trigger_mode () const +{ + return d_trigger_mode; +} + +double +gr_oscope_guts::get_trigger_level () const +{ + return d_trigger_level; +} + +int +gr_oscope_guts::get_samples_per_output_record () const +{ + return OUTPUT_RECORD_SIZE; +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.h b/gnuradio-core/src/lib/io/gr_oscope_guts.h new file mode 100644 index 00000000..4094a653 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.h @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef INCLUDED_GR_OSCOPE_GUTS_H +#define INCLUDED_GR_OSCOPE_GUTS_H + +#include +#include + +/*! + * \brief guts of oscilloscope trigger and buffer module + * + * This module processes sets of samples provided the \p process_sample + * method. When appropriate given the updateRate, sampleRate and + * trigger conditions, process_sample will periodically write output + * records of captured data to output_fd. For each trigger event, + * nchannels records will be written. Each record consists of + * get_samples_per_output_record binary floats. The trigger instant + * occurs at the 1/2 way point in the buffer. Thus, output records + * consist of 50% pre-trigger data and 50% post-trigger data. + */ + +class gr_oscope_guts { +private: + static const int MAX_CHANNELS = 16; + enum scope_state { HOLD_OFF, LOOK_FOR_TRIGGER, POST_TRIGGER }; + + int d_nchannels; // how many channels + gr_msg_queue_sptr d_msgq; // message queue we stuff output records into + gr_trigger_mode d_trigger_mode; + int d_trigger_channel; // which channel to watch for trigger condition + double d_sample_rate; // input sample rate in Hz + double d_update_rate; // approx freq to produce an output record (Hz) + double d_trigger_level; + + int d_obi; // output buffer index + float *d_buffer[MAX_CHANNELS]; + + scope_state d_state; + int d_decimator_count; + int d_decimator_count_init; + int d_hold_off_count; + int d_hold_off_count_init; + int d_post_trigger_count; + int d_post_trigger_count_init; + float d_prev_sample; // used for trigger checking + + // NOT IMPLEMENTED + gr_oscope_guts (const gr_oscope_guts &rhs); // no copy constructor + gr_oscope_guts &operator= (const gr_oscope_guts &rhs); // no assignment operator + + void trigger_changed (); + void update_rate_or_decimation_changed (); + int found_trigger (float sample); // returns -1, 0, +1 + void write_output_records (); + + void enter_hold_off (); // called on state entry + void enter_look_for_trigger (); + void enter_post_trigger (); + +public: + // CREATORS + gr_oscope_guts (int nchannels, double sample_rate, gr_msg_queue_sptr msgq); + ~gr_oscope_guts (); + + // MANIPULATORS + + /*! + * \p channel_data points to nchannels float values. These are the values + * for each channel at this sample time. + */ + void process_sample (const float *channel_data); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; +}; + +#endif /* INCLUDED_GR_OSCOPE_GUTS_H */ diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink.i b/gnuradio-core/src/lib/io/gr_oscope_sink.i new file mode 100644 index 00000000..ea841990 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink.i @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +enum gr_trigger_mode { + gr_TRIG_AUTO, // auto trigger (on anything) + gr_TRIG_POS_SLOPE, // trigger on positive slope across trigger level + gr_TRIG_NEG_SLOPE // trigger on negative slope across trigger level +}; + +// GR_SWIG_BLOCK_MAGIC(gr,oscope_sink_x) + +%ignore gr_oscope_sink_x; +class gr_oscope_sink_x : public gr_sync_block +{ + protected: + gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sample_rate); + + public: + ~gr_oscope_sink_x (); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(gr,oscope_sink_f) + +gr_oscope_sink_f_sptr +gr_make_oscope_sink_f (double sample_rate, gr_msg_queue_sptr msgq); + +class gr_oscope_sink_f : public gr_oscope_sink_x +{ +private: + gr_oscope_sink_f (double sample_rate, gr_msg_queue_sptr msgq); + +public: + ~gr_oscope_sink_f (); +}; + +// ---------------------------------------------------------------- diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc new file mode 100644 index 00000000..b505381d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_oscope_sink_f_sptr +gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq) +{ + return gr_oscope_sink_f_sptr (new gr_oscope_sink_f (sampling_rate, msgq)); +} + + +gr_oscope_sink_f::gr_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq) + : gr_oscope_sink_x ("oscope_sink_f", + gr_make_io_signature (1, MAX_CHANNELS, sizeof (float)), + sampling_rate), + d_msgq(msgq) +{ +} + + +bool +gr_oscope_sink_f::check_topology (int ninputs, int noutputs) +{ + delete d_guts; + d_guts = 0; + d_guts = new gr_oscope_guts (ninputs, d_sampling_rate, d_msgq); + return true; +} + + +gr_oscope_sink_f::~gr_oscope_sink_f () +{ +} + +int +gr_oscope_sink_f::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int ni = input_items.size (); + float tmp[MAX_CHANNELS]; + + for (int i = 0; i < noutput_items; i++){ + + // FIXME for now, copy the data. Fix later if reqd + for (int ch = 0; ch < ni; ch++) + tmp[ch] = ((const float *) input_items[ch])[i]; + + d_guts->process_sample (tmp); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_f.h b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h new file mode 100644 index 00000000..7b92a785 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_OSCOPE_SINK_F_H +#define INCLUDED_GR_OSCOPE_SINK_F_H + +#include +#include + +class gr_oscope_sink_f; +typedef boost::shared_ptr gr_oscope_sink_f_sptr; + +gr_oscope_sink_f_sptr gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + +/*! + * \brief Building block for python oscilloscope module. + * \ingroup sink + * + * Accepts 1 to 16 float streams. + */ +class gr_oscope_sink_f : public gr_oscope_sink_x +{ +public: + static const int MAX_CHANNELS = 16; + +private: + friend gr_oscope_sink_f_sptr + gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + gr_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + gr_msg_queue_sptr d_msgq; + + public: + ~gr_oscope_sink_f (); + + 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); +}; + +#endif /* INCLUDED_GR_OSCOPE_SINK_F_H */ + diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc new file mode 100644 index 00000000..51c28678 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_oscope_sink_x::gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sampling_rate) + : gr_sync_block (name, input_sig, gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), d_guts (0) +{ +} + +gr_oscope_sink_x::~gr_oscope_sink_x () +{ + delete d_guts; +} + +// ---------------------------------------------------------------- + +bool +gr_oscope_sink_x::set_update_rate (double update_rate) +{ + return d_guts->set_update_rate (update_rate); +} + +bool +gr_oscope_sink_x::set_decimation_count (int decimation_count) +{ + return d_guts->set_decimation_count (decimation_count); +} + +bool +gr_oscope_sink_x::set_trigger_channel (int channel) +{ + return d_guts->set_trigger_channel (channel); +} + +bool +gr_oscope_sink_x::set_trigger_mode (gr_trigger_mode mode) +{ + return d_guts->set_trigger_mode (mode); +} + +bool +gr_oscope_sink_x::set_trigger_level (double trigger_level) +{ + return d_guts->set_trigger_level (trigger_level); +} + + +bool +gr_oscope_sink_x::set_trigger_level_auto () +{ + return d_guts->set_trigger_level_auto (); +} + +bool +gr_oscope_sink_x::set_sample_rate (double sample_rate) +{ + return d_guts->set_sample_rate (sample_rate); +} + +// ACCESSORS + +int +gr_oscope_sink_x::num_channels () const +{ + return d_guts->num_channels (); +} + +double +gr_oscope_sink_x::sample_rate () const +{ + return d_guts->sample_rate (); +} + +double +gr_oscope_sink_x::update_rate () const +{ + return d_guts->update_rate (); +} + +int +gr_oscope_sink_x::get_decimation_count () const +{ + return d_guts->get_decimation_count (); +} + +int +gr_oscope_sink_x::get_trigger_channel () const +{ + return d_guts->get_trigger_channel (); +} + +gr_trigger_mode +gr_oscope_sink_x::get_trigger_mode () const +{ + return d_guts->get_trigger_mode (); +} + +double +gr_oscope_sink_x::get_trigger_level () const +{ + return d_guts->get_trigger_level (); +} + +int +gr_oscope_sink_x::get_samples_per_output_record () const +{ + return d_guts->get_samples_per_output_record (); +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_x.h b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h new file mode 100644 index 00000000..45cccc0d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_OSCOPE_SINK_X_H +#define INCLUDED_GR_OSCOPE_SINK_X_H + +#include +#include + +class gr_oscope_guts; + +/*! + * \brief Abstract class for python oscilloscope module. + * \ingroup sink + * + * Don't instantiate this. Use gr_oscope_sink_f or gr_oscope_sink_c instead. + */ +class gr_oscope_sink_x : public gr_sync_block +{ +protected: + double d_sampling_rate; + gr_oscope_guts *d_guts; + + gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sampling_rate); + +public: + ~gr_oscope_sink_x (); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; + +}; + +#endif /* INCLUDED_GR_OSCOPE_SINK_X_H */ diff --git a/gnuradio-core/src/lib/io/gr_trigger_mode.h b/gnuradio-core/src/lib/io/gr_trigger_mode.h new file mode 100644 index 00000000..0928c6a3 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_trigger_mode.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_TRIGGER_MODE_H +#define INCLUDED_GR_TRIGGER_MODE_H + +enum gr_trigger_mode { + gr_TRIG_AUTO, // auto trigger (on anything) + gr_TRIG_POS_SLOPE, // trigger on positive slope across trigger level + gr_TRIG_NEG_SLOPE // trigger on negative slope across trigger level +}; + +#endif /* INCLUDED_GR_TRIGGER_MODE_H */ diff --git a/gnuradio-core/src/lib/io/gri_logger.cc b/gnuradio-core/src/lib/io/gri_logger.cc new file mode 100644 index 00000000..a1bdfb0e --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_logger.cc @@ -0,0 +1,173 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + + +/* + * This class creates the thread that reads from the ringbuffer and + * and writes to the file. This is opaque to the user. + */ +class gri_log_poster : public omni_thread +{ + FILE *d_fp; + gr_buffer_sptr d_writer; + gr_buffer_reader_sptr d_reader; + omni_semaphore d_ringbuffer_ready; + volatile bool d_time_to_die; + volatile bool d_writer_overrun; + + virtual void* run_undetached(void * arg); + +public: + gri_log_poster(const char *filename); + ~gri_log_poster(); + + void kill() { d_time_to_die = true; post(); } + gr_buffer_sptr writer() const { return d_writer; } + void post() { d_ringbuffer_ready.post(); } + void note_writer_overrun() { d_writer_overrun = true; } +}; + +gri_log_poster::gri_log_poster(const char *filename) + : omni_thread(), + d_ringbuffer_ready(1, 1), // binary semaphore + d_time_to_die(false), + d_writer_overrun(false) +{ + if ((d_fp = fopen(filename, "w")) == 0){ + perror (filename); + throw std::runtime_error("can't open file"); + } + + // Create a 1MB buffer. + d_writer = gr_make_buffer(1 * 1024 * 1024, sizeof(unsigned char)); + d_reader = gr_buffer_add_reader(d_writer, 0); + + start_undetached(); // start the thread +} + +gri_log_poster::~gri_log_poster() +{ + if (d_fp != 0){ + fclose(d_fp); + d_fp = 0; + } +} + +/* + * This is the body of the logging thread. + */ +void * +gri_log_poster::run_undetached(void *arg) +{ + int nbytes; + + //fprintf(stderr, "Enter: run_undetached!\n"); + + while (!d_time_to_die){ + while ((nbytes = d_reader->items_available()) > 0){ + fwrite(d_reader->read_pointer(), 1, nbytes, d_fp); + d_reader->update_read_pointer(nbytes); + } + fflush(d_fp); + d_ringbuffer_ready.wait(); + + if (d_writer_overrun){ + fputs(">>>>> gri_logger: writer overrun. Info lost <<<<<\n", d_fp); + d_writer_overrun = false; + } + } + + // fprintf(stderr, "Exit: run_undetached!\n"); + return 0; +} + +// ------------------------------------------------------------------------ + +static boost::weak_ptr s_singleton; // weak pointer IQ test ;-) +static omni_mutex s_singleton_mutex; + +gri_logger_sptr +gri_logger::singleton() +{ + omni_mutex_lock l(s_singleton_mutex); + gri_logger_sptr r; + + if (r = s_singleton.lock()) + return r; + + r = gri_logger_sptr(new gri_logger("gri_logger.log")); + s_singleton = r; + return r; +} + + +gri_logger::gri_logger(const char *filename) +{ + d_poster = new gri_log_poster(filename); +} + +gri_logger::~gri_logger() +{ + d_poster->kill(); + d_poster->join(NULL); +} + +void +gri_logger::write(const void *buf, size_t count) +{ + omni_mutex_lock l(d_write_mutex); + gr_buffer_sptr writer = d_poster->writer(); + + // either write it all, or drop it on the ground + if (count <= (size_t) writer->space_available()){ + memcpy(writer->write_pointer(), buf, count); + writer->update_write_pointer(count); + d_poster->post(); + } + else { + d_poster->note_writer_overrun(); + } +} + +void +gri_logger::printf(const char *format, ...) +{ + va_list ap; + char buf[4096]; + int n; + + va_start(ap, format); + n = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + if (n > -1 && n < (ssize_t) sizeof(buf)) + write(buf, n); +} diff --git a/gnuradio-core/src/lib/io/gri_logger.h b/gnuradio-core/src/lib/io/gri_logger.h new file mode 100644 index 00000000..ecbd3141 --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_logger.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GRI_LOGGER_H +#define INCLUDED_GRI_LOGGER_H + +#include +#include +#include + +class gri_log_poster; +class gri_logger; +typedef boost::shared_ptr gri_logger_sptr; + + +/*! + * \brief non-blocking logging to a file. + * + * In reality, this may block, but only for a bounded time. + * Trust me, it's safe to use from portaudio and JACK callbacks. + */ +class gri_logger +{ + gri_log_poster *d_poster; + omni_mutex d_write_mutex; + +public: + static gri_logger_sptr singleton(); + + gri_logger(const char *filename); + ~gri_logger(); + + void write(const void *buf, size_t count); + void printf(const char *format, ...); +}; + +#endif /* INCLUDED_GRI_LOGGER_H */ diff --git a/gnuradio-core/src/lib/io/i2c.cc b/gnuradio-core/src/lib/io/i2c.cc new file mode 100644 index 00000000..9b9fbcd1 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.cc @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "i2c.h" + +i2c::~i2c () +{ + // NOP +} diff --git a/gnuradio-core/src/lib/io/i2c.h b/gnuradio-core/src/lib/io/i2c.h new file mode 100644 index 00000000..88b3c913 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_H +#define INCLUDED_I2C_H + +#include + +class i2c; +typedef boost::shared_ptr i2c_sptr; + +/*! + * \brief abstract class for controlling i2c bus + */ +class i2c { + public: + + i2c () {} + virtual ~i2c (); + + //! \returns true iff successful + virtual bool write (int addr, const unsigned char *buf, int nbytes) = 0; + + //! \returns number of bytes read or -1 if error + virtual int read (int addr, unsigned char *buf, int max_bytes) = 0; +}; + +#endif /* INCLUDED_I2C_H */ + diff --git a/gnuradio-core/src/lib/io/i2c_bbio.cc b/gnuradio-core/src/lib/io/i2c_bbio.cc new file mode 100644 index 00000000..8f383976 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.cc @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "i2c_bbio.h" + +i2c_bbio::~i2c_bbio () +{ + // NOP +} + diff --git a/gnuradio-core/src/lib/io/i2c_bbio.h b/gnuradio-core/src/lib/io/i2c_bbio.h new file mode 100644 index 00000000..f0ea3b66 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_BBIO_H +#define INCLUDED_I2C_BBIO_H + +#include + +class i2c_bbio; +typedef boost::shared_ptr i2c_bbio_sptr; + + +/*! + * \brief abstract class that implements bit banging i/o for i2c bus. + */ +class i2c_bbio { + public: + + i2c_bbio () {} + virtual ~i2c_bbio (); + + virtual void set_scl (bool state) = 0; + virtual void set_sda (bool state) = 0; + virtual bool get_sda () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + +#endif /* INCLUDED_I2C_BBIO_H */ diff --git a/gnuradio-core/src/lib/io/i2c_bbio_pp.cc b/gnuradio-core/src/lib/io/i2c_bbio_pp.cc new file mode 100644 index 00000000..125f01c3 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "i2c_bbio_pp.h" +#include "microtune_eval_board_defs.h" + +i2c_bbio_pp::i2c_bbio_pp (ppio_sptr pp) +{ + d_pp = pp; + d_pp->lock (); + d_pp->write_control (d_pp->read_control () & ~UT_CP_MUST_BE_ZERO); // output, no interrupts + d_pp->unlock (); +} + +i2c_bbio_sptr +make_i2c_bbio_pp (ppio_sptr pp) +{ + return i2c_bbio_sptr (new i2c_bbio_pp (pp)); +} + +void +i2c_bbio_pp::set_scl (bool state) +{ + int r = d_pp->read_control(); + + if (!state){ // active low + d_pp->write_control (r | UT_CP_TUNER_SCL); + } + else { + d_pp->write_control (r & ~UT_CP_TUNER_SCL); + } + d_pp->read_control (); // use for 1us delay + d_pp->read_control (); // use for 1us delay +} + +void +i2c_bbio_pp::set_sda (bool state) +{ + int r = d_pp->read_data (); + + if (!state){ // active low + d_pp->write_data (r | UT_DP_TUNER_SDA_OUT); + } + else { + d_pp->write_data (r & ~UT_DP_TUNER_SDA_OUT); + } + d_pp->read_data (); // use for 1us delay + d_pp->read_data (); // use for 1us delay +} + +bool +i2c_bbio_pp::get_sda () +{ + int r = d_pp->read_status (); + return (r & UT_SP_TUNER_SDA_IN) == 0; // eval board has an inverter on it +} + +void +i2c_bbio_pp::lock () +{ + d_pp->lock (); +} + +void +i2c_bbio_pp::unlock () +{ + d_pp->unlock (); +} diff --git a/gnuradio-core/src/lib/io/i2c_bbio_pp.h b/gnuradio-core/src/lib/io/i2c_bbio_pp.h new file mode 100644 index 00000000..25af0cf4 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_BBIO_PP_H +#define INCLUDED_I2C_BBIO_PP_H + +#include "i2c_bbio.h" +#include "ppio.h" + +/*! + * \brief concrete class that bit bangs eval board i2c bus using parallel port + * + * This class talks to the i2c bus on the microtune eval board using + * the parallel port. This works for both the 4937 and 4702 boards. + */ +class i2c_bbio_pp : public i2c_bbio { + friend i2c_bbio_sptr make_i2c_bbio_pp (ppio_sptr pp); + i2c_bbio_pp (ppio_sptr pp); + + public: + + virtual void set_scl (bool state); + virtual void set_sda (bool state); + virtual bool get_sda (); + + virtual void lock (); + virtual void unlock (); + + private: + ppio_sptr d_pp; +}; + +i2c_bbio_sptr make_i2c_bbio_pp (ppio_sptr pp); + + +#endif /* INCLUDED_I2C_BBIO_PP_H */ diff --git a/gnuradio-core/src/lib/io/i2c_bitbang.cc b/gnuradio-core/src/lib/io/i2c_bitbang.cc new file mode 100644 index 00000000..6bf37b60 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "i2c_bitbang.h" + +i2c_bitbang::i2c_bitbang (i2c_bbio_sptr io) +{ + d_io = io; + d_io->lock (); + + stop (); // get bus in known state + + d_io->unlock (); +} + +i2c_sptr +make_i2c_bitbang (i2c_bbio_sptr io) +{ + return i2c_sptr (new i2c_bitbang (io)); +} + + +// start: +// entry: SCL = 1, SDA = 1 +// exit: SCL = 0, SDA = 0 + +void +i2c_bitbang::start () +{ + set_sda (1); + set_scl (1); + set_sda (0); // SDA high -> low while SCL high + set_scl (0); +} + + +// stop: +// entry: SCL = X, SDA = X +// exit: SCL = 1, SDA = 1 + +void +i2c_bitbang::stop () +{ + set_scl (0); + set_sda (0); + set_scl (1); + set_sda (1); // SDA low -> high while SCL high +} + + +// write_bit: +// entry: SCL = 0, SDA = X +// exit: SCL = 0, SDA = X + +void +i2c_bitbang::write_bit (bool bit) +{ + set_sda (bit); + set_scl (1); + set_scl (0); +} + + +// write_byte: +// entry: SCL = 0, SDA = X +// exit: SCL = 0, SDA = 1 + +bool +i2c_bitbang::write_byte (char t) +{ + int i; + bool ack_bit; + + for (i = 0; i < 8; i++){ + write_bit (t & 0x80); + t <<= 1; + } + + // clock #9. This is the ACK bit. + + set_sda (1); // tristate SDA + set_scl (1); + ack_bit = get_sda (); // slave should pull SDA line low + set_scl (0); + + return ack_bit == 0; +} + + +// write: the high level entry point... +// entry: SCL = 1, SDA = 1 +// exit: SCL = 1, SDA = 1 + +bool +i2c_bitbang::write (int addr, const unsigned char *buf, int nbytes) +{ + bool ok = true; + + d_io->lock (); + start (); + ok = write_byte ((addr << 1) | 0); // addr plus "read opcode" + + for (int i = 0; i < nbytes; i++) + ok &= write_byte (buf[i]); + + stop (); + d_io->unlock (); + return ok; +} + + +// read: the high level entry point... +// entry: SCL = 1, SDA = 1 +// exit: SCL = 1, SDA = 1 + +int +i2c_bitbang::read (int addr, unsigned char *buf, int max_bytes) +{ + d_io->lock (); + + // FIXME + + d_io->unlock (); + return -1; +} diff --git a/gnuradio-core/src/lib/io/i2c_bitbang.h b/gnuradio-core/src/lib/io/i2c_bitbang.h new file mode 100644 index 00000000..5196cd23 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_BITBANG_H +#define INCLUDED_I2C_BITBANG_H + +#include +#include + +/*! + * \brief class for controlling i2c bus + */ +class i2c_bitbang : public i2c { + friend i2c_sptr make_i2c_bitbang (i2c_bbio_sptr io); + i2c_bitbang (i2c_bbio_sptr io); + + public: + ~i2c_bitbang () {} + + //! \returns true iff successful + bool write (int addr, const unsigned char *buf, int nbytes); + + //! \returns number of bytes read or -1 if error + int read (int addr, unsigned char *buf, int max_bytes); + + +private: + void start (); + void stop (); + void write_bit (bool bit); + bool write_byte (char byte); + + void set_sda (bool bit) { d_io->set_sda (bit); } + void set_scl (bool bit) { d_io->set_scl (bit); } + bool get_sda () { return d_io->get_sda (); } + + i2c_bbio_sptr d_io; +}; + +i2c_sptr make_i2c_bitbang (i2c_bbio_sptr io); + +#endif /* INCLUDED_I2C_BITBANG_H */ + + diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i new file mode 100644 index 00000000..ae4ca268 --- /dev/null +++ b/gnuradio-core/src/lib/io/io.i @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +%} + +%include "gr_file_sink.i" +%include "gr_file_source.i" +%include "gr_file_descriptor_sink.i" +%include "gr_file_descriptor_source.i" +%include "microtune_xxxx_eval_board.i" +%include "microtune_4702_eval_board.i" +%include "microtune_4937_eval_board.i" +%include "sdr_1000.i" +%include "gr_oscope_sink.i" +%include "ppio.i" +%include "gr_message_source.i" +%include "gr_message_sink.i" + diff --git a/gnuradio-core/src/lib/io/microtune_4702.cc b/gnuradio-core/src/lib/io/microtune_4702.cc new file mode 100644 index 00000000..9b180ff8 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.cc @@ -0,0 +1,183 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "microtune_4702.h" +#include +#include +#include "i2c.h" + +static const double FIRST_IF = 36.00e6; + +// The tuner internally has 3 bands: VHF Low, VHF High & UHF. +// These are the recommened boundaries +static const double VHF_High_takeover = 174e6; +static const double UHF_takeover = 470e6; + +static int PLL_I2C_ADDR = 0x60; + +static unsigned char +control_byte_1 (bool prescaler, int reference_divisor) +{ + int c = 0x80; + //Note: Last two divider bits (bits 2 and 3 of this byte) determined later + if (prescaler) + c |= 0x10; + + switch (reference_divisor){ + case 2: + c |= 0x00; break; + case 4: + c |= 0x01; break; + case 8: + c |= 0x02; break; + case 16: + c |= 0x03; break; + case 32: + c |= 0x04; break; + case 64: + c |= 0x05; break; + case 128: + c |= 0x06; break; + case 256: + c |= 0x07; break; + case 24: + c |= 0x08; break; + case 5: + c |= 0x09; break; + case 10: + c |= 0x0A; break; + case 20: + c |= 0x0B; break; + case 40: + c |= 0x0C; break; + case 80: + c |= 0x0D; break; + case 160: + c |= 0x0E; break; + case 320: + c |= 0x0F; break; + default: + abort (); + } + return c; +} + +static unsigned char +control_byte_2 (double target_freq) +{ + int c; + + if (target_freq < VHF_High_takeover) // VHF low + c = 0x8E; + + else if (target_freq < UHF_takeover){ // VHF high + c = 0x05; + if (target_freq < 390e6) + c |= 0x40; + else + c |= 0x80; + } + else { // UHF + c = 0x03; + if (target_freq < 750e6) + c |= 0x80; + else + c |= 0xC0; + } + + return c; +} + + +microtune_4702::microtune_4702 (i2c_sptr i2c, int i2c_addr) +{ + d_i2c = i2c; + d_i2c_addr = i2c_addr; + d_reference_divider = 320; + d_prescaler = false; +} + +microtune_4702::~microtune_4702 () +{ + // nop +} + +/*! + * \brief select RF frequency to be tuned to output frequency. + * \p target_freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ +bool +microtune_4702::set_RF_freq (double target_freq, double *p_actual_freq) +{ + unsigned char buf[4]; + + double target_f_osc = target_freq + FIRST_IF; + + double f_ref = 4e6 / d_reference_divider; + + //int divisor = (int) ((target_f_osc + (f_ref * 4)) / (f_ref * 8)); + + long int divisor = (long int) (target_f_osc / f_ref); + double actual_freq = (f_ref * divisor) - FIRST_IF; + if (p_actual_freq != 0) + *p_actual_freq = actual_freq; + + if ((divisor & ~0x1ffff) != 0) // >17 bit divisor + return false; + + buf[0] = ((divisor & 0x07f00) >> 8) & 0xff; // DB1 + buf[1] = divisor & 0xff; // DB2 + buf[2] = control_byte_1 (d_prescaler, d_reference_divider); + buf[2] = (buf[2]|(((divisor & 0x18000) >> 10)) & 0xff); + buf[3] = control_byte_2 (target_freq); + + printf ("%x\n", PLL_I2C_ADDR); +//#if 0 + printf ("set_RF_freq: target: %g MHz actual: %g MHz %02x %02x %02x %02x\n", + target_freq/1e6, actual_freq/1e6, buf[0], buf[1], buf[2], buf[3]); +//#endif + + return d_i2c->write (d_i2c_addr, buf, sizeof (buf)); +} + +/*! + * \returns true iff PLL is locked + */ +bool +microtune_4702::pll_locked_p () +{ + // FIXME + return true; +} + +/*! + * \returns the output frequency of the tuner in Hz. + */ +double +microtune_4702::get_output_freq () +{ + return FIRST_IF; +} diff --git a/gnuradio-core/src/lib/io/microtune_4702.h b/gnuradio-core/src/lib/io/microtune_4702.h new file mode 100644 index 00000000..b5890774 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4702_H +#define INCLUDED_MICROTUNE_4702_H + +#include + +/*! + * \brief class for controlling microtune 4702 tuner module + */ + +class microtune_4702 : public microtune_xxxx { +public: + microtune_4702 (i2c_sptr i2c, int i2c_addr); + + virtual ~microtune_4702 (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency of the tuner in Hz. + */ + double get_output_freq (); + + private: + + i2c_sptr d_i2c; + int d_i2c_addr; + int d_reference_divider; + bool d_prescaler; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +#endif /* INCLUDED_MICROTUNE_4702_H */ + diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc b/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc new file mode 100644 index 00000000..88cf2b6a --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "microtune_4702_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "ppio.h" +#include "microtune_4702.h" + +static const int TUNER_I2C_ADDR = 0x60; + +microtune_4702_eval_board::microtune_4702_eval_board (int which_pp) + : microtune_xxxx_eval_board (which_pp) +{ + d_tuner = new microtune_4702 (d_i2c, TUNER_I2C_ADDR); +} + +microtune_4702_eval_board::~microtune_4702_eval_board () +{ + // default is OK +} + +static const float RF_MIN_V = 1.0; // RF AGC control voltages +static const float RF_MAX_V = 4.0; +static const float IF_MIN_V = 2.0; // IF AGC control voltages +static const float IF_MAX_V = 4.0; + +static const float MIN_AGC = 0; // bottom of synthetic range +static const float MAX_AGC = 1000; // top of synthetic range + +static const float CUTOVER_POINT = 667; + + +// linear is in the range MIN_AGC to MAX_AGC + +static float +linear_to_RF_AGC_voltage (float linear) +{ + if (linear >= CUTOVER_POINT) + return RF_MAX_V; + + float slope = (RF_MAX_V - RF_MIN_V) / CUTOVER_POINT; + return RF_MIN_V + linear * slope; +} + +static float +linear_to_IF_AGC_voltage (float linear) +{ + if (linear < CUTOVER_POINT) + return IF_MIN_V; + + float slope = (IF_MAX_V - IF_MIN_V) / (MAX_AGC - CUTOVER_POINT); + return IF_MIN_V + (linear - CUTOVER_POINT) * slope; +} + +void +microtune_4702_eval_board::set_AGC (float v) +{ + if (v < MIN_AGC) + v = MIN_AGC; + + if (v > MAX_AGC) + v = MAX_AGC; + + float rf_agc_voltage = linear_to_RF_AGC_voltage (v); + float if_agc_voltage = linear_to_IF_AGC_voltage (v); + + set_RF_AGC_voltage (rf_agc_voltage); + set_IF_AGC_voltage (if_agc_voltage); +} diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.h b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h new file mode 100644 index 00000000..9fc2914e --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h @@ -0,0 +1,47 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4702_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4702_EVAL_BOARD_H + +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4702 eval board + */ + +class microtune_4702_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4702_eval_board (int which_pp = 0); + ~microtune_4702_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; + +#endif /* INCLUDED_MICROTUNE_4702_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.i b/gnuradio-core/src/lib/io/microtune_4702_eval_board.i new file mode 100644 index 00000000..6205c930 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.i @@ -0,0 +1,36 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class microtune_4702_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4702_eval_board (int which_pp = 0); + ~microtune_4702_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; diff --git a/gnuradio-core/src/lib/io/microtune_4937.cc b/gnuradio-core/src/lib/io/microtune_4937.cc new file mode 100644 index 00000000..c05f63c1 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.cc @@ -0,0 +1,146 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "microtune_4937.h" +#include +#include +#include + +static const double first_IF = 43.75e6; + +// The tuner internally has 3 bands: VHF Low, VHF High & UHF. +// These are the recommened boundaries +static const double VHF_High_takeover = 158e6; +static const double UHF_takeover = 464e6; + + +static unsigned char +control_byte_1 (bool fast_tuning_p, int reference_divisor) +{ + int c = 0x88; + + if (fast_tuning_p) + c |= 0x40; + + switch (reference_divisor){ + case 512: + c |= 0x3 << 1; break; + case 640: + c |= 0x0 << 1; break; + case 1024: + c |= 0x1 << 1; break; + default: + abort (); + } + return c; +} + +static unsigned char +control_byte_2 (double target_freq, bool shutdown_tx_PGA) +{ + int c; + + if (target_freq < VHF_High_takeover) // VHF low + c = 0xa0; + else if (target_freq < UHF_takeover) // VHF high + c = 0x90; + else // UHF + c = 0x30; + + if (shutdown_tx_PGA) + c |= 0x08; + + return c; +} + +microtune_4937::microtune_4937 (i2c_sptr i2c, int i2c_addr) +{ + d_i2c = i2c; + d_i2c_addr = i2c_addr; + d_reference_divider = 640; + d_fast_tuning_p = false; +} + +microtune_4937::~microtune_4937 () +{ + // nop +} + +/*! + * \brief select RF frequency to be tuned to output frequency. + * \p target_freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ +bool +microtune_4937::set_RF_freq (double target_freq, double *p_actual_freq) +{ + unsigned char buf[4]; + + double target_f_osc = target_freq + first_IF; + + double f_ref = 4e6 / d_reference_divider; + + // f_osc = f_ref * 8 * divisor + // divisor = f_osc / (f_ref * 8) + + int divisor = (int) ((target_f_osc + (f_ref * 4)) / (f_ref * 8)); + double actual_freq = (f_ref * 8 * divisor) - first_IF; + if (p_actual_freq != 0) + *p_actual_freq = actual_freq; + + if ((divisor & ~0x7fff) != 0) // 15 bit divisor + return false; + + buf[0] = (divisor >> 8) & 0xff; // DB1 + buf[1] = divisor & 0xff; // DB2 + buf[2] = control_byte_1 (d_fast_tuning_p, d_reference_divider); + buf[3] = control_byte_2 (target_freq, true); + +#if 0 + printf ("set_RF_freq: target: %g MHz actual: %g MHz %02x %02x %02x %02x\n", + target_freq/1e6, actual_freq/1e6, buf[0], buf[1], buf[2], buf[3]); +#endif + + return d_i2c->write (d_i2c_addr, buf, 4); +} + +/*! + * \returns true iff PLL is locked + */ +bool +microtune_4937::pll_locked_p () +{ + // FIXME + return true; +} + +/*! + * \returns the output frequency of the tuner in Hz. + */ +double +microtune_4937::get_output_freq () +{ + return 5.75e6; // 3x7702 +} diff --git a/gnuradio-core/src/lib/io/microtune_4937.h b/gnuradio-core/src/lib/io/microtune_4937.h new file mode 100644 index 00000000..84c8d611 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4937_H +#define INCLUDED_MICROTUNE_4937_H + +#include + +/*! + * \brief class for controlling microtune 4937 tuner module + */ +class microtune_4937 : public microtune_xxxx { +public: + microtune_4937 (i2c_sptr i2c, int i2c_addr = 0x61); + virtual ~microtune_4937 (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + private: + + i2c_sptr d_i2c; + int d_i2c_addr; + int d_reference_divider; + bool d_fast_tuning_p; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +#endif /* INCLUDED_MICROTUNE_4937_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc b/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc new file mode 100644 index 00000000..82a03740 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "microtune_4937_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "ppio.h" +#include "microtune_4937.h" + +static const int TUNER_I2C_ADDR = 0x61; + +microtune_4937_eval_board::microtune_4937_eval_board (int which_pp) + : microtune_xxxx_eval_board (which_pp) +{ + d_tuner = new microtune_4937 (d_i2c, TUNER_I2C_ADDR); + + // disable upstream amplifier + d_ppio->lock (); + int t = d_ppio->read_data (); + t &= ~(UT_DP_TX_ENABLE | UT_DP_TX_SDA | UT_DP_TX_SCL); + t |= UT_DP_TX_AS; + d_ppio->write_data (t); + d_ppio->unlock (); +} + +microtune_4937_eval_board::~microtune_4937_eval_board () +{ + // Default action is OK +} + + +static const float RF_MIN_V = 1.5; // RF AGC control voltages +static const float RF_MAX_V = 4.0; +static const float IF_MIN_V = 2.0; // IF AGC control voltages +static const float IF_MAX_V = 4.0; + +static const float MIN_AGC = 0; // bottom of synthetic range +static const float MAX_AGC = 1000; // top of synthetic range + +static const float CUTOVER_POINT = 667; + + +// linear is in the range MIN_AGC to MAX_AGC + +static float +linear_to_RF_AGC_voltage (float linear) +{ + if (linear >= CUTOVER_POINT) + return RF_MAX_V; + + float slope = (RF_MAX_V - RF_MIN_V) / CUTOVER_POINT; + return RF_MIN_V + linear * slope; +} + +static float +linear_to_IF_AGC_voltage (float linear) +{ + if (linear < CUTOVER_POINT) + return IF_MIN_V; + + float slope = (IF_MAX_V - IF_MIN_V) / (MAX_AGC - CUTOVER_POINT); + return IF_MIN_V + (linear - CUTOVER_POINT) * slope; +} + +void +microtune_4937_eval_board::set_AGC (float v) +{ + if (v < MIN_AGC) + v = MIN_AGC; + + if (v > MAX_AGC) + v = MAX_AGC; + + float rf_agc_voltage = linear_to_RF_AGC_voltage (v); + float if_agc_voltage = linear_to_IF_AGC_voltage (v); + + set_RF_AGC_voltage (rf_agc_voltage); + set_IF_AGC_voltage (if_agc_voltage); +} diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.h b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h new file mode 100644 index 00000000..8a8f46b0 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h @@ -0,0 +1,48 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4937_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4937_EVAL_BOARD_H + +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4937 eval board + */ + +class microtune_4937_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4937_eval_board (int which_pp = 0); + ~microtune_4937_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; + + +#endif /* INCLUDED_MICROTUNE_4937_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.i b/gnuradio-core/src/lib/io/microtune_4937_eval_board.i new file mode 100644 index 00000000..106832e3 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.i @@ -0,0 +1,36 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class microtune_4937_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4937_eval_board (int which_pp = 0); + ~microtune_4937_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; diff --git a/gnuradio-core/src/lib/io/microtune_eval_board.i b/gnuradio-core/src/lib/io/microtune_eval_board.i new file mode 100644 index 00000000..7c673e3a --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_eval_board.i @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * SWIG interface defs for Microtune 4937 and eval board with Eric's daughterboard + */ + +/*! + * \brief abstract class for controlling microtune 4937 tuner module + */ +class microtune_4937 { +public: + microtune_4937 (); + + virtual ~microtune_4937 (); + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + + private: + //! \returns true iff successful + virtual bool i2c_write (int addr, const unsigned char *buf, int nbytes) = 0; + + //! \returns number of bytes read or -1 if error + virtual int i2c_read (int addr, unsigned char *buf, int max_bytes) = 0; + + int d_reference_divider; + bool d_fast_tuning_p; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +/*! + * \brief concrete class for controlling microtune 4937 eval board attached to parallel port + */ +class microtune_eval_board : public microtune_4937 { +public: + microtune_eval_board (int which_pp = 0); + ~microtune_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + void set_AGC (float value_0_1000); + +private: + //! \returns true iff successful + virtual bool i2c_write (int addr, const unsigned char *buf, int nbytes); + + //! \returns number of bytes read or -1 if error + virtual int i2c_read (int addr, unsigned char *buf, int max_bytes); +}; diff --git a/gnuradio-core/src/lib/io/microtune_eval_board_defs.h b/gnuradio-core/src/lib/io/microtune_eval_board_defs.h new file mode 100644 index 00000000..5245fd5c --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_eval_board_defs.h @@ -0,0 +1,71 @@ +/* -*-C-*- +******************************************************************************* +* +* File: microtune_eval_board_defs.h +* Description: defines for parallel port control of eval board +* +******************************************************************************* +*/ + +/* + * Copyright 2001 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _MICROTUNE_EVAL_BOARD_DEFS_H_ +#define _MICROTUNE_EVAL_BOARD_DEFS_H_ + +/* + * The Microtune 4937DI5 cable modem tuner eval board is controlled + * by bit banging the PC parallel port. This file defines the relevant + * bits. + * + * The parallel port has an 8 bit data port (output), + * an 8 bit control port (output) and + * an 8 bit status port (input). + * + * Not all bits of the control and status ports may be arbitrarily used. + */ + + +// parallel port data port constants (output) + +static const int UT_DP_TX_SDA = 0x01; // upstream control bus +static const int UT_DP_TX_SCL = 0x02; // upstream control bus +static const int UT_DP_TX_AS = 0x04; // upstream control bus +static const int UT_DP_TX_ENABLE = 0x08; // upstream h/w enable +// bits 4,5,6 not used +static const int UT_DP_TUNER_SDA_OUT = 0x80; // tuner i2c bus data + +// parallel port control port constants (output) + +static const int UT_CP_TUNER_SCL = 0x08; // tuner i2c bus clock +static const int UT_CP_MUST_BE_ZERO = 0xf0; // must be zero + +// parallel port status port constants (input) + +// bits 0,1,2 not used +static const int UT_SP_TUNER_SCL_LOOP_BACK= 0x08; // inverted SCL loop back +static const int UT_SP_SHOULD_BE_ZERO = 0x10; // reads as zero +static const int UT_SP_SHOULD_BE_ONE = 0x20; // reads as one +// bit 6 not used +static const int UT_SP_TUNER_SDA_IN = 0x80; + + +#endif /* _MICROTUNE_EVAL_BOARD_DEFS_H_ */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx.cc b/gnuradio-core/src/lib/io/microtune_xxxx.cc new file mode 100644 index 00000000..8633b111 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.cc @@ -0,0 +1,41 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "microtune_xxxx.h" + +microtune_xxxx::~microtune_xxxx () +{ + // nop +} + +double +microtune_xxxx::set_RF_freq (double target_freq) +{ + double actual_freq = 0.0; + + if (set_RF_freq (target_freq, &actual_freq)) + return actual_freq; + + return 0.0; +} + + diff --git a/gnuradio-core/src/lib/io/microtune_xxxx.h b/gnuradio-core/src/lib/io/microtune_xxxx.h new file mode 100644 index 00000000..8fac06d8 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_XXXX_H +#define INCLUDED_MICROTUNE_XXXX_H + +#include + +class i2c; +typedef boost::shared_ptr i2c_sptr; + +/*! + * \brief abstract class for controlling microtune {4937,4702} tuner modules + */ +class microtune_xxxx { +public: + microtune_xxxx () {} + virtual ~microtune_xxxx (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + virtual bool set_RF_freq (double freq, double *actual_freq) = 0; + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + virtual bool pll_locked_p () = 0; + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + virtual double get_output_freq () = 0; + +}; + +#endif /* INCLUDED_MICROTUNE_XXXX_H */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc new file mode 100644 index 00000000..a7ea98d6 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "microtune_xxxx_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "microtune_xxxx.h" +#include "ppio.h" +#include "i2c_bitbang.h" +#include "i2c_bbio_pp.h" +#include + +static int AGC_DAC_I2C_ADDR = 0x2C; + +microtune_xxxx_eval_board::microtune_xxxx_eval_board (int which_pp) +{ + d_ppio = make_ppio (which_pp); + d_i2c = make_i2c_bitbang (make_i2c_bbio_pp (d_ppio)); + d_tuner = 0; +} + +microtune_xxxx_eval_board::~microtune_xxxx_eval_board () +{ + delete d_tuner; + d_tuner = 0; +} + + +//! is the eval board present? +bool +microtune_xxxx_eval_board::board_present_p () +{ + bool result = true; + d_ppio->lock (); + + int t = d_ppio->read_status (); + if ((t & UT_SP_SHOULD_BE_ZERO) != 0 + || (t & UT_SP_SHOULD_BE_ONE) != UT_SP_SHOULD_BE_ONE) + result = false; + + // could also see if SCL is looped back or not, but that seems like overkill + + d_ppio->unlock (); + return result; +} + +/* + * ---------------------------------------------------------------- + * AGC stuff + * + * We're using a MAX518 8-bit 5V dual dac for setting the AGC's + * ---------------------------------------------------------------- + */ +void +microtune_xxxx_eval_board::write_dac (int which, int value) +{ + unsigned char cmd[2]; + cmd[0] = which & 1; + cmd[1] = value; + d_i2c->write (AGC_DAC_I2C_ADDR, cmd, sizeof (cmd)); +} + +void +microtune_xxxx_eval_board::write_both_dacs (int value0, int value1) +{ + unsigned char cmd[4]; + cmd[0] = 0; + cmd[1] = value0; + cmd[2] = 1; + cmd[3] = value1; + d_i2c->write (AGC_DAC_I2C_ADDR, cmd, sizeof (cmd)); +} + +static int scale_volts (float volts) +{ + int n; + n = (int) rint (volts * (256 / 5.0)); + if (n < 0) + n = 0; + if (n > 255) + n = 255; + + return n; +} + +void +microtune_xxxx_eval_board::set_RF_AGC_voltage (float volts) +{ + write_dac (0, scale_volts (volts)); +} + +void +microtune_xxxx_eval_board::set_IF_AGC_voltage (float volts) +{ + write_dac (1, scale_volts (volts)); +} + +// delegate to tuner + +bool +microtune_xxxx_eval_board::set_RF_freq (double freq, double *actual_freq) +{ + return d_tuner->set_RF_freq (freq, actual_freq); +} + +double +microtune_xxxx_eval_board::set_RF_freq (double freq) +{ + return d_tuner->set_RF_freq (freq); +} + +bool +microtune_xxxx_eval_board::pll_locked_p () +{ + return d_tuner->pll_locked_p (); +} + +double +microtune_xxxx_eval_board::get_output_freq () +{ + return d_tuner->get_output_freq (); +} diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h new file mode 100644 index 00000000..3a817b69 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h @@ -0,0 +1,96 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H + +#include + +class microtune_xxxx; + +class ppio; +typedef boost::shared_ptr ppio_sptr; + +class i2c; +typedef boost::shared_ptr i2c_sptr; + +/*! + * \brief abstract class for controlling microtune xxxx eval board + */ +class microtune_xxxx_eval_board { +public: + microtune_xxxx_eval_board (int which_pp = 0); + virtual ~microtune_xxxx_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000) = 0; + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + +private: + void write_dac (int which, int value); + void write_both_dacs (int val0, int val1); + +protected: + ppio_sptr d_ppio; + i2c_sptr d_i2c; + microtune_xxxx *d_tuner; +}; + +#endif /* INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i new file mode 100644 index 00000000..2e43f27a --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class microtune_xxxx_eval_board { +public: + microtune_xxxx_eval_board (int which_pp = 0); + virtual ~microtune_xxxx_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000) = 0; + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); +}; diff --git a/gnuradio-core/src/lib/io/ppio.cc b/gnuradio-core/src/lib/io/ppio.cc new file mode 100644 index 00000000..86f402bb --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.cc @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +ppio::~ppio () +{ +} + +// Factory method. +// +// Right now, we've only got one subclass we like. If there were more, +// we'd instantiate the "right one" here. + +ppio_sptr +make_ppio (int which_pp) +{ + return make_ppio_ppdev (which_pp); +} diff --git a/gnuradio-core/src/lib/io/ppio.h b/gnuradio-core/src/lib/io/ppio.h new file mode 100644 index 00000000..41813870 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_PPIO_H +#define INCLUDED_PPIO_H + +#include + +class ppio; +typedef boost::shared_ptr ppio_sptr; + + +/*! + * \brief abstract class that provides low level access to parallel port bits + */ + +class ppio { + public: + ppio () {} + virtual ~ppio (); + + virtual void write_data (unsigned char v) = 0; + virtual unsigned char read_data () = 0; + virtual void write_control (unsigned char v) = 0; + virtual unsigned char read_control () = 0; + virtual unsigned char read_status () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + +/*! + * \brief Factory method. + * + * Split out from class to make life easier for SWIG + */ + +ppio_sptr make_ppio (int which_pp); + + +#endif /* INCLUDED_PPIO_H */ + diff --git a/gnuradio-core/src/lib/io/ppio.i b/gnuradio-core/src/lib/io/ppio.i new file mode 100644 index 00000000..2eaddc20 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.i @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class ppio; +typedef boost::shared_ptr ppio_sptr; + +%template(ppio_sptr) boost::shared_ptr; + +/*! + * \brief abstract class that provides low level access to parallel port bits + */ + +class ppio { + public: + ppio () {} + virtual ~ppio (); + + virtual void write_data (unsigned char v) = 0; + virtual unsigned char read_data () = 0; + virtual void write_control (unsigned char v) = 0; + virtual unsigned char read_control () = 0; + virtual unsigned char read_status () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + + +ppio_sptr make_ppio (int which_pp); diff --git a/gnuradio-core/src/lib/io/ppio_ppdev.cc b/gnuradio-core/src/lib/io/ppio_ppdev.cc new file mode 100644 index 00000000..bfdaa3de --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.cc @@ -0,0 +1,221 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_PPDEV_H +#include +#include +#include +#include +#else +// #warn "ppio_ppdev is not functional on this platform" +#endif + +// These control port bits are active low. +// We toggle them so that this weirdness doesn't get get propagated +// through our interface. + +static int CP_ACTIVE_LOW_BITS = 0x0B; + +// These status port bits are active low. +// We toggle them so that this weirdness doesn't get get propagated +// through our interface. + +static int SP_ACTIVE_LOW_BITS = 0x80; + +#ifndef HAVE_LINUX_PPDEV_H // use stubs + +ppio_ppdev::ppio_ppdev (int which) +{ + std::cerr << "ppio_ppdev: Not implemented on this platform\n"; + throw std::runtime_error ("not implmeneted"); +} + +ppio_ppdev::~ppio_ppdev () +{ +} + +void +ppio_ppdev::write_data (unsigned char v) +{ +} + +unsigned char +ppio_ppdev::read_data () +{ + return 0; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ +} + +unsigned char +ppio_ppdev::read_control () +{ + return 0; +} + +unsigned char +ppio_ppdev::read_status () +{ + return 0; +} + +void +ppio_ppdev::lock () +{ +} + +void +ppio_ppdev::unlock () +{ +} + +#else + +// The real code... + +ppio_ppdev::ppio_ppdev (int which) +{ + std::ostringstream filename; + filename << "/dev/parport" << which; + const char *c_filename = filename.str().c_str(); + + if ((d_fd = open (c_filename, O_RDWR)) < 0){ + int my_errno = errno; + perror (c_filename); + if (my_errno == ENOENT){ + std::cerr << "Does the device file " << c_filename << " exist?\n"; + std::cerr << "If not, as root execute: \n"; + std::cerr << " # mknod " << c_filename << " c 99 0\n"; + std::cerr << " # chmod 666 " << c_filename << std::endl; + } + throw std::runtime_error ("open"); + } + + int mode = IEEE1284_MODE_COMPAT; + if (ioctl (d_fd, PPSETMODE, &mode) != 0){ + perror ("ppio_ppdev: PPSETMODE"); + close (d_fd); + throw std::runtime_error ("PPSETMODE"); + } +} + +ppio_ppdev::~ppio_ppdev () +{ + close (d_fd); +} + + +void +ppio_ppdev::write_data (unsigned char v) +{ + if (ioctl (d_fd, PPWDATA, &v) != 0){ + perror ("ppio_ppdev: PPWDATA"); + throw std::runtime_error ("PPWDATA"); + } +} + +unsigned char +ppio_ppdev::read_data () +{ + unsigned char v; + + if (ioctl (d_fd, PPRDATA, &v) != 0){ + perror ("ppio_ppdev: PPRDATA"); + throw std::runtime_error ("PPRDATA"); + } + return v; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ + unsigned char ctrl = v ^ CP_ACTIVE_LOW_BITS; + if (ioctl (d_fd, PPWCONTROL, &ctrl) != 0){ + perror ("ppio_ppdev: PPWCONTROL"); + throw std::runtime_error ("PPWCONTROL"); + } +} + +unsigned char +ppio_ppdev::read_control () +{ + unsigned char ctrl; + if (ioctl (d_fd, PPRCONTROL, &ctrl) != 0){ + perror ("ppio_ppdev: PPRCONTROL"); + throw std::runtime_error ("PPRCONTROL"); + } + + return ctrl ^ CP_ACTIVE_LOW_BITS; +} + +unsigned char +ppio_ppdev::read_status () +{ + unsigned char status; + if (ioctl (d_fd, PPRSTATUS, &status) != 0){ + perror ("ppio_ppdev: PPRSTATUS"); + throw std::runtime_error ("PPRSTATUS"); + } + + return status ^ SP_ACTIVE_LOW_BITS; +} + +void +ppio_ppdev::lock () +{ + if (ioctl (d_fd, PPCLAIM) != 0){ + perror ("ppio_ppdev: PPCLAIM"); + throw std::runtime_error ("PPCLAIM"); + } +} + +void +ppio_ppdev::unlock () +{ + if (ioctl (d_fd, PPRELEASE) != 0){ + perror ("ppio_ppdev: PPRELEASE"); + throw std::runtime_error ("PPRELEASE"); + } +} + +#endif + +ppio_ppdev_sptr +make_ppio_ppdev (int which) +{ + return ppio_ppdev_sptr (new ppio_ppdev (which)); +} diff --git a/gnuradio-core/src/lib/io/ppio_ppdev.h b/gnuradio-core/src/lib/io/ppio_ppdev.h new file mode 100644 index 00000000..8ac4a35d --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_PPIO_PPDEV_H +#define INCLUDED_PPIO_PPDEV_H + +#include + +class ppio_ppdev; +typedef boost::shared_ptr ppio_ppdev_sptr; + +/*! + * \brief access to parallel port bits using the linux ppdev interface + */ + +class ppio_ppdev : public ppio { + friend ppio_ppdev_sptr make_ppio_ppdev (int which = 0); + ppio_ppdev (int which = 0); + + public: + virtual ~ppio_ppdev (); + + virtual void write_data (unsigned char v); + virtual unsigned char read_data (); + virtual void write_control (unsigned char v); + virtual unsigned char read_control (); + virtual unsigned char read_status (); + + virtual void lock (); + virtual void unlock (); + + private: + int d_fd; +}; + +ppio_ppdev_sptr +make_ppio_ppdev (int which); + + +#endif /* INCLUDED_PPIO_PPDEV_H */ + diff --git a/gnuradio-core/src/lib/io/sdr_1000.cc b/gnuradio-core/src/lib/io/sdr_1000.cc new file mode 100644 index 00000000..1cb9b9af --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +sdr_1000_base::sdr_1000_base (int which_pp) +{ + d_ppio = make_ppio (which_pp); + d_shadow[0] = 0; + d_shadow[1] = 0; + d_shadow[2] = 0; + d_shadow[3] = 0; + reset (); +} + +sdr_1000_base::~sdr_1000_base () +{ +} + +void +sdr_1000_base::reset () +{ + d_ppio->lock (); + d_ppio->write_control (0x0F); + d_ppio->unlock (); + write_latch (L_EXT, 0x00, 0xff); + write_latch (L_BAND, 0x00, 0xff); + write_latch (L_DDS0, 0x80, 0xff); // hold DDS in reset + write_latch (L_DDS1, 0x00, 0xff); +} + + +void +sdr_1000_base::write_latch (int which, int value, int mask) +{ + if (!(0 <= which && which <= 3)) + return; + + d_ppio->lock (); + d_shadow[which] = (d_shadow[which] & ~mask) | (value & mask); + d_ppio->write_data (d_shadow[which]); + d_ppio->write_control (0x0F ^ (1 << which)); + d_ppio->write_control (0x0F); + d_ppio->unlock (); +} diff --git a/gnuradio-core/src/lib/io/sdr_1000.h b/gnuradio-core/src/lib/io/sdr_1000.h new file mode 100644 index 00000000..f9ddb35c --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_SDR_1000_H +#define INCLUDED_SDR_1000_H + +#include + +class ppio; +typedef boost::shared_ptr ppio_sptr; + + +enum { L_EXT = 0, L_BAND = 1, L_DDS0 = 2, L_DDS1 = 3 }; + +/*! + * \brief Very low level interface to SDR 1000 xcvr hardware + * \sa sdr_1000.py for a higher level interface. + */ +class sdr_1000_base { + ppio_sptr d_ppio; + int d_shadow[4]; // shadow latches + +public: + + sdr_1000_base (int which_pp); + ~sdr_1000_base (); + + void reset (); + void write_latch (int which, int value, int mask); +}; + +#endif /* INCLUDED_SDR_1000_H */ diff --git a/gnuradio-core/src/lib/io/sdr_1000.i b/gnuradio-core/src/lib/io/sdr_1000.i new file mode 100644 index 00000000..46690e0c --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +const int L_EXT = 0; +const int L_BAND = 1; +const int L_DDS0 = 2; +const int L_DDS1 = 3; + +class sdr_1000_base { +public: + + sdr_1000_base (int which_pp); + ~sdr_1000_base (); + + void reset (); + void write_latch (int which, int value, int mask); +}; diff --git a/gnuradio-core/src/lib/missing/Makefile.am b/gnuradio-core/src/lib/missing/Makefile.am new file mode 100644 index 00000000..7985fb3e --- /dev/null +++ b/gnuradio-core/src/lib/missing/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + getopt.h \ + getopt.c \ + gettimeofday.c \ + usleep.c + +noinst_LTLIBRARIES = libmissing.la + +libmissing_la_SOURCES = \ + bug_work_around_8.cc diff --git a/gnuradio-core/src/lib/missing/bug_work_around_8.cc b/gnuradio-core/src/lib/missing/bug_work_around_8.cc new file mode 100644 index 00000000..b7970227 --- /dev/null +++ b/gnuradio-core/src/lib/missing/bug_work_around_8.cc @@ -0,0 +1,2 @@ +// if libmisc has no sources, it doesn't get built correctly +static int gr_bug_work_around_8; diff --git a/gnuradio-core/src/lib/missing/getopt.c b/gnuradio-core/src/lib/missing/getopt.c new file mode 100644 index 00000000..93fb6ea5 --- /dev/null +++ b/gnuradio-core/src/lib/missing/getopt.c @@ -0,0 +1,733 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* NOTE!!! AIX requires this to be the first thing in the file. + Do not put ANYTHING before it! */ +#if !defined (__GNUC__) && defined (_AIX) + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) +#include +#else +#ifndef _AIX +char *alloca (); +#endif +#endif /* alloca.h */ +#endif /* not __GNUC__ */ + +#if !__STDC__ && !defined(const) && IN_GCC +#define const +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#undef alloca +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#else /* Not GNU C library. */ +#define __alloca alloca +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +static void +my_bcopy (from, to, size) + const char *from; + char *to; + int size; +{ + int i; + for (i = 0; i < size; i++) + to[i] = from[i]; +} +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); + char **temp = (char **) __alloca (nonopts_size); + + /* Interchange the two blocks of data in ARGV. */ + + my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); + my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], + (optind - last_nonopt) * sizeof (char *)); + my_bcopy ((char *) temp, + (char *) &argv[first_nonopt + optind - last_nonopt], + nonopts_size); + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +#ifdef GETOPT +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} +#endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gnuradio-core/src/lib/missing/getopt.h b/gnuradio-core/src/lib/missing/getopt.h new file mode 100644 index 00000000..45541f5a --- /dev/null +++ b/gnuradio-core/src/lib/missing/getopt.h @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/gnuradio-core/src/lib/missing/gettimeofday.c b/gnuradio-core/src/lib/missing/gettimeofday.c new file mode 100644 index 00000000..4ed15e21 --- /dev/null +++ b/gnuradio-core/src/lib/missing/gettimeofday.c @@ -0,0 +1,50 @@ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#ifdef HAVE_WINDOWS_H +#include +#endif +#ifdef HAVE_WINBASE_H +# include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +/* + * broken implementation for WIN32. + * FIXME: usec precision + */ +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + if (tv) { + time_t tm; + + time(&tm); + tv->tv_sec = tm; + tv->tv_usec = 0; + } + return 0; +} + diff --git a/gnuradio-core/src/lib/missing/usleep.c b/gnuradio-core/src/lib/missing/usleep.c new file mode 100644 index 00000000..4a0f75ea --- /dev/null +++ b/gnuradio-core/src/lib/missing/usleep.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + +#ifndef HAVE_USLEEP + +#include +#include + +#ifdef HAVE_SYS_SELECT_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif +#ifdef HAVE_WINBASE_H +# include +#endif + +#ifdef apollo +# include +# include + static time_$clock_t DomainTime100mS = + { + 0, 100000/4 + }; + static status_$t DomainStatus; +#endif + +/* Sleep USECONDS microseconds, or until a previously set timer goes off. */ +int +usleep (unsigned long useconds) +{ +#ifdef apollo + /* The usleep function does not work under the SYS5.3 environment. + Use the Domain/OS time_$wait call instead. */ + time_$wait (time_$relative, DomainTime100mS, &DomainStatus); +#elif defined(HAVE_SSLEEP) /* Win32 */ + Sleep( useconds/1000 ); +#else + struct timeval delay; + + delay.tv_sec = 0; + delay.tv_usec = useconds; + select (0, 0, 0, 0, &delay); +#endif + return 0; +} + +#endif /* !HAVE_USLEEP */ diff --git a/gnuradio-core/src/lib/omnithread/Makefile.am b/gnuradio-core/src/lib/omnithread/Makefile.am new file mode 100644 index 00000000..f2234468 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/Makefile.am @@ -0,0 +1,67 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# This is the omnithread package, +# extracted from the omniORB-4.0.1 distribution + +# we should do some configure hacking to determine these on the fly +OMNITHREAD_DEFINES = -DPthreadDraftVersion=10 + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(OMNITHREAD_DEFINES) + +noinst_LTLIBRARIES = libomnithread.la + +# At this point we only support the posix and nt pthreads i/f... + +if OMNITHREAD_POSIX +libomnithread_la_SOURCES = \ + posix.cc +endif + +if OMNITHREAD_NT +libomnithread_la_SOURCES = \ + nt.cc +endif + +libomnithread_la_LIBADD = \ + $(PTHREAD_LIBS) + +# ... but this code also came with the package + +EXTRA_DIST = \ + mach.cc \ + nt.cc \ + posix.cc \ + solaris.cc \ + threaddata.cc \ + vxWorks.cc \ + dir.mk + +grinclude_HEADERS = \ + omnithread.h \ + ot_mach.h \ + ot_nt.h \ + ot_posix.h \ + ot_pthread_nt.h \ + ot_solaris.h \ + ot_VxThread.h diff --git a/gnuradio-core/src/lib/omnithread/dir.mk b/gnuradio-core/src/lib/omnithread/dir.mk new file mode 100644 index 00000000..d5380341 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/dir.mk @@ -0,0 +1,229 @@ +ifeq ($(ThreadSystem),Solaris) +CXXSRCS = solaris.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +endif + +ifeq ($(ThreadSystem),Posix) +CXXSRCS = posix.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) $(OMNITHREAD_POSIX_CPPFLAGS) +endif + +ifeq ($(ThreadSystem),NT) +CXXSRCS = nt.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +MSVC_STATICLIB_CXXNODEBUGFLAGS += -D_WINSTATIC +MSVC_STATICLIB_CXXDEBUGFLAGS += -D_WINSTATIC +MSVC_DLL_CXXNODEBUGFLAGS += -D_OMNITHREAD_DLL +MSVC_DLL_CXXDEBUGFLAGS += -D_OMNITHREAD_DLL +endif + +ifeq ($(ThreadSystem),NTPosix) +CXXSRCS = posix.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +MSVC_STATICLIB_CXXNODEBUGFLAGS += -D_WINSTATIC +MSVC_STATICLIB_CXXDEBUGFLAGS += -D_WINSTATIC +MSVC_DLL_CXXNODEBUGFLAGS += -D_OMNITHREAD_DLL +MSVC_DLL_CXXDEBUGFLAGS += -D_OMNITHREAD_DLL +endif + +ifeq ($(ThreadSystem),Mach) +CXXSRCS = mach.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +endif + +ifeq ($(ThreadSystem),vxWorks) +CXXSRCS = vxWorks.cc +OBJS = vxWorks.o +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +endif + +LIB_NAME := omnithread +LIB_VERSION := $(OMNITHREAD_VERSION) +LIB_OBJS := $(CXXSRCS:.cc=.o) +LIB_IMPORTS := $(OMNITHREAD_PLATFORM_LIB) + +all:: mkstatic mkshared + +export:: mkstatic mkshared + +ifdef INSTALLTARGET +install:: mkstatic mkshared +endif + +vers := $(subst ., ,$(LIB_VERSION)) +ifeq ($(words $(vers)), 2) + vers := _ $(vers) + major := "" +else + major := $(word 1, $(vers)) +endif + +namespec := $(LIB_NAME) $(vers) + +############################################################################## +# Build Static library +############################################################################## + +ifndef NoStaticLibrary + +staticlib := static/$(patsubst %,$(LibNoDebugPattern),$(LIB_NAME)$(major)) + +mkstatic:: + @(dir=static; $(CreateDir)) + +mkstatic:: $(staticlib) + +$(staticlib): $(patsubst %, static/%, $(LIB_OBJS)) + @$(StaticLinkLibrary) + +export:: $(staticlib) + @$(ExportLibrary) + +ifdef INSTALLTARGET +install:: $(staticlib) + @$(InstallLibrary) +endif + +clean:: + $(RM) static/*.o + $(RM) $(staticlib) + +veryclean:: + $(RM) static/*.o + $(RM) $(staticlib) + +else + +mkstatic:: + +endif + + +############################################################################## +# Build Shared library +############################################################################## +ifdef BuildSharedLibrary + +shlib := shared/$(shell $(SharedLibraryFullName) $(namespec)) + +ifdef Win32Platform +# in case of Win32 lossage: + imps := $(patsubst $(DLLDebugSearchPattern),$(DLLNoDebugSearchPattern), \ + $(LIB_IMPORTS)) +else + imps := $(LIB_IMPORTS) +endif + +mkshared:: + @(dir=shared; $(CreateDir)) + +mkshared:: $(shlib) + +$(shlib): $(patsubst %, shared/%, $(LIB_OBJS)) + @(namespec="$(namespec)" extralibs="$(imps)" nodeffile=1; \ + $(MakeCXXSharedLibrary)) + +export:: $(shlib) + @(namespec="$(namespec)"; \ + $(ExportSharedLibrary)) + +ifdef INSTALLTARGET +install:: $(shlib) + @(namespec="$(namespec)"; \ + $(InstallSharedLibrary)) +endif + +clean:: + $(RM) shared/*.o + (dir=shared; $(CleanSharedLibrary)) + +veryclean:: + $(RM) shared/*.o + @(dir=shared; $(CleanSharedLibrary)) + +else + +mkshared:: + +endif + +############################################################################## +# Build debug libraries for Win32 +############################################################################## +ifdef Win32Platform + +ifdef BuildSharedLibrary + +all:: mkstaticdbug mkshareddbug + +export:: mkstaticdbug mkshareddbug + +else + +all:: mkstaticdbug + +export:: mkstaticdbug + +endif + + +##################################################### +# Static debug libraries +##################################################### + +dbuglib := debug/$(patsubst %,$(LibDebugPattern),$(LIB_NAME)$(major)) + +mkstaticdbug:: + @(dir=debug; $(CreateDir)) + +mkstaticdbug:: $(dbuglib) + +$(dbuglib): $(patsubst %, debug/%, $(LIB_OBJS)) + @$(StaticLinkLibrary) + +export:: $(dbuglib) + @$(ExportLibrary) + +clean:: + $(RM) debug/*.o + $(RM) $(dbuglib) + +veryclean:: + $(RM) debug/*.o + $(RM) $(dbuglib) + +##################################################### +# DLL debug libraries +##################################################### + +ifdef BuildSharedLibrary + +dbugshlib := shareddebug/$(shell $(SharedLibraryDebugFullName) $(namespec)) + +dbugimps := $(patsubst $(DLLNoDebugSearchPattern),$(DLLDebugSearchPattern), \ + $(LIB_IMPORTS)) + +mkshareddbug:: + @(dir=shareddebug; $(CreateDir)) + +mkshareddbug:: $(dbugshlib) + +$(dbugshlib): $(patsubst %, shareddebug/%, $(LIB_OBJS)) + (namespec="$(namespec)" debug=1 extralibs="$(dbugimps)" nodeffile=1; \ + $(MakeCXXSharedLibrary)) + +export:: $(dbugshlib) + @(namespec="$(namespec)" debug=1; \ + $(ExportSharedLibrary)) + +clean:: + $(RM) shareddebug/*.o + @(dir=shareddebug; $(CleanSharedLibrary)) + +veryclean:: + $(RM) shareddebug/*.o + @(dir=shareddebug; $(CleanSharedLibrary)) + +endif +endif + diff --git a/gnuradio-core/src/lib/omnithread/mach.cc b/gnuradio-core/src/lib/omnithread/mach.cc new file mode 100644 index 00000000..06f8a11e --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/mach.cc @@ -0,0 +1,714 @@ +// Package : omnithread +// omnithread/mach.cc Created : 7/97 lars immisch lars@ibp.de +// +// Copyright (C) 1997 Immisch, Becker & Partner +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Implementation of OMNI thread abstraction for mach threads +// +// to the author's pleasure, mach cthreads are very similar to posix threads +// + +#include +#include +#include +#include +#include "omnithread.h" + +#define DB(x) // x +// #include or #include if DB is on. + +#define ERRNO(x) (x) + +// +// static variables +// + +int omni_thread::init_t::count = 0; + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; + +static int normal_priority; +static int highest_priority; + +static size_t stack_size = 0; + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ + mutex_init(&mach_mutex); +} + + +omni_mutex::~omni_mutex(void) +{ + mutex_clear(&mach_mutex); +} + + +void omni_mutex::lock(void) +{ + mutex_lock(&mach_mutex); +} + + +void omni_mutex::unlock(void) +{ + mutex_unlock(&mach_mutex); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + condition_init(&mach_cond); +} + + +omni_condition::~omni_condition(void) +{ + condition_clear(&mach_cond); +} + +void +omni_condition::wait(void) +{ + condition_wait(&mach_cond, &mutex->mach_mutex); +} + +typedef struct alarmclock_args { + unsigned long secs; + unsigned long nsecs; + bool wakeup; + condition_t condition; + mutex_t mutex; +}; + +any_t alarmclock(any_t arg) +{ + alarmclock_args* alarm = (alarmclock_args*)arg; + + omni_thread::sleep(alarm->secs, alarm->nsecs); + + mutex_lock(alarm->mutex); + + alarm->wakeup = TRUE; + + condition_signal(alarm->condition); + + mutex_unlock(alarm->mutex); + + return (any_t)TRUE; +} + +int omni_condition::timedwait(unsigned long abs_secs, unsigned long abs_nsecs) +{ + alarmclock_args alarm; + + omni_thread::get_time(&alarm.secs, &alarm.nsecs, 0, 0); + + if (abs_secs < alarm.secs || (abs_secs == alarm.secs && abs_nsecs <= alarm.nsecs)) + return ETIMEDOUT; + + alarm.secs = abs_secs - alarm.secs; + if (abs_nsecs <= alarm.nsecs) { + alarm.nsecs = 1000000 - alarm.nsecs + abs_nsecs; + alarm.secs--; + } + else { + alarm.nsecs = abs_nsecs - alarm.nsecs; + } + + alarm.mutex = &mutex->mach_mutex; + alarm.condition = &mach_cond; + alarm.wakeup = FALSE; + + cthread_t ct = cthread_fork((cthread_fn_t)alarmclock, (any_t)&alarm); + cthread_detach(ct); + + condition_wait(&mach_cond, &mutex->mach_mutex); + + if (alarm.wakeup) { + return 0; + } + + // interrupt the alarmclock thread sleep + cthread_abort(ct); + + // wait until it has signalled the condition + condition_wait(&mach_cond, &mutex->mach_mutex); + + return 1; +} + + +void omni_condition::signal(void) +{ + condition_signal(&mach_cond); +} + + +void omni_condition::broadcast(void) +{ + condition_signal(&mach_cond); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +omni_semaphore::omni_semaphore(unsigned int initial) : c(&m) +{ + value = initial; +} + + +omni_semaphore::~omni_semaphore(void) +{ +} + + +void +omni_semaphore::wait(void) +{ + omni_mutex_lock l(m); + + while (value == 0) + c.wait(); + + value--; +} + + +int +omni_semaphore::trywait(void) +{ + omni_mutex_lock l(m); + + if (value == 0) + return 0; + + value--; + return 1; +} + + +void +omni_semaphore::post(void) +{ + omni_mutex_lock l(m); + + if (value == 0) + c.signal(); + + value++; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + + +// +// Initialisation function (gets called before any user code). +// + +omni_thread::init_t::init_t(void) +{ + if (count++ != 0) // only do it once however many objects get created. + return; + + // + // find base and max priority. + // This is the initial thread, so the max priority of this + // thread also applies to any newly created thread. + // + + kern_return_t error; + struct thread_sched_info info; + unsigned int info_count = THREAD_SCHED_INFO_COUNT; + + error = thread_info(thread_self(), THREAD_SCHED_INFO, (thread_info_t)&info, &info_count); + if (error != KERN_SUCCESS) { + DB(cerr << "omni_thread::init: error determining thread_info" << endl); + ::exit(1); + } + else { + normal_priority = info.base_priority; + highest_priority = info.max_priority; + } + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + if (t->_state != STATE_NEW) { + DB(cerr << "omni_thread::init: problem creating initial thread object\n"); + ::exit(1); + } + + t->_state = STATE_RUNNING; + + t->mach_thread = cthread_self(); + + DB(cerr << "initial thread " << t->id() << endl); + + cthread_set_data(t->mach_thread, (any_t)t); +} + + +// +// Wrapper for thread creation. +// + +extern "C" void* +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread::wrapper: thread " << me->id() + << " started\n"); + + cthread_set_data(cthread_self(), (any_t)me); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. + + return NULL; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; + // posix_thread is set up in initialisation routine or start(). +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + int rc; + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + + mach_thread = cthread_fork(omni_thread_wrapper, (any_t)this); + + _state = STATE_RUNNING; + + if (detached) { + cthread_detach(mach_thread); + } +} + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call cthread_join. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing cthread_join\n"); + + *status = cthread_join(mach_thread); + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + + kern_return_t rc = cthread_priority(mach_thread, mach_priority(pri), FALSE); + + if (rc != KERN_SUCCESS) + throw omni_thread_fatal(errno); +} + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + if (me->_state != STATE_RUNNING) + DB(cerr << "omni_thread::exit: thread not in \"running\" state\n"); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) + delete me; + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } + cthread_exit(return_value); +} + +omni_thread* omni_thread::self(void) +{ + omni_thread* me; + + me = (omni_thread*)cthread_data(cthread_self()); + + if (!me) { + // This thread is not created by omni_thread::start because it + // doesn't has a class omni_thread instance attached to its key. + DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); + } + + return me; +} + +void omni_thread::yield(void) +{ + cthread_yield(); +} + +#define MAX_SLEEP_SECONDS (unsigned)4294966 // (2**32-2)/1000 + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + if (secs <= MAX_SLEEP_SECONDS) { + thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, secs * 1000 + nanosecs / 1000000); + return; + } + + unsigned no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; + + for (unsigned i = 0; i < no_of_max_sleeps; i++) + thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, MAX_SLEEP_SECONDS * 1000); + + thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, + (secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000); + + return; +} + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + int rc; + unsigned long tv_sec; + unsigned long tv_nsec; + struct timeval tv; + + rc = gettimeofday(&tv, NULL); + if (rc) throw omni_thread_fatal(rc); + + tv_sec = tv.tv_sec; + tv_nsec = tv.tv_usec * 1000; + + tv_nsec += rel_nsec; + tv_sec += rel_sec + tv_nsec / 1000000000; + tv_nsec = tv_nsec % 1000000000; + + *abs_sec = tv_sec; + *abs_nsec = tv_nsec; +} + + +int +omni_thread::mach_priority(priority_t pri) +{ + switch (pri) { + + case PRIORITY_LOW: + return 0; + + case PRIORITY_NORMAL: + return normal_priority; + + case PRIORITY_HIGH: + return highest_priority; + + default: + return -1; + } +} + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + + +// +// Dummy thread +// + +#error This dummy thread code is not tested. It might work if you're lucky. + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + mach_thread = cthread_self(); + cthread_set_data(mach_thread, (any_t)this)); + } + inline ~omni_thread_dummy() + { + cthread_set_data(mach_thread, (any_t)0)); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/nt.cc b/gnuradio-core/src/lib/omnithread/nt.cc new file mode 100644 index 00000000..09be4229 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/nt.cc @@ -0,0 +1,967 @@ +// Package : omnithread +// omnithread/nt.cc Created : 6/95 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1995-1999 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Implementation of OMNI thread abstraction for NT threads +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#define DB(x) // x +//#include or #include if DB is on. + +static void get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec); + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ + InitializeCriticalSection(&crit); +} + +omni_mutex::~omni_mutex(void) +{ + DeleteCriticalSection(&crit); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +// +// Condition variables are tricky to implement using NT synchronisation +// primitives, since none of them have the atomic "release mutex and wait to be +// signalled" which is central to the idea of a condition variable. To get +// around this the solution is to record which threads are waiting and +// explicitly wake up those threads. +// +// Here we implement a condition variable using a list of waiting threads +// (protected by a critical section), and a per-thread semaphore (which +// actually only needs to be a binary semaphore). +// +// To wait on the cv, a thread puts itself on the list of waiting threads for +// that cv, then releases the mutex and waits on its own personal semaphore. A +// signalling thread simply takes a thread from the head of the list and kicks +// that thread's semaphore. Broadcast is simply implemented by kicking the +// semaphore of each waiting thread. +// +// The only other tricky part comes when a thread gets a timeout from a timed +// wait on its semaphore. Between returning with a timeout from the wait and +// entering the critical section, a signalling thread could get in, kick the +// waiting thread's semaphore and remove it from the list. If this happens, +// the waiting thread's semaphore is now out of step so it needs resetting, and +// the thread should indicate that it was signalled rather than that it timed +// out. +// +// It is possible that the thread calling wait or timedwait is not a +// omni_thread. In this case we have to provide a temporary data structure, +// i.e. for the duration of the call, for the thread to link itself on the +// list of waiting threads. _internal_omni_thread_dummy provides such +// a data structure and _internal_omni_thread_helper is a helper class to +// deal with this special case for wait() and timedwait(). Once created, +// the _internal_omni_thread_dummy is cached for use by the next wait() or +// timedwait() call from a non-omni_thread. This is probably worth doing +// because creating a Semaphore is quite heavy weight. + +class _internal_omni_thread_helper; + +class _internal_omni_thread_dummy : public omni_thread { +public: + inline _internal_omni_thread_dummy() : next(0) { } + inline ~_internal_omni_thread_dummy() { } + friend class _internal_omni_thread_helper; +private: + _internal_omni_thread_dummy* next; +}; + +class _internal_omni_thread_helper { +public: + inline _internal_omni_thread_helper() { + d = 0; + t = omni_thread::self(); + if (!t) { + omni_mutex_lock sync(cachelock); + if (cache) { + d = cache; + cache = cache->next; + } + else { + d = new _internal_omni_thread_dummy; + } + t = d; + } + } + inline ~_internal_omni_thread_helper() { + if (d) { + omni_mutex_lock sync(cachelock); + d->next = cache; + cache = d; + } + } + inline operator omni_thread* () { return t; } + inline omni_thread* operator->() { return t; } + + static _internal_omni_thread_dummy* cache; + static omni_mutex cachelock; + +private: + _internal_omni_thread_dummy* d; + omni_thread* t; +}; + +_internal_omni_thread_dummy* _internal_omni_thread_helper::cache = 0; +omni_mutex _internal_omni_thread_helper::cachelock; + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + InitializeCriticalSection(&crit); + waiting_head = waiting_tail = NULL; +} + + +omni_condition::~omni_condition(void) +{ + DeleteCriticalSection(&crit); + DB( if (waiting_head != NULL) { + cerr << "omni_condition::~omni_condition: list of waiting threads " + << "is not empty\n"; + } ) +} + + +void +omni_condition::wait(void) +{ + _internal_omni_thread_helper me; + + EnterCriticalSection(&crit); + + me->cond_next = NULL; + me->cond_prev = waiting_tail; + if (waiting_head == NULL) + waiting_head = me; + else + waiting_tail->cond_next = me; + waiting_tail = me; + me->cond_waiting = TRUE; + + LeaveCriticalSection(&crit); + + mutex->unlock(); + + DWORD result = WaitForSingleObject(me->cond_semaphore, INFINITE); + + mutex->lock(); + + if (result != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); +} + + +int +omni_condition::timedwait(unsigned long abs_sec, unsigned long abs_nsec) +{ + _internal_omni_thread_helper me; + + EnterCriticalSection(&crit); + + me->cond_next = NULL; + me->cond_prev = waiting_tail; + if (waiting_head == NULL) + waiting_head = me; + else + waiting_tail->cond_next = me; + waiting_tail = me; + me->cond_waiting = TRUE; + + LeaveCriticalSection(&crit); + + mutex->unlock(); + + unsigned long now_sec, now_nsec; + + get_time_now(&now_sec, &now_nsec); + + DWORD timeout; + if ((abs_sec <= now_sec) && ((abs_sec < now_sec) || (abs_nsec < now_nsec))) + timeout = 0; + else { + timeout = (abs_sec-now_sec) * 1000; + + if( abs_nsec < now_nsec ) timeout -= (now_nsec-abs_nsec) / 1000000; + else timeout += (abs_nsec-now_nsec) / 1000000; + } + + DWORD result = WaitForSingleObject(me->cond_semaphore, timeout); + + if (result == WAIT_TIMEOUT) { + EnterCriticalSection(&crit); + + if (me->cond_waiting) { + if (me->cond_prev != NULL) + me->cond_prev->cond_next = me->cond_next; + else + waiting_head = me->cond_next; + if (me->cond_next != NULL) + me->cond_next->cond_prev = me->cond_prev; + else + waiting_tail = me->cond_prev; + me->cond_waiting = FALSE; + + LeaveCriticalSection(&crit); + + mutex->lock(); + return 0; + } + + // + // We timed out but another thread still signalled us. Wait for + // the semaphore (it _must_ have been signalled) to decrement it + // again. Return that we were signalled, not that we timed out. + // + + LeaveCriticalSection(&crit); + + result = WaitForSingleObject(me->cond_semaphore, INFINITE); + } + + if (result != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); + + mutex->lock(); + return 1; +} + + +void +omni_condition::signal(void) +{ + EnterCriticalSection(&crit); + + if (waiting_head != NULL) { + omni_thread* t = waiting_head; + waiting_head = t->cond_next; + if (waiting_head == NULL) + waiting_tail = NULL; + else + waiting_head->cond_prev = NULL; + t->cond_waiting = FALSE; + + if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) { + int rc = GetLastError(); + LeaveCriticalSection(&crit); + throw omni_thread_fatal(rc); + } + } + + LeaveCriticalSection(&crit); +} + + +void +omni_condition::broadcast(void) +{ + EnterCriticalSection(&crit); + + while (waiting_head != NULL) { + omni_thread* t = waiting_head; + waiting_head = t->cond_next; + if (waiting_head == NULL) + waiting_tail = NULL; + else + waiting_head->cond_prev = NULL; + t->cond_waiting = FALSE; + + if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) { + int rc = GetLastError(); + LeaveCriticalSection(&crit); + throw omni_thread_fatal(rc); + } + } + + LeaveCriticalSection(&crit); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +#define SEMAPHORE_MAX 0x7fffffff + + +omni_semaphore::omni_semaphore(unsigned int initial, unsigned int max_count) +{ + if (max_count > SEMAPHORE_MAX) + max_count= SEMAPHORE_MAX; + + nt_sem = CreateSemaphore(NULL, initial, max_count, NULL); + + if (nt_sem == NULL) { + DB( cerr << "omni_semaphore::omni_semaphore: CreateSemaphore error " + << GetLastError() << endl ); + throw omni_thread_fatal(GetLastError()); + } +} + + +omni_semaphore::~omni_semaphore(void) +{ + if (!CloseHandle(nt_sem)) { + DB( cerr << "omni_semaphore::~omni_semaphore: CloseHandle error " + << GetLastError() << endl ); + throw omni_thread_fatal(GetLastError()); + } +} + + +void +omni_semaphore::wait(void) +{ + if (WaitForSingleObject(nt_sem, INFINITE) != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); +} + + +int +omni_semaphore::trywait(void) +{ + switch (WaitForSingleObject(nt_sem, 0)) { + + case WAIT_OBJECT_0: + return 1; + case WAIT_TIMEOUT: + return 0; + } + + throw omni_thread_fatal(GetLastError()); + return 0; /* keep msvc++ happy */ +} + + +void +omni_semaphore::post(void) +{ + if (!ReleaseSemaphore(nt_sem, 1, NULL)) + throw omni_thread_fatal(GetLastError()); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// Static variables +// + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; +static DWORD self_tls_index; + +static unsigned int stack_size = 0; + +// +// Initialisation function (gets called before any user code). +// + +static int& count() { + static int the_count = 0; + return the_count; +} + +omni_thread::init_t::init_t(void) +{ + if (count()++ != 0) // only do it once however many objects get created. + return; + + DB(cerr << "omni_thread::init: NT implementation initialising\n"); + + self_tls_index = TlsAlloc(); + + if (self_tls_index == 0xffffffff) + throw omni_thread_fatal(GetLastError()); + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + t->_state = STATE_RUNNING; + + if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &t->handle, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + throw omni_thread_fatal(GetLastError()); + + t->nt_id = GetCurrentThreadId(); + + DB(cerr << "initial thread " << t->id() << " NT thread id " << t->nt_id + << endl); + + if (!TlsSetValue(self_tls_index, (LPVOID)t)) + throw omni_thread_fatal(GetLastError()); + + if (!SetThreadPriority(t->handle, nt_priority(PRIORITY_NORMAL))) + throw omni_thread_fatal(GetLastError()); +} + +omni_thread::init_t::~init_t(void) +{ + if (--count() != 0) return; + + omni_thread* self = omni_thread::self(); + if (!self) return; + + TlsSetValue(self_tls_index, (LPVOID)0); + delete self; + + delete next_id_mutex; + + TlsFree(self_tls_index); +} + +// +// Wrapper for thread creation. +// + +extern "C" +#ifndef __BCPLUSPLUS__ +unsigned __stdcall +#else +void _USERENTRY +#endif +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread_wrapper: thread " << me->id() + << " started\n"); + + if (!TlsSetValue(self_tls_index, (LPVOID)me)) + throw omni_thread_fatal(GetLastError()); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. +#ifndef __BCPLUSPLUS__ + return 0; +#endif +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void +omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + cond_semaphore = CreateSemaphore(NULL, 0, SEMAPHORE_MAX, NULL); + + if (cond_semaphore == NULL) + throw omni_thread_fatal(GetLastError()); + + cond_next = cond_prev = NULL; + cond_waiting = FALSE; + + handle = NULL; + + _dummy = 0; + _values = 0; + _value_alloc = 0; +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } + if (handle && !CloseHandle(handle)) + throw omni_thread_fatal(GetLastError()); + if (cond_semaphore && !CloseHandle(cond_semaphore)) + throw omni_thread_fatal(GetLastError()); +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + +#ifndef __BCPLUSPLUS__ + // MSVC++ or compatiable + unsigned int t; + handle = (HANDLE)_beginthreadex( + NULL, + stack_size, + omni_thread_wrapper, + (LPVOID)this, + CREATE_SUSPENDED, + &t); + nt_id = t; + if (handle == NULL) + throw omni_thread_fatal(GetLastError()); +#else + // Borland C++ + handle = (HANDLE)_beginthreadNT(omni_thread_wrapper, + stack_size, + (void*)this, + NULL, + CREATE_SUSPENDED, + &nt_id); + if (handle == INVALID_HANDLE_VALUE) + throw omni_thread_fatal(errno); +#endif + + if (!SetThreadPriority(handle, nt_priority(_priority))) + throw omni_thread_fatal(GetLastError()); + + if (ResumeThread(handle) == 0xffffffff) + throw omni_thread_fatal(GetLastError()); + + _state = STATE_RUNNING; +} + + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call WaitForSingleObject. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing WaitForSingleObject\n"); + + if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); + + DB(cerr << "omni_thread::join: WaitForSingleObject succeeded\n"); + + if (status) + *status = return_val; + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + + if (!SetThreadPriority(handle, nt_priority(pri))) + throw omni_thread_fatal(GetLastError()); +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + t->start(); + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + t->start(); + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void +omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) { + delete me; + } else { + me->return_val = return_value; + } + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } +#ifndef __BCPLUSPLUS__ + // MSVC++ or compatiable + // _endthreadex() does not automatically closes the thread handle. + // The omni_thread dtor closes the thread handle. + _endthreadex(0); +#else + // Borland C++ + // _endthread() does not automatically closes the thread handle. + // _endthreadex() is only available if __MFC_COMPAT__ is defined and + // all it does is to call _endthread(). + _endthread(); +#endif +} + + +omni_thread* +omni_thread::self(void) +{ + LPVOID me; + + me = TlsGetValue(self_tls_index); + + if (me == NULL) { + DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); + } + return (omni_thread*)me; +} + + +void +omni_thread::yield(void) +{ + Sleep(0); +} + + +#define MAX_SLEEP_SECONDS (DWORD)4294966 // (2**32-2)/1000 + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + if (secs <= MAX_SLEEP_SECONDS) { + Sleep(secs * 1000 + nanosecs / 1000000); + return; + } + + DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; + + for (DWORD i = 0; i < no_of_max_sleeps; i++) + Sleep(MAX_SLEEP_SECONDS * 1000); + + Sleep((secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000); +} + + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + get_time_now(abs_sec, abs_nsec); + *abs_nsec += rel_nsec; + *abs_sec += rel_sec + *abs_nsec / 1000000000; + *abs_nsec = *abs_nsec % 1000000000; +} + + +int +omni_thread::nt_priority(priority_t pri) +{ + switch (pri) { + + case PRIORITY_LOW: + return THREAD_PRIORITY_LOWEST; + + case PRIORITY_NORMAL: + return THREAD_PRIORITY_NORMAL; + + case PRIORITY_HIGH: + return THREAD_PRIORITY_HIGHEST; + } + + throw omni_thread_invalid(); + return 0; /* keep msvc++ happy */ +} + + +static void +get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec) +{ + static int days_in_preceding_months[12] + = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + static int days_in_preceding_months_leap[12] + = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + + SYSTEMTIME st; + + GetSystemTime(&st); + *abs_nsec = st.wMilliseconds * 1000000; + + // this formula should work until 1st March 2100 + + DWORD days = ((st.wYear - 1970) * 365 + (st.wYear - 1969) / 4 + + ((st.wYear % 4) + ? days_in_preceding_months[st.wMonth - 1] + : days_in_preceding_months_leap[st.wMonth - 1]) + + st.wDay - 1); + + *abs_sec = st.wSecond + 60 * (st.wMinute + 60 * (st.wHour + 24 * days)); +} + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + +// +// Dummy thread +// + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + + if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &handle, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + throw omni_thread_fatal(GetLastError()); + + nt_id = GetCurrentThreadId(); + + if (!TlsSetValue(self_tls_index, (LPVOID)this)) + throw omni_thread_fatal(GetLastError()); + } + inline ~omni_thread_dummy() + { + if (!TlsSetValue(self_tls_index, (LPVOID)0)) + throw omni_thread_fatal(GetLastError()); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#if defined(__DMC__) && defined(_WINDLL) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return TRUE; +} +#endif + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/omnithread.h b/gnuradio-core/src/lib/omnithread/omnithread.h new file mode 100644 index 00000000..f63adc4f --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/omnithread.h @@ -0,0 +1,622 @@ +// -*- Mode: C++; -*- +// Package : omnithread +// omnithread.h Created : 7/94 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Interface to OMNI thread abstraction. +// +// This file declares classes for threads and synchronisation objects +// (mutexes, condition variables and counting semaphores). +// +// Wherever a seemingly arbitrary choice has had to be made as to the interface +// provided, the intention here has been to be as POSIX-like as possible. This +// is why there is no semaphore timed wait, for example. +// + +#ifndef __omnithread_h_ +#define __omnithread_h_ + +#ifndef NULL +#define NULL 0 +#endif + +class omni_mutex; +class omni_condition; +class omni_semaphore; +class omni_thread; + +// +// OMNI_THREAD_EXPOSE can be defined as public or protected to expose the +// implementation class - this may be useful for debugging. Hopefully this +// won't change the underlying structure which the compiler generates so that +// this can work without recompiling the library. +// + +#ifndef OMNI_THREAD_EXPOSE +#define OMNI_THREAD_EXPOSE private +#endif + +// +// Include implementation-specific header file. +// +// This must define 4 CPP macros of the form OMNI_x_IMPLEMENTATION for mutex, +// condition variable, semaphore and thread. Each should define any +// implementation-specific members of the corresponding classes. +// + + +// +// For now, we assume they've always got a Posix Threads implementation. +// If not, it'll take some configure hacking to sort it out, along with +// the relevant libraries to link with, etc. +// + +#if !defined(OMNITHREAD_POSIX) && !defined(OMNITHREAD_NT) && defined HAVE_CONFIG_H +#include +#endif + +#if defined(OMNITHREAD_POSIX) +#include + +#elif defined(OMNITHREAD_NT) +#include + +#ifdef _MSC_VER + +// Using MSVC++ to compile. If compiling library as a DLL, +// define _OMNITHREAD_DLL. If compiling as a statuc library, define +// _WINSTATIC +// If compiling an application that is to be statically linked to omnithread, +// define _WINSTATIC (if the application is to be dynamically linked, +// there is no need to define any of these macros). + +#if defined (_OMNITHREAD_DLL) && defined(_WINSTATIC) +#error "Both _OMNITHREAD_DLL and _WINSTATIC are defined." +#elif defined(_OMNITHREAD_DLL) +#define _OMNITHREAD_NTDLL_ __declspec(dllexport) +#elif !defined(_WINSTATIC) +#define _OMNITHREAD_NTDLL_ __declspec(dllimport) +#elif defined(_WINSTATIC) +#define _OMNITHREAD_NTDLL_ +#endif + // _OMNITHREAD_DLL && _WINSTATIC + +#else + +// Not using MSVC++ to compile +#define _OMNITHREAD_NTDLL_ + +#endif + // _MSC_VER + +#elif defined(__vxWorks__) +#include + +#elif defined(__sunos__) +#if __OSVERSION__ != 5 +// XXX Workaround for SUN C++ compiler (seen on 4.2) Template.DB code +// regeneration bug. See omniORB2/CORBA_sysdep.h for details. +#if !defined(__SUNPRO_CC) || __OSVERSION__ != '5' +#error "Only SunOS 5.x or later is supported." +#endif +#endif +#ifdef UseSolarisThreads +#include +#else +#include +#endif + +#elif defined(__rtems__) +#include +#include + +#elif defined(__macos__) +#include +#include + +#else +#error "No implementation header file" +#endif + + +#if !defined(__WIN32__) +#define _OMNITHREAD_NTDLL_ +#endif + +#if (!defined(OMNI_MUTEX_IMPLEMENTATION) || \ + !defined(OMNI_MUTEX_LOCK_IMPLEMENTATION) || \ + !defined(OMNI_MUTEX_TRYLOCK_IMPLEMENTATION)|| \ + !defined(OMNI_MUTEX_UNLOCK_IMPLEMENTATION) || \ + !defined(OMNI_CONDITION_IMPLEMENTATION) || \ + !defined(OMNI_SEMAPHORE_IMPLEMENTATION) || \ + !defined(OMNI_THREAD_IMPLEMENTATION)) +#error "Implementation header file incomplete" +#endif + + +// +// This exception is thrown in the event of a fatal error. +// + +class _OMNITHREAD_NTDLL_ omni_thread_fatal { +public: + int error; + omni_thread_fatal(int e = 0) : error(e) {} +}; + + +// +// This exception is thrown when an operation is invoked with invalid +// arguments. +// + +class _OMNITHREAD_NTDLL_ omni_thread_invalid {}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_mutex { + +public: + omni_mutex(void); + ~omni_mutex(void); + + inline void lock(void) { OMNI_MUTEX_LOCK_IMPLEMENTATION } + inline void unlock(void) { OMNI_MUTEX_UNLOCK_IMPLEMENTATION } + inline int trylock(void) { return OMNI_MUTEX_TRYLOCK_IMPLEMENTATION } + // if mutex is unlocked, lock it and return 1 (true). + // If it's already locked then return 0 (false). + + inline void acquire(void) { lock(); } + inline void release(void) { unlock(); } + // the names lock and unlock are preferred over acquire and release + // since we are attempting to be as POSIX-like as possible. + + friend class omni_condition; + +private: + // dummy copy constructor and operator= to prevent copying + omni_mutex(const omni_mutex&); + omni_mutex& operator=(const omni_mutex&); + +OMNI_THREAD_EXPOSE: + OMNI_MUTEX_IMPLEMENTATION +}; + +// +// As an alternative to: +// { +// mutex.lock(); +// ..... +// mutex.unlock(); +// } +// +// you can use a single instance of the omni_mutex_lock class: +// +// { +// omni_mutex_lock l(mutex); +// .... +// } +// +// This has the advantage that mutex.unlock() will be called automatically +// when an exception is thrown. +// + +class _OMNITHREAD_NTDLL_ omni_mutex_lock { + omni_mutex& mutex; +public: + omni_mutex_lock(omni_mutex& m) : mutex(m) { mutex.lock(); } + ~omni_mutex_lock(void) { mutex.unlock(); } +private: + // dummy copy constructor and operator= to prevent copying + omni_mutex_lock(const omni_mutex_lock&); + omni_mutex_lock& operator=(const omni_mutex_lock&); +}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_condition { + + omni_mutex* mutex; + +public: + omni_condition(omni_mutex* m); + // constructor must be given a pointer to an existing mutex. The + // condition variable is then linked to the mutex, so that there is an + // implicit unlock and lock around wait() and timed_wait(). + + ~omni_condition(void); + + void wait(void); + // wait for the condition variable to be signalled. The mutex is + // implicitly released before waiting and locked again after waking up. + // If wait() is called by multiple threads, a signal may wake up more + // than one thread. See POSIX threads documentation for details. + + int timedwait(unsigned long secs, unsigned long nanosecs = 0); + // timedwait() is given an absolute time to wait until. To wait for a + // relative time from now, use omni_thread::get_time. See POSIX threads + // documentation for why absolute times are better than relative. + // Returns 1 (true) if successfully signalled, 0 (false) if time + // expired. + + void signal(void); + // if one or more threads have called wait(), signal wakes up at least + // one of them, possibly more. See POSIX threads documentation for + // details. + + void broadcast(void); + // broadcast is like signal but wakes all threads which have called + // wait(). + +private: + // dummy copy constructor and operator= to prevent copying + omni_condition(const omni_condition&); + omni_condition& operator=(const omni_condition&); + +OMNI_THREAD_EXPOSE: + OMNI_CONDITION_IMPLEMENTATION +}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting (or binary) semaphore +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_semaphore { + +public: + // if max_count == 1, you've got a binary semaphore. + omni_semaphore(unsigned int initial = 1, unsigned int max_count = 0x7fffffff); + ~omni_semaphore(void); + + void wait(void); + // if semaphore value is > 0 then decrement it and carry on. If it's + // already 0 then block. + + int trywait(void); + // if semaphore value is > 0 then decrement it and return 1 (true). + // If it's already 0 then return 0 (false). + + void post(void); + // if any threads are blocked in wait(), wake one of them up. Otherwise + // increment the value of the semaphore. + +private: + // dummy copy constructor and operator= to prevent copying + omni_semaphore(const omni_semaphore&); + omni_semaphore& operator=(const omni_semaphore&); + +OMNI_THREAD_EXPOSE: + OMNI_SEMAPHORE_IMPLEMENTATION +}; + +// +// A helper class for semaphores, similar to omni_mutex_lock above. +// + +class _OMNITHREAD_NTDLL_ omni_semaphore_lock { + omni_semaphore& sem; +public: + omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); } + ~omni_semaphore_lock(void) { sem.post(); } +private: + // dummy copy constructor and operator= to prevent copying + omni_semaphore_lock(const omni_semaphore_lock&); + omni_semaphore_lock& operator=(const omni_semaphore_lock&); +}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_thread { + +public: + + enum priority_t { + PRIORITY_LOW, + PRIORITY_NORMAL, + PRIORITY_HIGH + }; + + enum state_t { + STATE_NEW, // thread object exists but thread hasn't + // started yet. + STATE_RUNNING, // thread is running. + STATE_TERMINATED // thread has terminated but storage has not + // been reclaimed (i.e. waiting to be joined). + }; + + // + // Constructors set up the thread object but the thread won't start until + // start() is called. The create method can be used to construct and start + // a thread in a single call. + // + + omni_thread(void (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + omni_thread(void* (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + // these constructors create a thread which will run the given function + // when start() is called. The thread will be detached if given a + // function with void return type, undetached if given a function + // returning void*. If a thread is detached, storage for the thread is + // reclaimed automatically on termination. Only an undetached thread + // can be joined. + + void start(void); + // start() causes a thread created with one of the constructors to + // start executing the appropriate function. + +protected: + + omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL); + // this constructor is used in a derived class. The thread will + // execute the run() or run_undetached() member functions depending on + // whether start() or start_undetached() is called respectively. + + void start_undetached(void); + // can be used with the above constructor in a derived class to cause + // the thread to be undetached. In this case the thread executes the + // run_undetached member function. + + virtual ~omni_thread(void); + // destructor cannot be called by user (except via a derived class). + // Use exit() or cancel() instead. This also means a thread object must + // be allocated with new - it cannot be statically or automatically + // allocated. The destructor of a class that inherits from omni_thread + // shouldn't be public either (otherwise the thread object can be + // destroyed while the underlying thread is still running). + +public: + + void join(void**); + // join causes the calling thread to wait for another's completion, + // putting the return value in the variable of type void* whose address + // is given (unless passed a null pointer). Only undetached threads + // may be joined. Storage for the thread will be reclaimed. + + void set_priority(priority_t); + // set the priority of the thread. + + static omni_thread* create(void (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + static omni_thread* create(void* (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + // create spawns a new thread executing the given function with the + // given argument at the given priority. Returns a pointer to the + // thread object. It simply constructs a new thread object then calls + // start. + + static void exit(void* return_value = NULL); + // causes the calling thread to terminate. + + static omni_thread* self(void); + // returns the calling thread's omni_thread object. If the + // calling thread is not the main thread and is not created + // using this library, returns 0. (But see create_dummy() + // below.) + + static void yield(void); + // allows another thread to run. + + static void sleep(unsigned long secs, unsigned long nanosecs = 0); + // sleeps for the given time. + + static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec = 0, unsigned long rel_nsec=0); + // calculates an absolute time in seconds and nanoseconds, suitable for + // use in timed_waits on condition variables, which is the current time + // plus the given relative offset. + + + static void stacksize(unsigned long sz); + static unsigned long stacksize(); + // Use this value as the stack size when spawning a new thread. + // The default value (0) means that the thread library default is + // to be used. + + + // Per-thread data + // + // These functions allow you to attach additional data to an + // omni_thread. First allocate a key for yourself with + // allocate_key(). Then you can store any object whose class is + // derived from value_t. Any values still stored in the + // omni_thread when the thread exits are deleted. + // + // These functions are NOT thread safe, so you should be very + // careful about setting/getting data in a different thread to the + // current thread. + + typedef unsigned int key_t; + static key_t allocate_key(); + + class value_t { + public: + virtual ~value_t() {} + }; + + value_t* set_value(key_t k, value_t* v); + // Sets a value associated with the given key. The key must + // have been allocated with allocate_key(). If a value has + // already been set with the specified key, the old value_t + // object is deleted and replaced. Returns the value which was + // set, or zero if the key is invalid. + + value_t* get_value(key_t k); + // Returns the value associated with the key. If the key is + // invalid, or there is no value for the key, returns zero. + + value_t* remove_value(key_t k); + // Removes the value associated with the key and returns it. + // If the key is invalid, or there is no value for the key, + // returns zero. + + + // Dummy omni_thread + // + // Sometimes, an application finds itself with threads created + // outside of omnithread which must interact with omnithread + // features such as the per-thread data. In this situation, + // omni_thread::self() would normally return 0. These functions + // allow the application to create a suitable dummy omni_thread + // object. + + static omni_thread* create_dummy(void); + // creates a dummy omni_thread for the calling thread. Future + // calls to self() will return the dummy omni_thread. Throws + // omni_thread_invalid if this thread already has an + // associated omni_thread (real or dummy). + + static void release_dummy(); + // release the dummy omni_thread for this thread. This + // function MUST be called before the thread exits. Throws + // omni_thread_invalid if the calling thread does not have a + // dummy omni_thread. + + // class ensure_self should be created on the stack. If created in + // a thread without an associated omni_thread, it creates a dummy + // thread which is released when the ensure_self object is deleted. + + class ensure_self { + public: + inline ensure_self() : _dummy(0) + { + _self = omni_thread::self(); + if (!_self) { + _dummy = 1; + _self = omni_thread::create_dummy(); + } + } + inline ~ensure_self() + { + if (_dummy) + omni_thread::release_dummy(); + } + inline omni_thread* self() { return _self; } + private: + omni_thread* _self; + int _dummy; + }; + + +private: + + virtual void run(void* /*arg*/) {} + virtual void* run_undetached(void* /*arg*/) { return NULL; } + // can be overridden in a derived class. When constructed using the + // the constructor omni_thread(void*, priority_t), these functions are + // called by start() and start_undetached() respectively. + + void common_constructor(void* arg, priority_t pri, int det); + // implements the common parts of the constructors. + + omni_mutex mutex; + // used to protect any members which can change after construction, + // i.e. the following 2 members. + + state_t _state; + priority_t _priority; + + static omni_mutex* next_id_mutex; + static int next_id; + int _id; + + void (*fn_void)(void*); + void* (*fn_ret)(void*); + void* thread_arg; + int detached; + int _dummy; + value_t** _values; + unsigned long _value_alloc; + + omni_thread(const omni_thread&); + omni_thread& operator=(const omni_thread&); + // Not implemented + +public: + + priority_t priority(void) { + + // return this thread's priority. + + omni_mutex_lock l(mutex); + return _priority; + } + + state_t state(void) { + + // return thread state (invalid, new, running or terminated). + + omni_mutex_lock l(mutex); + return _state; + } + + int id(void) { return _id; } + // return unique thread id within the current process. + + + // This class plus the instance of it declared below allows us to execute + // some initialisation code before main() is called. + + class _OMNITHREAD_NTDLL_ init_t { + public: + init_t(void); + ~init_t(void); + }; + + friend class init_t; + friend class omni_thread_dummy; + +OMNI_THREAD_EXPOSE: + OMNI_THREAD_IMPLEMENTATION +}; + +#ifndef __rtems__ +static omni_thread::init_t omni_thread_init; +#else +// RTEMS calls global Ctor/Dtor in a context that is not +// a posix thread. Calls to functions to pthread_self() in +// that context returns NULL. +// So, for RTEMS we will make the thread initialization at the +// beginning of the Init task that has a posix context. +#endif + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_VxThread.h b/gnuradio-core/src/lib/omnithread/ot_VxThread.h new file mode 100644 index 00000000..e96c036c --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_VxThread.h @@ -0,0 +1,118 @@ +#ifndef __VXTHREAD_H__ +#define __VXTHREAD_H__ +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Project: omniORB +%% Filename: $Filename$ +%% Author: Guillaume/Bill ARRECKX +%% Copyright Wavetek Wandel & Goltermann, Plymouth. +%% Description: OMNI thread implementation classes for VxWorks threads +%% Notes: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% $Log$ +%% Revision 1.1 2004/04/10 18:00:52 eb +%% Initial revision +%% +%% Revision 1.1.1.1 2004/03/01 00:20:27 eb +%% initial checkin +%% +%% Revision 1.1 2003/05/25 05:29:04 eb +%% see ChangeLog +%% +%% Revision 1.1.2.1 2003/02/17 02:03:07 dgrisby +%% vxWorks port. (Thanks Michael Sturm / Acterna Eningen GmbH). +%% +%% Revision 1.1.1.1 2002/11/19 14:55:21 sokcevti +%% OmniOrb4.0.0 VxWorks port +%% +%% Revision 1.2 2002/06/14 12:45:50 engeln +%% unnecessary members in condition removed. +%% --- +%% +%% Revision 1.1.1.1 2002/04/02 10:08:49 sokcevti +%% omniORB4 initial realease +%% +%% Revision 1.1 2001/03/23 16:50:23 hartmut +%% Initial Version 2.8 +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +*/ + + +/////////////////////////////////////////////////////////////////////////// +// Includes +/////////////////////////////////////////////////////////////////////////// +#include +#include +#include + + +/////////////////////////////////////////////////////////////////////////// +// Externs prototypes +/////////////////////////////////////////////////////////////////////////// +extern "C" void omni_thread_wrapper(void* ptr); + + +/////////////////////////////////////////////////////////////////////////// +// Exported macros +// Note: These are added as private members in each class implementation. +/////////////////////////////////////////////////////////////////////////// +#define OMNI_MUTEX_IMPLEMENTATION \ + SEM_ID mutexID; \ + bool m_bConstructed; + +#define OMNI_CONDITION_IMPLEMENTATION \ + long waiters_; \ + SEM_ID waiters_lock_; \ + SEM_ID sema_; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + SEM_ID semID; + +#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ + if(semTake(mutexID, WAIT_FOREVER) != OK) \ + { \ + throw omni_thread_fatal(errno); \ + } + +#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ + if(semGive(mutexID) != OK) \ + { \ + throw omni_thread_fatal(errno); \ + } + +#define OMNI_THREAD_IMPLEMENTATION \ + friend void omni_thread_wrapper(void* ptr); \ + static int vxworks_priority(priority_t); \ + omni_condition *running_cond; \ + void* return_val; \ + int tid; \ + public: \ + static void attach(void); \ + static void detach(void); \ + static void show(void); + + +/////////////////////////////////////////////////////////////////////////// +// Porting macros +/////////////////////////////////////////////////////////////////////////// +// This is a wrapper function for the 'main' function which does not exists +// as such in VxWorks. The wrapper creates a launch function instead, +// which spawns the application wrapped in a omni_thread. +// Argc will always be null. +/////////////////////////////////////////////////////////////////////////// +#define main( discarded_argc, discarded_argv ) \ + omni_discard_retval() \ + { \ + throw; \ + } \ + int omni_main( int argc, char **argv ); \ + void launch( ) \ + { \ + omni_thread* th = new omni_thread( (void(*)(void*))omni_main );\ + th->start();\ + }\ + int omni_main( int argc, char **argv ) + + +#endif // ndef __VXTHREAD_H__ diff --git a/gnuradio-core/src/lib/omnithread/ot_mach.h b/gnuradio-core/src/lib/omnithread/ot_mach.h new file mode 100644 index 00000000..483f600f --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_mach.h @@ -0,0 +1,51 @@ +// Package : omnithread +// omnithread/posix.h Created : 7/97 lars immisch lars@ibp.de +// +// Copyright (C) 1994,1995,1996, 1997 Immisch, becker & Partner +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// OMNI thread implementation classes for posix threads +// + +#ifndef __omnithread_mach_h_ +#define __omnithread_mach_h_ + +#include + +extern "C" void* omni_thread_wrapper(void* ptr); + +#define OMNI_MUTEX_IMPLEMENTATION \ + struct mutex mach_mutex; + +#define OMNI_CONDITION_IMPLEMENTATION \ + struct condition mach_cond; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + omni_mutex m; \ + omni_condition c; \ + int value; + + +#define OMNI_THREAD_IMPLEMENTATION \ + cthread_t mach_thread; \ + static int mach_priority(priority_t); \ + friend void* omni_thread_wrapper(void* ptr); + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_nt.h b/gnuradio-core/src/lib/omnithread/ot_nt.h new file mode 100644 index 00000000..3ed173f2 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_nt.h @@ -0,0 +1,85 @@ +// Package : omnithread +// omnithread/nt.h Created : 6/95 tjr +// +// Copyright (C) 1995, 1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// OMNI thread implementation classes for NT threads. +// + +#ifndef __omnithread_nt_h_ +#define __omnithread_nt_h_ + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN +#endif + +#include + +#ifdef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +# undef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +#endif + + +#ifndef __BCPLUSPLUS__ +#define OMNI_THREAD_WRAPPER \ + unsigned __stdcall omni_thread_wrapper(LPVOID ptr); +#else +#define OMNI_THREAD_WRAPPER \ + void _USERENTRY omni_thread_wrapper(void *ptr); +#endif + +extern "C" OMNI_THREAD_WRAPPER; + +#define OMNI_MUTEX_IMPLEMENTATION \ + CRITICAL_SECTION crit; + +#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ + EnterCriticalSection(&crit); + +#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ + TryEnterCriticalSection(&crit); + +#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ + LeaveCriticalSection(&crit); + +#define OMNI_CONDITION_IMPLEMENTATION \ + CRITICAL_SECTION crit; \ + omni_thread* waiting_head; \ + omni_thread* waiting_tail; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + HANDLE nt_sem; + +#define OMNI_THREAD_IMPLEMENTATION \ + HANDLE handle; \ + DWORD nt_id; \ + void* return_val; \ + HANDLE cond_semaphore; \ + omni_thread* cond_next; \ + omni_thread* cond_prev; \ + BOOL cond_waiting; \ + static int nt_priority(priority_t); \ + friend class omni_condition; \ + friend OMNI_THREAD_WRAPPER; + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_posix.h b/gnuradio-core/src/lib/omnithread/ot_posix.h new file mode 100644 index 00000000..1e5bf9d2 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_posix.h @@ -0,0 +1,81 @@ +// Package : omnithread +// omnithread/posix.h Created : 7/94 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// OMNI thread implementation classes for posix threads +// + +#ifndef __omnithread_posix_h_ +#define __omnithread_posix_h_ + +#if defined(__alpha__) && defined(__osf1__) || defined(__hpux__) +// stop unnecessary definitions of TRY, etc on OSF +#ifndef EXC_HANDLING +#define EXC_HANDLING +#endif +#endif + +#ifndef __POSIX_NT__ +# include +#else +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# endif +# include +# include "pthread_nt.h" +# ifdef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +# undef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# endif +#endif + +extern "C" void* omni_thread_wrapper(void* ptr); + +#define OMNI_MUTEX_IMPLEMENTATION \ + pthread_mutex_t posix_mutex; + +#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ + pthread_mutex_lock(&posix_mutex); + +#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ + (pthread_mutex_trylock(&posix_mutex)==0); + +#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ + pthread_mutex_unlock(&posix_mutex); + +#define OMNI_CONDITION_IMPLEMENTATION \ + pthread_cond_t posix_cond; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + omni_mutex m; \ + omni_condition c; \ + int value; \ + int max_count; + +#define OMNI_THREAD_IMPLEMENTATION \ + pthread_t posix_thread; \ + static int posix_priority(priority_t); \ + friend void* omni_thread_wrapper(void* ptr); + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_pthread_nt.h b/gnuradio-core/src/lib/omnithread/ot_pthread_nt.h new file mode 100644 index 00000000..cf3d8794 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_pthread_nt.h @@ -0,0 +1,186 @@ +/* Package : omnithread + omnithread/pthread_nt.h Created : Steven Brenneis + + Copyright (C) 1998 Steven Brennes + + This file is part of the omnithread library + + The omnithread library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA + + Posix Threads implementation for Windows NT, version 4.0 +*/ + +#ifndef PTHREAD_NT_H_INCLUDED +#define PTHREAD_NT_H_INCLUDED + +#include + +#ifndef ETIMEDOUT +// May have to be changed if NT starts supporting more errno values +#define ETIMEDOUT 60 +#endif + +#undef PthreadDraftVersion +#define PthreadDraftVersion 10 + +#define NoNanoSleep + +#define PthreadSupportThreadPriority + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _TIMERS_T_ +#define _TIMERS_T_ + typedef struct timespec { + unsigned long tv_sec; + long tv_nsec; + } timespec_t; +#endif + +typedef char* __pthreadLongString_t; +typedef void* __pthreadLongAddr_t; +typedef __pthreadLongAddr_t* __pthreadLongAddr_p; +typedef long __pthreadLongInt_t; +typedef unsigned long __pthreadLongUint_t; +typedef __pthreadLongAddr_p __pthreadTsd_t; + +typedef struct __pthread_mutex_t { + unsigned int lock; /* LOCK, SLOW, TYPE, RECURSIVE */ + unsigned int valid; /* Validation info */ + __pthreadLongString_t name; /* Name of mutex */ + unsigned int arg; /* printf argument for name */ + unsigned int depth; /* Recursive lock depth */ + unsigned long sequence; /* Mutex sequence number */ + unsigned long owner; /* Current owner (if known */ + __pthreadLongAddr_t block; /* Pointer to blocking struct */ +} pthread_mutex_t; + +typedef struct __pthread_mutexattr_t { + long valid; + __pthreadLongUint_t reserved[15]; +} pthread_mutexattr_t; + +typedef struct __pthread_cond_t { + unsigned int state; /* EVENT, SLOW, REFCNT */ + unsigned int valid; /* Validation info */ + __pthreadLongString_t name; /* Name of condition variable */ + unsigned int arg; /* printf argument for name */ + unsigned long sequence; /* Condition variable seq # */ + __pthreadLongAddr_t block; /* Pointer to blocking struct */ +} pthread_cond_t ; + +typedef struct __pthread_condattr_t { + long valid; + __pthreadLongUint_t reserved[13]; +} pthread_condattr_t ; + +typedef struct __pthread_transp_t { + __pthreadLongAddr_t reserved1; /* Reserved to posix_nt */ + __pthreadLongAddr_t reserved2; /* Reserved to posix_nt */ + unsigned short size; /* Size of data structure */ + unsigned char reserved3[2]; /* Reserved to posix_nt */ + __pthreadLongAddr_t reserved4; /* Reserved to posix_nt */ + __pthreadLongUint_t sequence; /* Thread sequence number */ + __pthreadLongUint_t reserved5[2]; /* Reserved to posix_nt */ + __pthreadLongAddr_t per_kt_area; /* Pointer to kernel context */ + __pthreadLongAddr_t stack_base; /* Current stack base */ + __pthreadLongAddr_t stack_reserve; /* Current stack reserve zone */ + __pthreadLongAddr_t stack_yellow; /* Current stack yellow zone */ + __pthreadLongAddr_t stack_guard; /* Current stack guard zone */ + __pthreadLongUint_t stack_size; /* Size of stack */ + __pthreadTsd_t tsd_values; /* TSD array (indexed by key) */ + unsigned long tsd_count; /* Number of TSD cells */ + __pthreadLongAddr_t reserved6; /* Reserved to posix_nt */ + __pthreadLongAddr_t reserved7; /* Reserved to posix_nt */ + unsigned int thread_flags; /* Dynamic external state */ +} pthread_transp_t, *pthread_transp_p; + +typedef pthread_transp_p pthread_t; + +typedef struct __pthread_attr_t { + long valid; + __pthreadLongString_t name; + __pthreadLongUint_t arg; + __pthreadLongUint_t reserved[19]; +} pthread_attr_t ; + +typedef unsigned int pthread_key_t; + +typedef struct sched_param { + int sched_priority; +} sched_param_t; + +/* Function Prototypes */ + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); +int pthread_detach(pthread_t thread); +int pthread_join(pthread_t thread, void **value_ptr); +void pthread_exit(void *value_ptr); +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_destroy(pthread_attr_t *attr); +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); +int pthread_attr_getstacksize(const pthread_attr_t *attr, + size_t *stacksize); +int pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); +int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); +int pthread_key_delete(pthread_key_t key); +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *attr); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); +pthread_t pthread_self(); +int pthread_setspecific(pthread_key_t key, const void *value); +void *pthread_getspecific(pthread_key_t key); +int pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param); +int pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param); +int pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param); +int pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param); + +int pthread_delay_np(const struct timespec *interval); +int pthread_get_expiration_np(const struct timespec *delta, + struct timespec *abstime); + +# define SCHED_FIFO 1 +# define SCHED_RR 2 +# define SCHED_OTHER 3 + +int sched_yield(); +int sched_get_priority_max(int policy); +int sched_get_priority_min(int policy); + + +#ifdef __cplusplus +} +#endif + +#endif // PTHREAD_NT_H_INCLUDED diff --git a/gnuradio-core/src/lib/omnithread/ot_solaris.h b/gnuradio-core/src/lib/omnithread/ot_solaris.h new file mode 100644 index 00000000..aaef036f --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_solaris.h @@ -0,0 +1,47 @@ +// Package : omnithread +// omnithread/solaris.h Created : 7/94 tjr +// +// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// OMNI thread implementation classes for solaris threads. +// + +#ifndef __omnithread_solaris_h_ +#define __omnithread_solaris_h_ + +#include + +extern "C" void* omni_thread_wrapper(void* ptr); + +#define OMNI_MUTEX_IMPLEMENTATION \ + mutex_t sol_mutex; + +#define OMNI_CONDITION_IMPLEMENTATION \ + cond_t sol_cond; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + sema_t sol_sem; + +#define OMNI_THREAD_IMPLEMENTATION \ + thread_t sol_thread; \ + static int sol_priority(priority_t); \ + friend void* omni_thread_wrapper(void* ptr); + +#endif diff --git a/gnuradio-core/src/lib/omnithread/posix.cc b/gnuradio-core/src/lib/omnithread/posix.cc new file mode 100644 index 00000000..5fda14fc --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/posix.cc @@ -0,0 +1,972 @@ +// Package : omnithread +// omnithread/posix.cc Created : 7/94 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1994-1999 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Implementation of OMNI thread abstraction for posix threads +// +// The source below tests for the definition of the macros: +// PthreadDraftVersion +// PthreadSupportThreadPriority +// NoNanoSleep +// NeedPthreadInit +// +// As different draft versions of the pthread standard P1003.4a/P1003.1c +// define slightly different APIs, the macro 'PthreadDraftVersion' +// identifies the draft version supported by this particular platform. +// +// Some unix variants do not support thread priority unless a real-time +// kernel option is installed. The macro 'PthreadSupportThreadPriority', +// if defined, enables the use of thread priority. If it is not defined, +// setting or changing thread priority will be silently ignored. +// +// nanosleep() is defined in Posix P1003.4 since Draft 9 (?). +// Not all platforms support this standard. The macro 'NoNanoSleep' +// identifies platform that don't. +// + +#include +#include +#include +#include +#include + +#ifdef HAVE_NANOSLEEP +#undef NoNanoSleep +#else +#define NoNanoSleep +#endif + +#ifdef HAVE_SYS_TIME_H +// typedef of struct timeval and gettimeofday(); +#include +#include +#endif + +#if defined(__linux__) && defined(_MIT_POSIX_THREADS) +#include +#endif + +#if defined(__irix__) && defined(PthreadSupportThreadPriority) +#if _POSIX_THREAD_PRIORITY_SCHEDULING +#include +#endif +#endif + +#define DB(x) // x +//#include or #include if DB is on. + +#if (PthreadDraftVersion <= 6) +#define ERRNO(x) (((x) != 0) ? (errno) : 0) +#ifdef __VMS +// pthread_setprio returns old priority on success (draft version 4: +// OpenVms version < 7) +#define THROW_ERRORS(x) { if ((x) == -1) throw omni_thread_fatal(errno); } +#else +#define THROW_ERRORS(x) { if ((x) != 0) throw omni_thread_fatal(errno); } +#endif +#else +#define ERRNO(x) (x) +#define THROW_ERRORS(x) { int rc = (x); \ + if (rc != 0) throw omni_thread_fatal(rc); } +#endif + + + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_mutex_init(&posix_mutex, pthread_mutexattr_default)); +#else + THROW_ERRORS(pthread_mutex_init(&posix_mutex, 0)); +#endif +} + +omni_mutex::~omni_mutex(void) +{ + THROW_ERRORS(pthread_mutex_destroy(&posix_mutex)); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_cond_init(&posix_cond, pthread_condattr_default)); +#else + THROW_ERRORS(pthread_cond_init(&posix_cond, 0)); +#endif +} + +omni_condition::~omni_condition(void) +{ + THROW_ERRORS(pthread_cond_destroy(&posix_cond)); +} + +void +omni_condition::wait(void) +{ + THROW_ERRORS(pthread_cond_wait(&posix_cond, &mutex->posix_mutex)); +} + +int +omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + +again: + int rc = ERRNO(pthread_cond_timedwait(&posix_cond, + &mutex->posix_mutex, &rqts)); + if (rc == 0) + return 1; + +#if (PthreadDraftVersion <= 6) + if (rc == EAGAIN) + return 0; +#endif + + // Some versions of unix produces this errno when the wait was + // interrupted by a unix signal or fork. + // Some versions of the glibc 2.0.x produces this errno when the + // program is debugged under gdb. Straightly speaking this is non-posix + // compliant. We catch this here to make debugging possible. + if (rc == EINTR) + goto again; + + if (rc == ETIMEDOUT) + return 0; + + throw omni_thread_fatal(rc); +#ifdef _MSC_VER + return 0; +#endif +} + +void +omni_condition::signal(void) +{ + THROW_ERRORS(pthread_cond_signal(&posix_cond)); +} + +void +omni_condition::broadcast(void) +{ + THROW_ERRORS(pthread_cond_broadcast(&posix_cond)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting (or binary) semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +omni_semaphore::omni_semaphore(unsigned int initial, unsigned int _max_count) : c(&m) +{ + value = initial; + max_count = _max_count; + if (value < 0 || max_count < 1) + throw omni_thread_fatal(0); +} + +omni_semaphore::~omni_semaphore(void) +{ +} + +void +omni_semaphore::wait(void) +{ + omni_mutex_lock l(m); + + while (value == 0) + c.wait(); + + value--; +} + +int +omni_semaphore::trywait(void) +{ + omni_mutex_lock l(m); + + if (value == 0) + return 0; + + value--; + return 1; +} + +void +omni_semaphore::post(void) +{ + { + omni_mutex_lock l(m); + if (value < max_count) + value++; + } + + c.signal(); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// static variables +// + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; + +static pthread_key_t self_key; + +#ifdef PthreadSupportThreadPriority +static int lowest_priority; +static int normal_priority; +static int highest_priority; +#endif + +#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) +// omniORB requires a larger stack size than the default (21120) on OSF/1 +static size_t stack_size = 32768; +#elif defined(__rtems__) +static size_t stack_size = ThreadStackSize; +#elif defined(__aix__) +static size_t stack_size = 262144; +#else +static size_t stack_size = 0; +#endif + +// +// Initialisation function (gets called before any user code). +// + +static int& count() { + static int the_count = 0; + return the_count; +} + +omni_thread::init_t::init_t(void) +{ + if (count()++ != 0) // only do it once however many objects get created. + return; + + DB(cerr << "omni_thread::init: posix 1003.4a/1003.1c (draft " + << PthreadDraftVersion << ") implementation initialising\n"); + +#ifdef NeedPthreadInit + + pthread_init(); + +#endif + +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_keycreate(&self_key, NULL)); +#else + THROW_ERRORS(pthread_key_create(&self_key, NULL)); +#endif + +#ifdef PthreadSupportThreadPriority + +#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) + + lowest_priority = PRI_OTHER_MIN; + highest_priority = PRI_OTHER_MAX; + +#elif defined(__hpux__) + + lowest_priority = PRI_OTHER_MIN; + highest_priority = PRI_OTHER_MAX; + +#elif defined(__sunos__) && (__OSVERSION__ == 5) + + // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0 + + lowest_priority = 1; + highest_priority = 3; + +#else + + lowest_priority = sched_get_priority_min(SCHED_FIFO); + highest_priority = sched_get_priority_max(SCHED_FIFO); + +#endif + + switch (highest_priority - lowest_priority) { + + case 0: + case 1: + normal_priority = lowest_priority; + break; + + default: + normal_priority = lowest_priority + 1; + break; + } + +#endif /* PthreadSupportThreadPriority */ + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + t->_state = STATE_RUNNING; + + t->posix_thread = pthread_self (); + + DB(cerr << "initial thread " << t->id() << endl); + + THROW_ERRORS(pthread_setspecific(self_key, (void*)t)); + +#ifdef PthreadSupportThreadPriority + +#if (PthreadDraftVersion == 4) + + THROW_ERRORS(pthread_setprio(t->posix_thread, + posix_priority(PRIORITY_NORMAL))); + +#elif (PthreadDraftVersion == 6) + + pthread_attr_t attr; + pthread_attr_init(&attr); + + THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(PRIORITY_NORMAL))); + + THROW_ERRORS(pthread_setschedattr(t->posix_thread, attr)); + +#else + + struct sched_param sparam; + + sparam.sched_priority = posix_priority(PRIORITY_NORMAL); + + THROW_ERRORS(pthread_setschedparam(t->posix_thread, SCHED_OTHER, &sparam)); + +#endif /* PthreadDraftVersion */ + +#endif /* PthreadSupportThreadPriority */ +} + +omni_thread::init_t::~init_t(void) +{ + if (--count() != 0) return; + + omni_thread* self = omni_thread::self(); + if (!self) return; + + pthread_setspecific(self_key, 0); + delete self; + + delete next_id_mutex; +} + +// +// Wrapper for thread creation. +// + +extern "C" void* +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread_wrapper: thread " << me->id() + << " started\n"); + + THROW_ERRORS(pthread_setspecific(self_key, me)); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. + + return NULL; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void +omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; + // posix_thread is set up in initialisation routine or start(). +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + + pthread_attr_t attr; + +#if (PthreadDraftVersion == 4) + pthread_attr_create(&attr); +#else + pthread_attr_init(&attr); +#endif + +#if (PthreadDraftVersion == 8) + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); +#endif + +#ifdef PthreadSupportThreadPriority + +#if (PthreadDraftVersion <= 6) + + THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(_priority))); + +#else + + struct sched_param sparam; + + sparam.sched_priority = posix_priority(_priority); + + THROW_ERRORS(pthread_attr_setschedparam(&attr, &sparam)); + +#endif /* PthreadDraftVersion */ + +#endif /* PthreadSupportThreadPriority */ + +#if !defined(__linux__) + if (stack_size) { + THROW_ERRORS(pthread_attr_setstacksize(&attr, stack_size)); + } +#endif + + +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_create(&posix_thread, attr, omni_thread_wrapper, + (void*)this)); + pthread_attr_delete(&attr); +#else + THROW_ERRORS(pthread_create(&posix_thread, &attr, omni_thread_wrapper, + (void*)this)); + pthread_attr_destroy(&attr); +#endif + + _state = STATE_RUNNING; + + if (detached) { + +#if (PthreadDraftVersion <= 6) + THROW_ERRORS(pthread_detach(&posix_thread)); +#else + THROW_ERRORS(pthread_detach(posix_thread)); +#endif + } +} + + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call pthread_join. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing pthread_join\n"); + + THROW_ERRORS(pthread_join(posix_thread, status)); + + DB(cerr << "omni_thread::join: pthread_join succeeded\n"); + +#if (PthreadDraftVersion == 4) + // With draft 4 pthreads implementations (HPUX 10.x and + // Digital Unix 3.2), have to detach the thread after + // join. If not, the storage for the thread will not be + // be reclaimed. + THROW_ERRORS(pthread_detach(&posix_thread)); +#endif + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + +#ifdef PthreadSupportThreadPriority + +#if (PthreadDraftVersion == 4) + + THROW_ERRORS(pthread_setprio(posix_thread, posix_priority(pri))); + +#elif (PthreadDraftVersion == 6) + + pthread_attr_t attr; + pthread_attr_init(&attr); + + THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(pri))); + + THROW_ERRORS(pthread_setschedattr(posix_thread, attr)); + +#else + + struct sched_param sparam; + + sparam.sched_priority = posix_priority(pri); + + THROW_ERRORS(pthread_setschedparam(posix_thread, SCHED_OTHER, &sparam)); + +#endif /* PthreadDraftVersion */ + +#endif /* PthreadSupportThreadPriority */ +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void +omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) + delete me; + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } + + pthread_exit(return_value); +} + + +omni_thread* +omni_thread::self(void) +{ + omni_thread* me; + +#if (PthreadDraftVersion <= 6) + + THROW_ERRORS(pthread_getspecific(self_key, (void**)&me)); + +#else + + me = (omni_thread *)pthread_getspecific(self_key); + +#endif + + if (!me) { + // This thread is not created by omni_thread::start because it + // doesn't has a class omni_thread instance attached to its key. + DB(cerr << "omni_thread::self: called with a non-omnithread. NULL is returned." << endl); + } + + return me; +} + + +void +omni_thread::yield(void) +{ +#if (PthreadDraftVersion == 6) + + pthread_yield(NULL); + +#elif (PthreadDraftVersion < 9) + + pthread_yield(); + +#else + + THROW_ERRORS(sched_yield()); + +#endif +} + + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + +#ifndef NoNanoSleep + + timespec remain; + while (nanosleep(&rqts, &remain)) { + if (errno == EINTR) { + rqts.tv_sec = remain.tv_sec; + rqts.tv_nsec = remain.tv_nsec; + continue; + } + else + throw omni_thread_fatal(errno); + } +#else + +#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined (__POSIX_NT__) + + if (pthread_delay_np(&rqts) != 0) + throw omni_thread_fatal(errno); + +#elif defined(__linux__) || defined(__aix__) + + if (secs > 2000) { + while ((secs = ::sleep(secs))) ; + } else { + usleep(secs * 1000000 + (nanosecs / 1000)); + } + +#elif defined(__darwin__) || defined(__macos__) + + // Single UNIX Specification says argument of usleep() must be + // less than 1,000,000. + secs += nanosecs / 1000000000; + nanosecs %= 1000000000; + while ((secs = ::sleep(secs))) ; + usleep(nanosecs / 1000); + +#else + + throw omni_thread_invalid(); + +#endif +#endif /* NoNanoSleep */ +} + + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + timespec abs; + +#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined(__POSIX_NT__) + + timespec rel; + rel.tv_sec = rel_sec; + rel.tv_nsec = rel_nsec; + THROW_ERRORS(pthread_get_expiration_np(&rel, &abs)); + +#else + +#ifdef HAVE_CLOCK_GETTIME /* __linux__ || __aix__ */ + + clock_gettime(CLOCK_REALTIME, &abs); + +#elif defined(HAVE_GETTIMEOFDAY) /* defined(__linux__) || defined(__aix__) || defined(__SCO_VERSION__) || defined(__darwin__) || defined(__macos__) */ + + struct timeval tv; + gettimeofday(&tv, NULL); + abs.tv_sec = tv.tv_sec; + abs.tv_nsec = tv.tv_usec * 1000; + +#else +#error no get time support +#endif /* __linux__ || __aix__ */ + + abs.tv_nsec += rel_nsec; + abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; + abs.tv_nsec = abs.tv_nsec % 1000000000; + +#endif /* __osf1__ && __alpha__ */ + + *abs_sec = abs.tv_sec; + *abs_nsec = abs.tv_nsec; +} + + +int +omni_thread::posix_priority(priority_t pri) +{ +#ifdef PthreadSupportThreadPriority + switch (pri) { + + case PRIORITY_LOW: + return lowest_priority; + + case PRIORITY_NORMAL: + return normal_priority; + + case PRIORITY_HIGH: + return highest_priority; + + } +#endif + + throw omni_thread_invalid(); +#ifdef _MSC_VER + return 0; +#endif +} + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + +// +// Dummy thread +// + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + posix_thread = pthread_self(); + THROW_ERRORS(pthread_setspecific(self_key, (void*)this)); + } + inline ~omni_thread_dummy() + { + THROW_ERRORS(pthread_setspecific(self_key, 0)); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/solaris.cc b/gnuradio-core/src/lib/omnithread/solaris.cc new file mode 100644 index 00000000..827a645f --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/solaris.cc @@ -0,0 +1,615 @@ +// Package : omnithread +// omnithread/solaris.cc Created : 7/94 tjr +// +// Copyright (C) 1994-1999 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// Implementation of OMNI thread abstraction for solaris threads. +// + +#include +#include +#include + +#define DB(x) // x +// #include or #include if DB is on. + +#define THROW_ERRORS(x) { int rc = (x); \ + if (rc != 0) throw omni_thread_fatal(rc); } + + + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ + THROW_ERRORS(mutex_init(&sol_mutex, USYNC_THREAD, 0)); +} + +omni_mutex::~omni_mutex(void) +{ + THROW_ERRORS(mutex_destroy(&sol_mutex)); +} + +void +omni_mutex::lock(void) +{ + THROW_ERRORS(mutex_lock(&sol_mutex)); +} + +void +omni_mutex::unlock(void) +{ + THROW_ERRORS(mutex_unlock(&sol_mutex)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + THROW_ERRORS(cond_init(&sol_cond, USYNC_THREAD, 0)); +} + +omni_condition::~omni_condition(void) +{ + THROW_ERRORS(cond_destroy(&sol_cond)); +} + +void +omni_condition::wait(void) +{ + THROW_ERRORS(cond_wait(&sol_cond, &mutex->sol_mutex)); +} + +int +omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + + again: + int rc = cond_timedwait(&sol_cond, &mutex->sol_mutex, &rqts); + + if (rc == 0) + return 1; + + if (rc == EINTR) + goto again; + + if (rc == ETIME) + return 0; + + throw omni_thread_fatal(rc); +} + +void +omni_condition::signal(void) +{ + THROW_ERRORS(cond_signal(&sol_cond)); +} + +void +omni_condition::broadcast(void) +{ + THROW_ERRORS(cond_broadcast(&sol_cond)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +omni_semaphore::omni_semaphore(unsigned int initial) +{ + THROW_ERRORS(sema_init(&sol_sem, initial, USYNC_THREAD, NULL)); +} + +omni_semaphore::~omni_semaphore(void) +{ + THROW_ERRORS(sema_destroy(&sol_sem)); +} + +void +omni_semaphore::wait(void) +{ + THROW_ERRORS(sema_wait(&sol_sem)); +} + +void +omni_semaphore::post(void) +{ + THROW_ERRORS(sema_post(&sol_sem)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// Static variables +// + +int omni_thread::init_t::count = 0; + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; + +static thread_key_t self_key; + +static size_t stack_size = 0; + +// +// Initialisation function (gets called before any user code). +// + +omni_thread::init_t::init_t(void) +{ + if (count++ != 0) // only do it once however many objects get created. + return; + + DB(cerr << "omni_thread::init: solaris implementation initialising\n"); + + THROW_ERRORS(thr_keycreate(&self_key, NULL)); + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + t->_state = STATE_RUNNING; + + t->sol_thread = thr_self(); + + DB(cerr << "initial thread " << t->id() << " sol_thread " << t->sol_thread + << endl); + + THROW_ERRORS(thr_setspecific(self_key, (void*)t)); + + THROW_ERRORS(thr_setprio(t->sol_thread, sol_priority(PRIORITY_NORMAL))); +} + + +// +// Wrapper for thread creation. +// + +extern "C" void* +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread::wrapper: thread " << me->id() + << " started\n"); + + THROW_ERRORS(thr_setspecific(self_key, me)); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. + + return NULL; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void +omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; + // sol_thread is set up in initialisation routine or start(). +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + long flags = 0; + + if (detached) + flags |= THR_DETACHED; + + omni_mutex_lock l(mutex); + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + + THROW_ERRORS(thr_create(0, stack_size, omni_thread_wrapper, (void*)this, flags, + &sol_thread)); + + _state = STATE_RUNNING; + + THROW_ERRORS(thr_setprio(sol_thread, sol_priority(_priority))); +} + + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call thr_join. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing thr_join\n"); + + THROW_ERRORS(thr_join(sol_thread, (thread_t *)NULL, status)); + + DB(cerr << "omni_thread::join: thr_join succeeded\n"); + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + + THROW_ERRORS(thr_setprio(sol_thread, sol_priority(pri))); +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void +omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) + delete me; + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } + + thr_exit(return_value); +} + + +omni_thread* +omni_thread::self(void) +{ + omni_thread* me; + + THROW_ERRORS(thr_getspecific(self_key, (void**)&me)); + + if (!me) { + // This thread is not created by omni_thread::start because it + // doesn't has a class omni_thread instance attached to its key. + DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); + } + + return me; +} + + +void +omni_thread::yield(void) +{ + thr_yield(); +} + + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + timespec remain; + while (nanosleep(&rqts, &remain)) { + if (errno == EINTR) { + rqts.tv_sec = remain.tv_sec; + rqts.tv_nsec = remain.tv_nsec; + continue; + } + else + throw omni_thread_fatal(errno); + } +} + + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + timespec abs; + clock_gettime(CLOCK_REALTIME, &abs); + abs.tv_nsec += rel_nsec; + abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; + abs.tv_nsec = abs.tv_nsec % 1000000000; + *abs_sec = abs.tv_sec; + *abs_nsec = abs.tv_nsec; +} + + +int +omni_thread::sol_priority(priority_t pri) +{ + switch (pri) { + + case PRIORITY_LOW: + return 0; + + case PRIORITY_NORMAL: + return 1; + + case PRIORITY_HIGH: + return 2; + } + + throw omni_thread_invalid(); +} + + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + + +// +// Dummy thread +// + +#error This dummy thread code is not tested. It might work if you're lucky. + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + sol_thread = thr_self(); + THROW_ERRORS(thr_setspecific(self_key, (void*)this)); + } + inline ~omni_thread_dummy() + { + THROW_ERRORS(thr_setspecific(self_key, 0)); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/threaddata.cc b/gnuradio-core/src/lib/omnithread/threaddata.cc new file mode 100644 index 00000000..3d007714 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/threaddata.cc @@ -0,0 +1,83 @@ +// Package : omnithread +// omnithread/threaddata.cc Created : 10/2000 dpg1 +// +// Copyright (C) 2000 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// Implementation of per-thread data + +#ifndef INSIDE_THREAD_IMPL_CC +#error "threaddata.cc must be #included by a thread implementation." +#endif + + +static omni_thread::key_t allocated_keys = 0; + +omni_thread::key_t +omni_thread::allocate_key() +{ + omni_mutex_lock l(*next_id_mutex); + return ++allocated_keys; +} + +omni_thread::value_t* +omni_thread::set_value(key_t k, value_t* v) +{ + if (k == 0) return 0; + if (k > _value_alloc) { + next_id_mutex->lock(); + key_t alloc = allocated_keys; + next_id_mutex->unlock(); + + if (k > alloc) return 0; + + value_t** nv = new value_t*[alloc]; + key_t i = 0; + if (_values) { + for (; i < _value_alloc; i++) + nv[i] = _values[i]; + delete [] _values; + } + for (; i < alloc; i++) + nv[i] = 0; + + _values = nv; + _value_alloc = alloc; + } + if (_values[k-1]) delete _values[k-1]; + _values[k-1] = v; + return v; +} + +omni_thread::value_t* +omni_thread::get_value(key_t k) +{ + if (k > _value_alloc) return 0; + return _values[k-1]; +} + +omni_thread::value_t* +omni_thread::remove_value(key_t k) +{ + if (k > _value_alloc) return 0; + value_t* v = _values[k-1]; + _values[k-1] = 0; + return v; +} diff --git a/gnuradio-core/src/lib/omnithread/vxWorks.cc b/gnuradio-core/src/lib/omnithread/vxWorks.cc new file mode 100644 index 00000000..25634ce9 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/vxWorks.cc @@ -0,0 +1,1160 @@ +////////////////////////////////////////////////////////////////////////////// +// Filename: vxWorks.cc +// Author: Tihomir Sokcevic +// Acterna, Eningen. +// Description: vxWorks adaptation of the omnithread wrapper classes +// Notes: Munching strategy is imperative +////////////////////////////////////////////////////////////////////////////// +// $Log$ +// Revision 1.1 2004/04/10 18:00:52 eb +// Initial revision +// +// Revision 1.1.1.1 2004/03/01 00:20:27 eb +// initial checkin +// +// Revision 1.1 2003/05/25 05:29:04 eb +// see ChangeLog +// +// Revision 1.1.2.1 2003/02/17 02:03:11 dgrisby +// vxWorks port. (Thanks Michael Sturm / Acterna Eningen GmbH). +// +// Revision 1.1.1.1 2002/11/19 14:58:04 sokcevti +// OmniOrb4.0.0 VxWorks port +// +// Revision 1.4 2002/10/15 07:54:09 kuttlest +// change semaphore from SEM_FIFO to SEM_PRIO +// --- +// +// Revision 1.3 2002/07/05 07:38:52 engeln +// made priority redefinable on load time by defining int variables +// omni_thread_prio_low = 220; +// omni_thread_prio_normal = 110; +// omni_thread_prio_high = 55; +// the default priority is prio_normal. +// The normal priority default has been increased from 200 to 110 and the +// high priority from 100 to 55. +// --- +// +// Revision 1.2 2002/06/14 12:44:57 engeln +// replaced possibly unsafe wakeup procedure in broadcast. +// --- +// +// Revision 1.1.1.1 2002/04/02 10:09:34 sokcevti +// omniORB4 initial realease +// +// Revision 1.0 2001/10/23 14:22:45 sokcevti +// Initial Version 4.00 +// --- +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Include files +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#include // assert +#include // intContext + + +////////////////////////////////////////////////////////////////////////////// +// Local defines +////////////////////////////////////////////////////////////////////////////// +#define ERRNO(x) (((x) != 0) ? (errno) : 0) +#define THROW_ERRORS(x) { if((x) != OK) throw omni_thread_fatal(errno); } +#define OMNI_THREAD_ID 0x7F7155AAl +#define OMNI_STACK_SIZE 32768l + +#ifdef _DEBUG + #include + #define DBG_TRACE(X) X +#else // _DEBUG + #define DBG_TRACE(X) +#endif // _DEBUG + +#define DBG_ASSERT(X) + +#define DBG_THROW(X) X + +int omni_thread_prio_low = 220; +int omni_thread_prio_normal = 110; +int omni_thread_prio_high = 55; +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// +omni_mutex::omni_mutex(void):m_bConstructed(false) +{ + mutexID = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); + + DBG_ASSERT(assert(mutexID != NULL)); + + if(mutexID==NULL) + { + DBG_TRACE(cout<<"Exception: omni_mutex::omni_mutex() tid: "<<(int)taskIdSelf()<mutexID<<" tid:"<<(int)taskIdSelf()<mutexID<<" tid:"<<(int)taskIdSelf()< count. + + STATUS status = semTake(waiters_lock_,WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<unlock(); + + // Wait to be awakened by a cond_signal() or cond_broadcast(). + status = semTake(sema_,WAIT_FOREVER); + + // reenable task rescheduling + taskUnlock(); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"< count. + status = semTake(waiters_lock_,WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<, even when errors + // occur because that's the guarantee that we give to our callers. + mutex->lock(); +} + + +// The time given is absolute. Return 0 is timeout +int omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) +{ + STATUS result = OK; + timespec now; + unsigned long timeout; + int ticks; + + // Prevent race conditions on the count. + STATUS status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<unlock(); + + // Wait to be awakened by a signal() or broadcast(). + ticks = (timeout * sysClkRateGet()) / 1000L; + result = semTake(sema_, ticks); + + // reenable task rescheduling + taskUnlock(); + + // Reacquire lock to avoid race conditions. + status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<id()<<" SemID:"<<(int)sema_<<" errno:"<, even when errors + // occur because that's the guarantee that we give to our callers. + mutex->lock(); + + if(result!=OK) // timeout + return 0; + + return 1; +} + +void omni_condition::signal(void) +{ + DBG_TRACE(cout<<"omni_condition::signal mutexID: "<<(int)mutex->mutexID<<" tid:"<<(int)taskIdSelf()< 0; + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<mutexID<<" tid:"<<(int)taskIdSelf()< must be locked before this call is made. + // This is needed to ensure that and are + // consistent relative to each other. + STATUS status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"< 0) + { + // We are broadcasting, even if there is just one waiter... + // Record the fact that we are broadcasting. This helps the + // cond_wait() method know how to optimize itself. Be sure to + // set this with the held. + have_waiters = 1; + } + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<id()<<" SemID:"<<(int)sema_<<" errno:"<spare1 = 0; + delete self; + + delete next_id_mutex; +} + + +// +// Wrapper for thread creation. +// +extern "C" void omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DBG_TRACE(cout<<"omni_thread_wrapper: thread "<id()<<" started\n"); + + // + // We can now tweaked the task info since the tcb exist now + // + me->mutex.lock(); // To ensure that start has had time to finish + taskTcb(me->tid)->spare1 = OMNI_THREAD_ID; + taskTcb(me->tid)->spare2 = (int)ptr; + me->mutex.unlock(); + + // + // Now invoke the thread function with the given argument. + // + if(me->fn_void != NULL) + { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if(me->fn_ret != NULL) + { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if(me->detached) + { + me->run(me->thread_arg); + omni_thread::exit(); + } + else + { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } +} + + +// +// Special functions for VxWorks only +// +void omni_thread::attach(void) +{ + DBG_TRACE(cout<<"omni_thread_attach: VxWorks mapping thread initialising\n"); + + int _tid = taskIdSelf(); + + // Check the task is not already attached + if(taskTcb(_tid)->spare1 == OMNI_THREAD_ID) + return; + + // Create the mutex required to lock the threads debugging id (create before the thread!!!) + if(next_id_mutex == 0) + next_id_mutex = new omni_mutex; + + // Create a thread object for THIS running process + omni_thread* t = new omni_thread; + + // Lock its mutex straigh away! + omni_mutex_lock l(t->mutex); + + // Adjust data members of this instance + t->_state = STATE_RUNNING; + t->tid = taskIdSelf(); + + // Set the thread values so it can be recongnised as a omni_thread + // Set the id last can possibly prevent race condition + taskTcb(t->tid)->spare2 = (int)t; + taskTcb(t->tid)->spare1 = OMNI_THREAD_ID; + + // Create the running_mutex at this stage, but leave it empty. We are not running + // in the task context HERE, so taking it would be disastrous. + t->running_cond = new omni_condition(&t->mutex); +} + + +void omni_thread::detach(void) +{ + DBG_TRACE(cout<<"omni_thread_detach: VxWorks detaching thread mapping\n"); + + int _tid = taskIdSelf(); + + // Check the task has a OMNI_THREAD attached + if(taskTcb(_tid)->spare1 != OMNI_THREAD_ID) + return; + + // Invalidate the id NOW ! + taskTcb(_tid)->spare1 = 0; + + // Even if NULL, it is safe to delete the thread + omni_thread* t = (omni_thread*)taskTcb(_tid)->spare2; + // Fininsh cleaning the tcb structure + taskTcb(_tid)->spare2 = 0; + + delete t; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. +void omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + // Set the debugging id + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + // Note : tid can only be setup when the task is up and running + tid = 0; + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; +} + +// +// Destructor for omni_thread. +// +omni_thread::~omni_thread(void) +{ + DBG_TRACE(cout<<"omni_thread::~omni_thread for thread "<wait(); + mutex.unlock(); + + if(status) + *status = return_val; + + delete this; +} + + +// +// Change this thread's priority. +// +void omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + DBG_ASSERT(assert(_state == STATE_RUNNING)); + + if(_state != STATE_RUNNING) + { + DBG_THROW(throw omni_thread_invalid()); + } + + _priority = pri; + + if(taskPrioritySet(tid, vxworks_priority(pri))==ERROR) + { + DBG_ASSERT(assert(false)); + + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version (the entry point is a void) +omni_thread* omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version (the entry point is a void*) +omni_thread* omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// +void omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if(me) + { + me->mutex.lock(); + + me->return_val = return_value; + me->_state = STATE_TERMINATED; + me->running_cond->signal(); + + me->mutex.unlock(); + + DBG_TRACE(cout<<"omni_thread::exit: thread "<id()<<" detached "<detached<<" return value "<<(int)return_value<detached) + delete me; + } + else + DBG_TRACE(cout<<"omni_thread::exit: called with a non-omnithread. Exit quietly."<spare1 != OMNI_THREAD_ID) + return NULL; + + return (omni_thread*)taskTcb(taskIdSelf())->spare2; +} + + +void omni_thread::yield(void) +{ + taskDelay(NO_WAIT); +} + + +void omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + int tps = sysClkRateGet(); + + // Convert to us to avoid overflow in the multiplication + // tps should always be less than 1000 ! + nanosecs /= 1000; + + taskDelay(secs*tps + (nanosecs*tps)/1000000l); +} + + +void omni_thread::get_time( unsigned long* abs_sec, + unsigned long* abs_nsec, + unsigned long rel_sec, + unsigned long rel_nsec) +{ + timespec abs; + clock_gettime(CLOCK_REALTIME, &abs); + abs.tv_nsec += rel_nsec; + abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; + abs.tv_nsec = abs.tv_nsec % 1000000000; + *abs_sec = abs.tv_sec; + *abs_nsec = abs.tv_nsec; +} + + +int omni_thread::vxworks_priority(priority_t pri) +{ + switch (pri) + { + case PRIORITY_LOW: + return omni_thread_prio_low; + + case PRIORITY_NORMAL: + return omni_thread_prio_normal; + + case PRIORITY_HIGH: + return omni_thread_prio_high; + } + + DBG_ASSERT(assert(false)); + + DBG_THROW(throw omni_thread_invalid()); +} + + +void omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + + +unsigned long omni_thread::stacksize() +{ + return stack_size; +} + + +void omni_thread::show(void) +{ + omni_thread *pThread; + int s1, s2; + int tid = taskIdSelf(); + + printf("TaskId is %.8x\n", tid); + + s1 = taskTcb(tid)->spare1; + + if(s1 != OMNI_THREAD_ID) + { + printf("Spare 1 is %.8x, and not recongnized\n", s1); + + return; + } + else + { + printf("Spare 1 indicate an omni_thread.\n"); + } + + s2 = taskTcb(tid)->spare2; + + if(s2 == 0) + { + printf("Spare 2 is NULL! - No thread object attached !!\n"); + + return; + } + else + { + printf("Thread object at %.8x\n", s2); + } + + pThread = (omni_thread *)s2; + + state_t status = pThread->_state; + + printf(" | Thread status is "); + + switch (status) + { + case STATE_NEW: + printf("NEW\n"); break; + case STATE_RUNNING: + printf("STATE_RUNNING\n"); break; + case STATE_TERMINATED: + printf("TERMINATED\n"); break; + default: + printf("Illegal (=%.8x)\n", (unsigned int)status); + + return; + } + + if(pThread->tid != tid) + { + printf(" | Task ID in thread object is different!! (=%.8x)\n", pThread->tid); + + return; + } + else + { + printf(" | Task ID in thread consistent\n"); + } + + printf("\n"); +} + + +// +// Dummy thread +// + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + + // Adjust data members of this instance + tid = taskIdSelf(); + + // Set the thread values so it can be recongnised as a omni_thread + // Set the id last can possibly prevent race condition + taskTcb(tid)->spare2 = (int)this; + taskTcb(tid)->spare1 = OMNI_THREAD_ID; + } + inline ~omni_thread_dummy() + { + taskTcb(taskIdSelf())->spare1 = 0; + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/reed-solomon/Makefile.am b/gnuradio-core/src/lib/reed-solomon/Makefile.am new file mode 100644 index 00000000..71af7664 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/Makefile.am @@ -0,0 +1,55 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Note, this Makefile.am only builds the char versions of the reed soloman routines. +# If you need the int versions too, please figure out how to add them *cleanly* to +# this Makefile.am. + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +TESTS = rstest + +EXTRA_DIST = \ + README.karn + +noinst_LTLIBRARIES = librs.la + +noinst_PROGRAMS = \ + rstest + +librs_la_SOURCES = \ + encode_rs.c \ + decode_rs.c \ + init_rs.c + +grinclude_HEADERS = \ + rs.h + +noinst_HEADERS = \ + ccsds.h \ + char.h \ + int.h \ + fixed.h + +rstest_SOURCES = rstest.c exercise.c +rstest_LDADD = librs.la diff --git a/gnuradio-core/src/lib/reed-solomon/Makefile.in.karn b/gnuradio-core/src/lib/reed-solomon/Makefile.in.karn new file mode 100644 index 00000000..8550b415 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/Makefile.in.karn @@ -0,0 +1,99 @@ +# Copyright 2002 Phil Karn, KA9Q +# May be used under the terms of the GNU General Public License (GPL) +# @configure_input@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix=@exec_prefix@ +VPATH = @srcdir@ +CC=@CC@ + +CFLAGS=@CFLAGS@ @ARCH_OPTION@ -Wall + +LIB= encode_rs_char.o encode_rs_int.o encode_rs_8.o \ + decode_rs_char.o decode_rs_int.o decode_rs_8.o \ + init_rs_char.o init_rs_int.o ccsds_tab.o \ + encode_rs_ccsds.o decode_rs_ccsds.o ccsds_tal.o + +all: librs.a librs.so.@SO_VERSION@ + +test: rstest + ./rstest + +rstest: rstest.o exercise_int.o exercise_char.o exercise_8.o exercise_ccsds.o \ + librs.a + gcc -g -o $@ $^ + +install: all + install -D -m 644 -p librs.a librs.so.@SO_VERSION@ @libdir@ + (cd @libdir@;ln -f -s librs.so.@SO_VERSION@ librs.so) + ldconfig + install -m 644 -p rs.h @includedir@ + install -m 644 rs.3 @mandir@/man3 + +librs.a: $(LIB) + ar rv $@ $^ + +librs.so.@SO_VERSION@: librs.a + gcc -shared -Xlinker -soname=librs.so.@SO_NAME@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive -lc + +encode_rs_char.o: encode_rs.c + gcc $(CFLAGS) -c -o $@ $^ + +encode_rs_int.o: encode_rs.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +encode_rs_8.o: encode_rs.c + gcc -DFIXED=1 $(CFLAGS) -c -o $@ $^ + +decode_rs_char.o: decode_rs.c + gcc $(CFLAGS) -c -o $@ $^ + +decode_rs_int.o: decode_rs.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +decode_rs_8.o: decode_rs.c + gcc -DFIXED=1 $(CFLAGS) -c -o $@ $^ + +init_rs_char.o: init_rs.c + gcc $(CFLAGS) -c -o $@ $^ + +init_rs_int.o: init_rs.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +ccsds_tab.o: ccsds_tab.c + +ccsds_tab.c: gen_ccsds + ./gen_ccsds > ccsds_tab.c + +gen_ccsds: gen_ccsds.o init_rs_char.o + gcc -o $@ $^ + +gen_ccsds.o: gen_ccsds.c + gcc $(CFLAGS) -c -o $@ $^ + +ccsds_tal.o: ccsds_tal.c + +ccsds_tal.c: gen_ccsds_tal + ./gen_ccsds_tal > ccsds_tal.c + +exercise_char.o: exercise.c + gcc $(CFLAGS) -c -o $@ $^ + +exercise_int.o: exercise.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +exercise_8.o: exercise.c + gcc -DFIXED=1 $(CFLAGS) -c -o $@ $^ + +exercise_ccsds.o: exercise.c + gcc -DCCSDS=1 $(CFLAGS) -c -o $@ $^ + + +clean: + rm -f *.o *.a ccsds_tab.c ccsds_tal.c gen_ccsds gen_ccsds_tal \ + rstest librs.so.@SO_VERSION@ + +distclean: clean + rm -f config.log config.cache config.status config.h makefile + + diff --git a/gnuradio-core/src/lib/reed-solomon/README b/gnuradio-core/src/lib/reed-solomon/README new file mode 100644 index 00000000..341832db --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/README @@ -0,0 +1,5 @@ +This code is from http://people.qualcomm.com/karn/code/fec +It is based on reed-soloman-3.1.1 (1 Jan 2002). + +I has been converted to use automake, to better integrate with GNU +Radio's build strategy. diff --git a/gnuradio-core/src/lib/reed-solomon/README.karn b/gnuradio-core/src/lib/reed-solomon/README.karn new file mode 100644 index 00000000..f30644ff --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/README.karn @@ -0,0 +1,22 @@ +This package implements a general purpose Reed-Solomon encoding and decoding +facility. See the rs.3 man page for details. + +To install, simply do the following after extracting this tarball into +an empty directory: + +./configure +make +make install + +The command "make test" runs a battery of encode/decode tests using a +variety of RS codes using random data and random errors. Each test +should pass with an "OK"; if any fail, please let me know so I can +track down the problem. + +Phil Karn (karn@ka9q.net) 1 Jan 2002 + +Copyright 2002, Phil Karn, KA9Q +This software may be used under the terms of the GNU General Public License (GPL). + + + diff --git a/gnuradio-core/src/lib/reed-solomon/ccsds.h b/gnuradio-core/src/lib/reed-solomon/ccsds.h new file mode 100644 index 00000000..0f2bde61 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/ccsds.h @@ -0,0 +1 @@ +extern unsigned char Taltab[],Tal1tab[]; diff --git a/gnuradio-core/src/lib/reed-solomon/char.h b/gnuradio-core/src/lib/reed-solomon/char.h new file mode 100644 index 00000000..2fbcb504 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/char.h @@ -0,0 +1,56 @@ +/* Include file to configure the RS codec for character symbols + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +#define DTYPE unsigned char + +/* Reed-Solomon codec control block */ +struct rs { + unsigned int mm; /* Bits per symbol */ + unsigned int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define A0 (NN) + +#define ENCODE_RS encode_rs_char +#define DECODE_RS decode_rs_char +#define INIT_RS init_rs_char +#define FREE_RS free_rs_char + +void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +void FREE_RS(void *p); + + + + + diff --git a/gnuradio-core/src/lib/reed-solomon/decode_rs.c b/gnuradio-core/src/lib/reed-solomon/decode_rs.c new file mode 100644 index 00000000..ca409782 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/decode_rs.c @@ -0,0 +1,262 @@ +/* Reed-Solomon decoder + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +#ifdef DEBUG +#include +#endif + +#include + +#define NULL ((void *)0) +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifdef FIXED +#include "fixed.h" +#elif defined(BIGSYM) +#include "int.h" +#else +#include "char.h" +#endif + +int DECODE_RS( +#ifndef FIXED +void *p, +#endif +DTYPE *data, int *eras_pos, int no_eras){ + +#ifndef FIXED + struct rs *rs = (struct rs *)p; +#endif + int deg_lambda, el, deg_omega; + int i, j, r,k; + DTYPE u,q,tmp,num1,num2,den,discr_r; + DTYPE lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly + * and syndrome poly */ + DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; + DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; + int syn_error, count; + + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + for(i=0;i 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))]; + for (i = 1; i < no_eras; i++) { + u = MODNN(PRIM*(NN-1-eras_pos[i])); + for (j = i+1; j > 0; j--) { + tmp = INDEX_OF[lambda[j - 1]]; + if(tmp != A0) + lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; + } + } + +#if DEBUG >= 1 + /* Test code that verifies the erasure locator polynomial just constructed + Needed only for decoder debugging. */ + + /* find roots of the erasure location polynomial */ + for(i=1;i<=no_eras;i++) + reg[i] = INDEX_OF[lambda[i]]; + + count = 0; + for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) { + q = 1; + for (j = 1; j <= no_eras; j++) + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + if (q != 0) + continue; + /* store root and error location number indices */ + root[count] = i; + loc[count] = k; + count++; + } + if (count != no_eras) { + printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); + count = -1; + goto finish; + } +#if DEBUG >= 2 + printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); +#endif +#endif + } + for(i=0;i 0; j--){ + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + } + if (q != 0) + continue; /* Not a root */ + /* store root (index-form) and error location number */ +#if DEBUG>=2 + printf("count %d root %d loc %d\n",count,i,k); +#endif + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if(++count == deg_lambda) + break; + } + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + count = -1; + goto finish; + } + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**NROOTS). in index form. Also find deg(omega). + */ + deg_omega = 0; + for (i = 0; i < NROOTS;i++){ + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for(;j >= 0; j--){ + if ((s[i - j] != A0) && (lambda[j] != A0)) + tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; + } + if(tmp != 0) + deg_omega = i; + omega[i] = INDEX_OF[tmp]; + } + omega[NROOTS] = A0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >=0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; + } + num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) { + if(lambda[i+1] != A0) + den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])]; + } + if (den == 0) { +#if DEBUG >= 1 + printf("\n ERROR: denominator = 0\n"); +#endif + count = -1; + goto finish; + } + /* Apply error to data */ + if (num1 != 0) { + data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; + } + } + finish: + if(eras_pos != NULL){ + for(i=0;i 0){ + /* Convert from conventional to dual basis */ + for(i=0;i + +#ifdef FIXED +#include "fixed.h" +#elif defined(BIGSYM) +#include "int.h" +#else +#include "char.h" +#endif + +void ENCODE_RS( +#ifndef FIXED +void *p, +#endif +DTYPE *data, DTYPE *bb){ +#ifndef FIXED + struct rs *rs = (struct rs *)p; +#endif + int i, j; + DTYPE feedback; + + memset(bb,0,NROOTS*sizeof(DTYPE)); + + for(i=0;i +#endif + +#include +#include +#include + +#ifdef FIXED +#include "fixed.h" +#define EXERCISE exercise_8 +#elif defined(CCSDS) +#include "fixed.h" +#include "ccsds.h" +#define EXERCISE exercise_ccsds +#elif defined(BIGSYM) +#include "int.h" +#define EXERCISE exercise_int +#else +#include "char.h" +#define EXERCISE exercise_char +#endif + +#ifdef FIXED +#define PRINTPARM printf("(255,223):"); +#elif defined(CCSDS) +#define PRINTPARM printf("CCSDS (255,223):"); +#else +#define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots); +#endif + +/* Exercise the RS codec passed as an argument */ +int EXERCISE( +#if !defined(CCSDS) && !defined(FIXED) +void *p, +#endif +int trials){ +#if !defined(CCSDS) && !defined(FIXED) + struct rs *rs = (struct rs *)p; +#endif + DTYPE block[NN],tblock[NN]; + int i; + int errors; + int errlocs[NN]; + int derrlocs[NROOTS]; + int derrors; + int errval,errloc; + int erasures; + int decoder_errors = 0; + + while(trials-- != 0){ + /* Test up to the error correction capacity of the code */ + for(errors=0;errors <= NROOTS/2;errors++){ + + /* Load block with random data and encode */ + for(i=0;i= 255) { + x -= 255; + x = (x >> 8) + (x & 255); + } + return x; +} +#define MODNN(x) mod255(x) + +extern unsigned char CCSDS_alpha_to[]; +extern unsigned char CCSDS_index_of[]; +extern unsigned char CCSDS_poly[]; + +#define MM 8 +#define NN 255 +#define ALPHA_TO CCSDS_alpha_to +#define INDEX_OF CCSDS_index_of +#define GENPOLY CCSDS_poly +#define NROOTS 32 +#define FCR 112 +#define PRIM 11 +#define IPRIM 116 +#define A0 (NN) + +#define ENCODE_RS encode_rs_8 +#define DECODE_RS decode_rs_8 + +void ENCODE_RS(DTYPE *data,DTYPE *parity); +int DECODE_RS(DTYPE *data, int *eras_pos, int no_eras); diff --git a/gnuradio-core/src/lib/reed-solomon/gen_ccsds.c b/gnuradio-core/src/lib/reed-solomon/gen_ccsds.c new file mode 100644 index 00000000..1e4e4f53 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/gen_ccsds.c @@ -0,0 +1,34 @@ +/* Generate tables for CCSDS code + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#include +#include "char.h" + +int main(){ + struct rs *rs; + int i; + + rs = init_rs_char(8,0x187,112,11,32); /* CCSDS standard */ + printf("unsigned char CCSDS_alpha_to[] = {"); + for(i=0;i<256;i++){ + if((i % 16) == 0) + printf("\n"); + printf("0x%02x,",rs->alpha_to[i]); + } + printf("\n};\n\nunsigned char CCSDS_index_of[] = {"); + for(i=0;i<256;i++){ + if((i % 16) == 0) + printf("\n"); + printf("%3d,",rs->index_of[i]); + } + printf("\n};\n\nunsigned char CCSDS_poly[] = {"); + for(i=0;i<33;i++){ + if((i % 16) == 0) + printf("\n"); + + printf("%3d,",rs->genpoly[i]); + } + printf("\n};\n"); + exit(0); +} diff --git a/gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c b/gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c new file mode 100644 index 00000000..9dde1891 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c @@ -0,0 +1,50 @@ +/* Conversion lookup tables from conventional alpha to Berlekamp's + * dual-basis representation. Used in the CCSDS version only. + * taltab[] -- convert conventional to dual basis + * tal1tab[] -- convert dual basis to conventional + + * Note: the actual RS encoder/decoder works with the conventional basis. + * So data is converted from dual to conventional basis before either + * encoding or decoding and then converted back. + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#include +unsigned char Taltab[256],Tal1tab[256]; + +static unsigned char tal[] = { 0x8d, 0xef, 0xec, 0x86, 0xfa, 0x99, 0xaf, 0x7b }; + +/* Generate conversion lookup tables between conventional alpha representation + * (@**7, @**6, ...@**0) + * and Berlekamp's dual basis representation + * (l0, l1, ...l7) + */ +int main(){ + int i,j,k; + + for(i=0;i<256;i++){/* For each value of input */ + Taltab[i] = 0; + for(j=0;j<8;j++) /* for each column of matrix */ + for(k=0;k<8;k++){ /* for each row of matrix */ + if(i & (1< + +#ifdef CCSDS +#include "ccsds.h" +#elif defined(BIGSYM) +#include "int.h" +#else +#include "char.h" +#endif + +#define NULL ((void *)0) + +void FREE_RS(void *p){ + struct rs *rs = (struct rs *)p; + + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); + free(rs); +} + +/* Initialize a Reed-Solomon codec + * symsize = symbol size, bits (1-8) + * gfpoly = Field generator polynomial coefficients + * fcr = first root of RS code generator polynomial, index form + * prim = primitive element to generate polynomial roots + * nroots = RS code generator polynomial degree (number of roots) + */ +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned prim, + unsigned int nroots){ + struct rs *rs; + int i, j, sr,root,iprim; + + if(symsize > 8*sizeof(DTYPE)) + return NULL; /* Need version with ints rather than chars */ + + if(fcr >= (1<= (1<= (1<mm = symsize; + rs->nn = (1<alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); + if(rs->alpha_to == NULL){ + free(rs); + return NULL; + } + rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); + if(rs->index_of == NULL){ + free(rs->alpha_to); + free(rs); + return NULL; + } + + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for(i=0;inn;i++){ + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<nn; + } + if(sr != 1){ + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + + /* Form RS code generator polynomial from its roots */ + rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1)); + if(rs->genpoly == NULL){ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + + /* Find prim-th root of 1, used in decoding */ + for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { + rs->genpoly[i+1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--){ + if (rs->genpoly[j] != 0) + rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j-1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + +#if 0 + printf ("genpoly:\n"); + for (i = nroots; i >= 0; i--){ + printf (" %3d*X^%d\n", rs->alpha_to[rs->genpoly[i]], i); + } +#endif + + return rs; +} diff --git a/gnuradio-core/src/lib/reed-solomon/int.h b/gnuradio-core/src/lib/reed-solomon/int.h new file mode 100644 index 00000000..2b0405ae --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/int.h @@ -0,0 +1,54 @@ +/* Include file to configure the RS codec for integer symbols + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define DTYPE int + +/* Reed-Solomon codec control block */ +struct rs { + unsigned int mm; /* Bits per symbol */ + unsigned int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define A0 (NN) + +#define ENCODE_RS encode_rs_int +#define DECODE_RS decode_rs_int +#define INIT_RS init_rs_int +#define FREE_RS free_rs_int + +void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +void FREE_RS(void *p); + + + + diff --git a/gnuradio-core/src/lib/reed-solomon/rs.3 b/gnuradio-core/src/lib/reed-solomon/rs.3 new file mode 100644 index 00000000..c3953ce5 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rs.3 @@ -0,0 +1,170 @@ +.TH REED-SOLOMON 3 +.SH NAME +init_rs_int, encode_rs_int, decode_rs_int, free_rs_int, +init_rs_char, encode_rs_char, decode_rs_char, free_rs_char, +encode_rs_8, decode_rs_8, encode_rs_ccsds, decode_rs_ccsds +.SH SYNOPSIS +.nf +.ft B +#include "rs.h" + +void *init_rs_int(unsigned int symsize,unsigned int gfpoly,unsigned fcr, +unsigned prim,unsigned int nroots); +void encode_rs_int(void *rs,int *data,int *parity); +int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras); +void free_rs_int(void *rs); + +void *init_rs_char(unsigned int symsize,unsigned int gfpoly,unsigned fcr, +unsigned prim,unsigned int nroots); +void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity); +int decode_rs_char(void *rs,unsigned char *data,int *eras_pos,int no_eras); +void free_rs_char(void *rs); + +void encode_rs_8(unsigned char *data,unsigned char *parity); +int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras); + +void encode_rs_ccsds(unsigned char *data,unsigned char *parity); +int decode_rs_ccsds(unsigned char *data,int *eras_pos,int no_eras); + +unsigned char Taltab[256]; +unsigned char Tal1tab[256]; + +.fi + +.SH DESCRIPTION +These functions implement Reed-Solomon error control encoding and +decoding. For optimal performance in a variety of applications, three +sets of functions are supplied. To access these functions, add "-lrs" +to your linker command line. + +The functions with names ending in "_int" handle data in integer arrays, +permitting arbitrarily large codewords limited only by machine +resources. + +The functions with names ending in "_char" take unsigned char arrays and can +handle codes with symbols of 8 bits or less (i.e., with codewords of +255 symbols or less). + +\fBencode_rs_8\fR and \fBdecode_rs_8\fR implement a specific +(255,223) code with 8-bit symbols specified by the CCSDS: +a field generator of 1 + X + X^2 + X^7 + X^8 and a code +generator with first consecutive root = 112 and a primitive element of +11. These functions use the conventional +polynomial form, \fBnot\fR the dual-basis specified in +the CCSDS standard, to represent symbols. + +For full CCSDS compatibility, \fBencode_rs_ccsds\fR and +\fBdecode_rs_ccsds\fR are provided. These functions use two lookup +tables, \fBTaltab\fR to convert from conventional to dual-basis, and +\fBTal1tab\fR to perform the inverse mapping from dual-basis to +conventional form, before and after calls to \fBencode_rs_8\fR +and \fBdecode_rs_8\fR. + +The _8 and _ccsds functions do not require initialization. +To use the general purpose RS encoder or decoder (i.e., +the _char or _int versions), the user must first +call \fBinit_rs_int\fR or \fBinit_rs_char\fR as appropriate. The +arguments are as follows: + +\fBsymsize\fR gives the symbol size in bits, up to 8 for \fBinit_rs_char\fR +or 32 for \fBinit_rs_int\fR on a machine with 32-bit ints (though such a +huge code would exhaust memory limits on a 32-bit machine). The resulting +Reed-Solomon code word will have 2^\fBsymsize\fR - 1 symbols, +each containing \fBsymsize\fR bits. + +\fBgfpoly\fR gives the extended Galois field generator polynomial coefficients, +with the 0th coefficient in the low order bit. The polynomial +\fImust\fR be primitive; if not, the call will fail and NULL will be +returned. + +\fBfcr\fR gives, in index form, the first consecutive root of the +Reed Solomon code generator polynomial. + +\fBprim\fR gives, in index form, the primitive element in the Galois field +used to generate the Reed Solomon code generator polynomial. + +\fBnroots\fR gives the number of roots in the Reed Solomon code +generator polynomial. This equals the number of parity symbols +per code block. + +The resulting Reed-Solomon code has parameters (N,K), where +N = 2^\fBsymsize\fR-1 and K = N-\fBnroots\fR. + +The \fBencode_rs_char\fR and \fBencode_rs_int\fR functions accept +the pointer returned by \fBinit_rs_char\fR or +\fBinit_rs_int\fR, respectively, to +encode a block of data using the specified code. +The input data array is expected to +contain K symbols (of \fBsymsize\fR bits each, right justified +in each char or int) and \fBnroots\fR parity symbols will be placed +into the \fBparity\fR array, right justified. + +The \fBdecode_rs_char\fR and \fBdecode_rs_int\fR functions correct +the errors in a Reed-Solomon codeword up to the capability of the code. +An optional list of "erased" symbol indices may be given in the \fBeras_pos\fR +array to assist the decoder; this parameter may be NULL if no erasures +are given. The number of erased symbols must be given in the \fBno_eras\fR +parameter. + +To maximize performance, the encode and decode functions perform no +"sanity checking" of their inputs. Decoder failure may result if +\fBeras_pos\fR contains duplicate entries, and both encoder and +decoder will fail if an input symbol exceeds its allowable range. +(Symbol range overflow cannot occur with the _8 or _ccsds functions, +or with the _char functions when 8-bit symbols are specified.) + +The decoder corrects the symbols "in place", returning the number +of symbols in error. If the codeword is uncorrectable, -1 is returned +and the data block is unchanged. If \fBeras_pos\fR is non-null, it is +used to return a list of corrected symbol positions, in no particular +order. This means that the +array passed through this parameter \fImust\fR have at least \fBnroots\fR +elements to prevent a possible buffer overflow. + +The \fBfree_rs_int\fR and \fBfree_rs_char\fR functions free the internal +space allocated by the \fBinit_rs_int\fR and \fBinit_rs_char\fR functions, +respecitively. + +The functions \fBencode_rs_8\fR and \fBdecode_rs_8\fR do not have +corresponding \fBinit\fR and \fBfree\fR, nor do they take the +\fBrs\fR argument accepted by the other functions as their parameters +are statically compiled. These functions implement a code +equivalent to calling + +\fBinit_rs_char\fR(8,0x187,112,11,32); + +and using the resulting pointer with \fBencode_rs_char\fR and +\fBdecode_rs_char\fR. + +.SH RETURN VALUES +\fBinit_rs_int\fR and \fBinit_rs_char\fR return a pointer to an internal +control structure that must be passed to the corresponding encode, decode +and free functions. These functions return NULL on error. + +The decode functions return a count of corrected +symbols, or -1 if the block was uncorrectible. + +.SH AUTHOR +Phil Karn, KA9Q (karn@ka9q.net), based heavily on earlier work by Robert +Morelos-Zaragoza (rober@spectra.eng.hawaii.edu) and Hari Thirumoorthy +(harit@spectra.eng.hawaii.edu). + +.SH COPYRIGHT +Copyright 2002, Phil Karn, KA9Q. May be used under the terms of the +GNU General Public License (GPL). + +.SH SEE ALSO +CCSDS 101.0-B-5: Telemetry Channel Coding. +http://www.ccsds.org/documents/pdf/CCSDS-101.0-B-5.pdf + +.SH NOTE +CCSDS chose the "dual basis" symbol representation because it +simplified the implementation of a Reed-Solomon encoder in dedicated +hardware. However, this approach holds no advantages for a software +implementation on a general purpose computer, so use of the dual basis +is recommended only if compatibility with the CCSDS standard is needed, +e.g., to decode data from an existing spacecraft using the CCSDS +standard. If you just want a fast (255,223) RS codec without needing +to interoperate with a CCSDS standard code, use \fBencode_rs_8\fR +and \fBdecode_rs_8\fR. + diff --git a/gnuradio-core/src/lib/reed-solomon/rs.h b/gnuradio-core/src/lib/reed-solomon/rs.h new file mode 100644 index 00000000..9e731d9d --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rs.h @@ -0,0 +1,30 @@ +/* User include file for the Reed-Solomon codec + * Copyright 2002, Phil Karn KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +/* General purpose RS codec, 8-bit symbols */ +void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity); +int decode_rs_char(void *rs,unsigned char *data,int *eras_pos, + int no_eras); +void *init_rs_char(unsigned int symsize,unsigned int gfpoly, + unsigned int fcr,unsigned int prim,unsigned int nroots); +void free_rs_char(void *rs); + +/* General purpose RS codec, integer symbols */ +void encode_rs_int(void *rs,int *data,int *parity); +int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras); +void *init_rs_int(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +void free_rs_int(void *rs); + +/* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis) + * symbol representation + */ +void encode_rs_8(unsigned char *data,unsigned char *parity); +int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras); + +/* Tables to map from conventional->dual (Taltab) and + * dual->conventional (Tal1tab) bases + */ +extern unsigned char Taltab[],Tal1tab[]; diff --git a/gnuradio-core/src/lib/reed-solomon/rstest.c b/gnuradio-core/src/lib/reed-solomon/rstest.c new file mode 100644 index 00000000..d8fc5448 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rstest.c @@ -0,0 +1,117 @@ +/* Test the Reed-Solomon codecs + * for various block sizes and with random data and random error patterns + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include "rs.h" + +int exercise_char(void *,int); + +#ifdef ALL_VERSIONS +int exercise_int(void *,int); +int exercise_8(int); +int exercise_ccsds(int); +#endif + +struct { + int symsize; + int genpoly; + int fcs; + int prim; + int nroots; + int ntrials; +} Tab[] = { + {2, 0x7, 1, 1, 1, 10 }, + {3, 0xb, 1, 1, 2, 10 }, + {4, 0x13, 1, 1, 4, 10 }, + {5, 0x25, 1, 1, 6, 10 }, + {6, 0x43, 1, 1, 8, 10 }, + {7, 0x89, 1, 1, 10, 10 }, + {8, 0x11d, 1, 1, 32, 10 }, + {8, 0x187, 112,11, 32, 10 }, /* Duplicates CCSDS codec */ +#ifdef ALL_VESIONS + {9, 0x211, 1, 1, 32, 10 }, + {10,0x409, 1, 1, 32, 10 }, + {11,0x805, 1, 1, 32, 10 }, + {12,0x1053, 1, 1, 32, 5 }, + {13,0x201b, 1, 1, 32, 2 }, + {14,0x4443, 1, 1, 32, 1 }, + {15,0x8003, 1, 1, 32, 1 }, + {16,0x1100b, 1, 1, 32, 1 }, +#endif + {0, 0, 0, 0, 0}, +}; + +int main(){ + void *handle; + int errs,terrs; + int i; + + terrs = 0; + srandom(time(NULL)); + +#ifdef ALL_VERSIONS + printf("Testing fixed (255,223) RS codec..."); + fflush(stdout); + errs = exercise_8(10); + terrs += errs; + if(errs == 0){ + printf("OK\n"); + } + printf("Testing CCSDS standard (255,223) RS codec..."); + fflush(stdout); + errs = exercise_ccsds(10); + terrs += errs; + if(errs == 0){ + printf("OK\n"); + } +#endif + + for(i=0;Tab[i].symsize != 0;i++){ + int nn,kk; + + nn = (1< +#include +#include + +static long s_next_id = 0; +static long s_ncurrently_allocated = 0; + +long +gr_block_ncurrently_allocated () +{ + return s_ncurrently_allocated; +} + +gr_block::gr_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : d_name (name), + d_input_signature (input_signature), + d_output_signature (output_signature), + d_output_multiple (1), + d_relative_rate (1.0), + d_unique_id (s_next_id++), + d_history(1), + d_fixed_rate(false) +{ + s_ncurrently_allocated++; +} + +gr_block::~gr_block () +{ + s_ncurrently_allocated--; +} + +// stub implementation: 1:1 + +void +gr_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items; +} + +// default implementation + +bool +gr_block::check_topology (int ninputs, int noutputs) +{ + return true; +} + +bool +gr_block::start() +{ + return true; +} + +bool +gr_block::stop() +{ + return true; +} + +void +gr_block::set_output_multiple (int multiple) +{ + if (multiple < 1) + throw std::invalid_argument ("gr_block::set_output_multiple"); + + d_output_multiple = multiple; +} + +void +gr_block::set_relative_rate (double relative_rate) +{ + if (relative_rate < 0.0) + throw std::invalid_argument ("gr_block::set_relative_rate"); + + d_relative_rate = relative_rate; +} + + +void +gr_block::consume (int which_input, int how_many_items) +{ + d_detail->consume (which_input, how_many_items); +} + +void +gr_block::consume_each (int how_many_items) +{ + d_detail->consume_each (how_many_items); +} + +int +gr_block::fixed_rate_ninput_to_noutput(int ninput) +{ + throw std::runtime_error("Unimplemented"); +} + +int +gr_block::fixed_rate_noutput_to_ninput(int noutput) +{ + throw std::runtime_error("Unimplemented"); +} diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h new file mode 100644 index 00000000..df72e1a3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -0,0 +1,247 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BLOCK_H +#define INCLUDED_GR_BLOCK_H + +#include +#include + +/*! + * \brief The abstract base class for all signal processing blocks. + * \ingroup block + * + * Blocks have a set of input streams and output streams. The + * input_signature and output_signature define the number of input + * streams and output streams respectively, and the type of the data + * items in each stream. + * + * Although blocks may consume data on each input stream at a + * different rate, all outputs streams must produce data at the same + * rate. That rate may be different from any of the input rates. + * + * User derived blocks override two methods, forecast and general_work, + * to implement their signal processing behavior. forecast is called + * by the system scheduler to determine how many items are required on + * each input stream in order to produce a given number of output + * items. + * + * general_work is called to perform the signal processing in the block. + * It reads the input items and writes the output items. + */ + +class gr_block { + + public: + + virtual ~gr_block (); + + std::string name () const { return d_name; } + gr_io_signature_sptr input_signature () const { return d_input_signature; } + gr_io_signature_sptr output_signature () const { return d_output_signature; } + long unique_id () const { return d_unique_id; } + + /*! + * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) + * History is the number of x_i's that are examined to produce one y_i. + * This comes in handy for FIR filters, where we use history to + * ensure that our input contains the appropriate "history" for the + * filter. History should be equal to the number of filter taps. + */ + unsigned history () const { return d_history; } + void set_history (unsigned history) { d_history = history; } + + /*! + * \brief return true if this block has a fixed input to output rate + * + * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called. + */ + bool fixed_rate() const { return d_fixed_rate; } + + // ---------------------------------------------------------------- + // override these to define your behavior + // ---------------------------------------------------------------- + + /*! + * \brief Estimate input requirements given output request + * + * \param noutput_items number of output items to produce + * \param ninput_items_required number of input items required on each input stream + * + * Given a request to product \p noutput_items, estimate the number of + * data items required on each input stream. The estimate doesn't have + * to be exact, but should be close. + */ + virtual void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + /*! + * \brief compute output items from input items + * + * \param noutput_items number of output items to write on each output stream + * \param ninput_items number of input items available on each input stream + * \param input_items vector of pointers to the input items, one entry per input stream + * \param output_items vector of pointers to the output items, one entry per output stream + * + * \returns number of items actually written to each output stream, or -1 on EOF. + * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items + * + * general_work must call consume or consume_each to indicate how many items + * were consumed on each input stream. + */ + virtual int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) = 0; + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + virtual bool check_topology (int ninputs, int noutputs); + + /*! + * \brief Called to enable drivers, etc for i/o devices. + * + * This allows a block to enable an associated driver to begin + * transfering data just before we start to execute the scheduler. + * The end result is that this reduces latency in the pipeline when + * dealing with audio devices, usrps, etc. + */ + virtual bool start(); + + /*! + * \brief Called to disable drivers, etc for i/o devices. + */ + virtual bool stop(); + + // ---------------------------------------------------------------- + + /*! + * \brief Constrain the noutput_items argument passed to forecast and general_work + * + * set_output_multiple causes the scheduler to ensure that the noutput_items + * argument passed to forecast and general_work will be an integer multiple + * of \param multiple The default value of output multiple is 1. + */ + void set_output_multiple (int multiple); + int output_multiple () const { return d_output_multiple; } + + /*! + * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. + */ + void consume (int which_input, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were consumed on each input stream. + */ + void consume_each (int how_many_items); + + /*! + * \brief Set the approximate output rate / input rate + * + * Provide a hint to the buffer allocator and scheduler. + * The default relative_rate is 1.0 + * + * decimators have relative_rates < 1.0 + * interpolators have relative_rates > 1.0 + */ + void set_relative_rate (double relative_rate); + + /*! + * \brief return the approximate output rate / input rate + */ + double relative_rate () const { return d_relative_rate; } + + /* + * The following two methods provide special case info to the + * scheduler in the event that a block has a fixed input to output + * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator + * override these. If you're fixed rate, subclass one of those. + */ + /*! + * \brief Given ninput samples, return number of output samples that will be produced. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + virtual int fixed_rate_ninput_to_noutput(int ninput); + + /*! + * \brief Given noutput samples, return number of input samples required to produce noutput. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + virtual int fixed_rate_noutput_to_ninput(int noutput); + + // ---------------------------------------------------------------------------- + + private: + + std::string d_name; + gr_io_signature_sptr d_input_signature; + gr_io_signature_sptr d_output_signature; + int d_output_multiple; + double d_relative_rate; // approx output_rate / input_rate + gr_block_detail_sptr d_detail; // implementation details + long d_unique_id; // convenient for debugging + unsigned d_history; + bool d_fixed_rate; + + + protected: + + gr_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + //! may only be called during constructor + void set_input_signature (gr_io_signature_sptr iosig){ + d_input_signature = iosig; + } + + //! may only be called during constructor + void set_output_signature (gr_io_signature_sptr iosig){ + d_output_signature = iosig; + } + + void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } + + // These are really only for internal use, but leaving them public avoids + // having to work up an ever-varying list of friends + + public: + gr_block_detail_sptr detail () const { return d_detail; } + void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } +}; + +long gr_block_ncurrently_allocated (); + +#endif /* INCLUDED_GR_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i new file mode 100644 index 00000000..f1f0332e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.i @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_block; +typedef boost::shared_ptr gr_block_sptr; +%template(gr_block_sptr) boost::shared_ptr; + +// support vectors of these... +namespace std { + %template(x_vector_gr_block_sptr) vector; +}; + +class gr_block { + protected: + gr_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + public: + + virtual ~gr_block (); + + std::string name () const; + gr_io_signature_sptr input_signature () const; + gr_io_signature_sptr output_signature () const; + long unique_id () const; + unsigned history () const; + + int output_multiple () const; + double relative_rate () const; + + bool check_topology (int ninputs, int noutputs); + bool start(); + bool stop(); + + // internal use + gr_block_detail_sptr detail () const { return d_detail; } + void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } +}; + +%rename(block_ncurrently_allocated) gr_block_ncurrently_allocated; +long gr_block_ncurrently_allocated (); + +%pythoncode %{ +gr_block_sptr.__repr__ = lambda self: "" % (self.name(), self.unique_id ()) +gr_block_sptr.block = lambda self: self +%} diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc new file mode 100644 index 00000000..0ad5da49 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -0,0 +1,108 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static long s_ncurrently_allocated = 0; + +long +gr_block_detail_ncurrently_allocated () +{ + return s_ncurrently_allocated; +} + +gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs) + : d_ninputs (ninputs), d_noutputs (noutputs), + d_input (ninputs), d_output (noutputs), + d_done (false) +{ + s_ncurrently_allocated++; +} + +gr_block_detail::~gr_block_detail () +{ + // should take care of itself + s_ncurrently_allocated--; +} + +void +gr_block_detail::set_input (unsigned int which, gr_buffer_reader_sptr reader) +{ + if (which >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::set_input"); + + d_input[which] = reader; +} + +void +gr_block_detail::set_output (unsigned int which, gr_buffer_sptr buffer) +{ + if (which >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::set_output"); + + d_output[which] = buffer; +} + +gr_block_detail_sptr +gr_make_block_detail (unsigned int ninputs, unsigned int noutputs) +{ + return gr_block_detail_sptr (new gr_block_detail (ninputs, noutputs)); +} + +void +gr_block_detail::set_done (bool done) +{ + d_done = done; + for (unsigned int i = 0; i < d_noutputs; i++) + d_output[i]->set_done (done); + + for (unsigned int i = 0; i < d_ninputs; i++) + d_input[i]->set_done (done); +} + +void +gr_block_detail::consume (int which_input, int how_many_items) +{ + if (how_many_items > 0) + input (which_input)->update_read_pointer (how_many_items); +} + +void +gr_block_detail::consume_each (int how_many_items) +{ + if (how_many_items > 0) + for (int i = 0; i < ninputs (); i++) + d_input[i]->update_read_pointer (how_many_items); +} + +void +gr_block_detail::produce_each (int how_many_items) +{ + if (how_many_items > 0) + for (int i = 0; i < noutputs (); i++) + d_output[i]->update_write_pointer (how_many_items); +} diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h new file mode 100644 index 00000000..90c912c2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more detail. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BLOCK_DETAIL_H +#define INCLUDED_GR_BLOCK_DETAIL_H + +#include +#include + +/*! + * \brief Implementation details to support the signal processing abstraction + * \ingroup internal + * + * This class contains implementation detail that should be "out of sight" + * of almost all users of GNU Radio. This decoupling also means that + * we can make changes to the guts without having to recompile everything. + */ + +class gr_block_detail { + public: + ~gr_block_detail (); + + int ninputs () const { return d_ninputs; } + int noutputs () const { return d_noutputs; } + bool sink_p () const { return d_noutputs == 0; } + bool source_p () const { return d_ninputs == 0; } + + void set_done (bool done); + bool done () const { return d_done; } + + void set_input (unsigned int which, gr_buffer_reader_sptr reader); + gr_buffer_reader_sptr input (unsigned int which) + { + if (which >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::input"); + return d_input[which]; + } + + void set_output (unsigned int which, gr_buffer_sptr buffer); + gr_buffer_sptr output (unsigned int which) + { + if (which >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::output"); + return d_output[which]; + } + + /*! + * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. + */ + void consume (int which_input, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were consumed on each input stream. + */ + void consume_each (int how_many_items); + + void produce_each (int how_many_items); + + // ---------------------------------------------------------------------------- + + private: + unsigned int d_ninputs; + unsigned int d_noutputs; + std::vector d_input; + std::vector d_output; + bool d_done; + + gr_block_detail (unsigned int ninputs, unsigned int noutputs); + + friend gr_block_detail_sptr + gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); +}; + +gr_block_detail_sptr +gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); + +long +gr_block_detail_ncurrently_allocated (); + +#endif /* INCLUDED_GR_BLOCK_DETAIL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.i b/gnuradio-core/src/lib/runtime/gr_block_detail.i new file mode 100644 index 00000000..9d3843eb --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.i @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_block_detail; +typedef boost::shared_ptr gr_block_detail_sptr; +%template(gr_block_detail_sptr) boost::shared_ptr; +%rename(block_detail) gr_make_block_detail; +%ignore gr_block_detail; + +gr_block_detail_sptr gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); + +class gr_block_detail { + public: + + ~gr_block_detail (); + + int ninputs () const { return d_ninputs; } + int noutputs () const { return d_noutputs; } + bool sink_p () const { return d_noutputs == 0; } + bool source_p () const { return d_ninputs == 0; } + + void set_input (unsigned int which, gr_buffer_reader_sptr reader); + gr_buffer_reader_sptr input (unsigned int which) + { + if (which >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::input"); + return d_input[which]; + } + + void set_output (unsigned int which, gr_buffer_sptr buffer); + gr_buffer_sptr output (unsigned int which) + { + if (which >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::output"); + return d_output[which]; + } + + // ---------------------------------------------------------------------------- + + private: + gr_block_detail (unsigned int ninputs, unsigned int noutputs); + +}; + + +%rename(block_detail_ncurrently_allocated) gr_block_detail_ncurrently_allocated; +long gr_block_detail_ncurrently_allocated (); diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.cc b/gnuradio-core/src/lib/runtime/gr_buffer.cc new file mode 100644 index 00000000..d3d12309 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.cc @@ -0,0 +1,248 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +static long s_buffer_count = 0; // counts for debugging storage mgmt +static long s_buffer_reader_count = 0; + +// ---------------------------------------------------------------------------- +// Notes on storage management +// +// Pretty much all the fundamental classes are now using the +// shared_ptr stuff for automatic reference counting. To ensure that +// no mistakes are made, we make the constructors for classes private, +// and then provide a free factory function that returns a smart +// pointer to the desired class. +// +// gr_buffer and gr_buffer_reader are no exceptions. However, they +// both want pointers to each other, and unless we do something, we'll +// never delete any of them because of the circular structure. +// They'll always have a reference count of at least one. We could +// use boost::weak_ptr's from gr_buffer to gr_buffer_reader but that +// introduces it's own problems. (gr_buffer_reader's destructor needs +// to call gr_buffer::drop_reader, but has no easy way to get a +// shared_ptr to itself.) +// +// Instead, we solve this problem by having gr_buffer hold a raw +// pointer to gr_buffer_reader in its d_reader vector. +// gr_buffer_reader's destructor calls gr_buffer::drop_reader, so +// we're never left with an dangling pointer. gr_buffer_reader still +// has a shared_ptr to the buffer ensuring that the buffer doesn't go +// away under it. However, when the reference count of a +// gr_buffer_reader goes to zero, we can successfully reclaim it. +// ---------------------------------------------------------------------------- + + +/* + * Compute the minimum number of buffer items that work (i.e., + * address space wrap-around works). To work is to satisfy this + * contraint for integer buffer_size and k: + * + * type_size * nitems == k * page_size + */ +static long +minimum_buffer_items (long type_size, long page_size) +{ + return page_size / gr_gcd (type_size, page_size); +} + + +gr_buffer::gr_buffer (int nitems, size_t sizeof_item) + : d_base (0), d_bufsize (0), d_vmcircbuf (0), + d_sizeof_item (sizeof_item), d_write_index (0), + d_done (false) +{ + if (!allocate_buffer (nitems, sizeof_item)) + throw std::bad_alloc (); + + s_buffer_count++; +} + +gr_buffer_sptr +gr_make_buffer (int nitems, size_t sizeof_item) +{ + return gr_buffer_sptr (new gr_buffer (nitems, sizeof_item)); +} + +gr_buffer::~gr_buffer () +{ + delete d_vmcircbuf; + assert (d_readers.size() == 0); + s_buffer_count--; +} + +/*! + * sets d_vmcircbuf, d_base, d_bufsize. + * returns true iff successful. + */ +bool +gr_buffer::allocate_buffer (int nitems, size_t sizeof_item) +{ + int orig_nitems = nitems; + + // Any buffersize we come up with must be a multiple of min_nitems. + + int granularity = gr_vmcircbuf_sysconfig::granularity (); + int min_nitems = minimum_buffer_items (sizeof_item, granularity); + + // Round-up nitems to a multiple of min_nitems. + + if (nitems % min_nitems != 0) + nitems = ((nitems / min_nitems) + 1) * min_nitems; + + // If we rounded-up a whole bunch, give the user a heads up. + // This only happens if sizeof_item is not a power of two. + + if (nitems > 2 * orig_nitems && nitems * (int) sizeof_item > granularity){ + std::cerr << "gr_buffer::allocate_buffer: warning: tried to allocate\n" + << " " << orig_nitems << " items of size " + << sizeof_item << ". Due to alignment requirements\n" + << " " << nitems << " were allocated. If this isn't OK, consider padding\n" + << " your structure to a power-of-two bytes.\n" + << " On this platform, our allocation granularity is " << granularity << " bytes.\n"; + } + + d_bufsize = nitems; + d_vmcircbuf = gr_vmcircbuf_sysconfig::make (d_bufsize * d_sizeof_item); + if (d_vmcircbuf == 0){ + std::cerr << "gr_buffer::allocate_buffer: failed to allocate buffer of size " + << d_bufsize * d_sizeof_item / 1024 << " KB\n"; + return false; + } + + d_base = (char *) d_vmcircbuf->pointer_to_first_copy (); + return true; +} + + +int +gr_buffer::space_available () const +{ + if (d_readers.empty ()) + return d_bufsize - 1; // See comment below + + else { + + // Find out the maximum amount of data available to our readers + + int most_data = d_readers[0]->items_available (); + for (unsigned int i = 1; i < d_readers.size (); i++) + most_data = std::max (most_data, d_readers[i]->items_available ()); + + // The -1 ensures that the case d_write_index == d_read_index is + // unambiguous. It indicates that there is no data for the reader + + return d_bufsize - most_data - 1; + } +} + +void * +gr_buffer::write_pointer () +{ + return &d_base[d_write_index * d_sizeof_item]; +} + +void +gr_buffer::update_write_pointer (int nitems) +{ + d_write_index = index_add (d_write_index, nitems); +} + +gr_buffer_reader_sptr +gr_buffer_add_reader (gr_buffer_sptr buf, int history) +{ + gr_buffer_reader_sptr r (new gr_buffer_reader (buf, + buf->index_sub(buf->d_write_index, + history-1))); + buf->d_readers.push_back (r.get ()); + + return r; +} + +void +gr_buffer::drop_reader (gr_buffer_reader *reader) +{ + // isn't C++ beautiful... GAG! + + std::vector::iterator result = + std::find (d_readers.begin (), d_readers.end (), reader); + + if (result == d_readers.end ()) + throw std::invalid_argument ("gr_buffer::drop_reader"); // we didn't find it... + + d_readers.erase (result); +} + +long +gr_buffer_ncurrently_allocated () +{ + return s_buffer_count; +} + +// ---------------------------------------------------------------------------- + +gr_buffer_reader::gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index) + : d_buffer (buffer), d_read_index (read_index) +{ + s_buffer_reader_count++; +} + +gr_buffer_reader::~gr_buffer_reader () +{ + d_buffer->drop_reader(this); + s_buffer_reader_count--; +} + +int +gr_buffer_reader::items_available () const +{ + return d_buffer->index_sub (d_buffer->d_write_index, d_read_index); +} + +const void * +gr_buffer_reader::read_pointer () +{ + return &d_buffer->d_base[d_read_index * d_buffer->d_sizeof_item]; +} + +void +gr_buffer_reader::update_read_pointer (int nitems) +{ + d_read_index = d_buffer->index_add (d_read_index, nitems); +} + +long +gr_buffer_reader_ncurrently_allocated () +{ + return s_buffer_reader_count; +} diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.h b/gnuradio-core/src/lib/runtime/gr_buffer.h new file mode 100644 index 00000000..6f85f275 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.h @@ -0,0 +1,196 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BUFFER_H +#define INCLUDED_GR_BUFFER_H + +#include + +class gr_vmcircbuf; + +/*! + * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item. + * + * The total size of the buffer will be rounded up to a system + * dependent boundary. This is typically the system page size, but + * under MS windows is 64KB. + */ +gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item); + + +/*! + * \brief Single writer, multiple reader fifo. + * \ingroup internal + */ +class gr_buffer { + public: + virtual ~gr_buffer (); + + /*! + * \brief return number of items worth of space available for writing + */ + int space_available () const; + + /*! + * \brief return pointer to write buffer. + * + * The return value points at space that can hold at least + * space_available() items. + */ + void *write_pointer (); + + /*! + * \brief tell buffer that we wrote \p nitems into it + */ + void update_write_pointer (int nitems); + + + void set_done (bool done) { d_done = done; } + bool done () const { return d_done; } + + // ------------------------------------------------------------------------- + + private: + + friend class gr_buffer_reader; + friend gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item); + friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + + protected: + char *d_base; // base address of buffer + unsigned int d_bufsize; // in items + private: + gr_vmcircbuf *d_vmcircbuf; + size_t d_sizeof_item; // in bytes + unsigned int d_write_index; // in items [0,d_bufsize) + std::vector d_readers; + bool d_done; + + unsigned + index_add (unsigned a, unsigned b) + { + unsigned s = a + b; + + if (s >= d_bufsize) + s -= d_bufsize; + + assert (s < d_bufsize); + return s; + } + + unsigned + index_sub (unsigned a, unsigned b) + { + int s = a - b; + + if (s < 0) + s += d_bufsize; + + assert ((unsigned) s < d_bufsize); + return s; + } + + virtual bool allocate_buffer (int nitems, size_t sizeof_item); + + /*! + * \brief constructor is private. Use gr_make_buffer to create instances. + * + * Allocate a buffer that holds at least \p nitems of size \p sizeof_item. + * + * The total size of the buffer will be rounded up to a system + * dependent boundary. This is typically the system page size, but + * under MS windows is 64KB. + */ + gr_buffer (int nitems, size_t sizeof_item); + + /*! + * \brief disassociate \p reader from this buffer + */ + void drop_reader (gr_buffer_reader *reader); + +}; + +//! create a new gr_buffer_reader and attach it to buffer \p buf +gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + +//! returns # of gr_buffers currently allocated +long gr_buffer_ncurrently_allocated (); + + +// --------------------------------------------------------------------------- + +/*! + * \brief How we keep track of the readers of a gr_buffer. + * \ingroup internal + */ + +class gr_buffer_reader { + + public: + ~gr_buffer_reader (); + + /*! + * \brief Return number of items available for reading. + */ + int items_available () const; + + /*! + * \brief Return maximum number of items that could ever be available for reading. + * This is used as a sanity check in the scheduler to avoid looping forever. + */ + int max_possible_items_available () const { return d_buffer->d_bufsize - 1; } + + /*! + * \brief return pointer to read buffer. + * + * The return value points to items_available() number of items + */ + const void *read_pointer (); + + /* + * \brief tell buffer we read \p items from it + */ + void update_read_pointer (int nitems); + + void set_done (bool done) { d_buffer->set_done (done); } + bool done () const { return d_buffer->done (); } + + // ------------------------------------------------------------------------- + + private: + + friend class gr_buffer; + friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + + + gr_buffer_sptr d_buffer; + unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) + + //! constructor is private. Use gr_buffer::add_reader to create instances + gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index); +}; + +//! returns # of gr_buffer_readers currently allocated +long gr_buffer_reader_ncurrently_allocated (); + + +#endif /* INCLUDED_GR_BUFFER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.i b/gnuradio-core/src/lib/runtime/gr_buffer.i new file mode 100644 index 00000000..80f92ece --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.i @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_buffer; +typedef boost::shared_ptr gr_buffer_sptr; +%template(gr_buffer_sptr) boost::shared_ptr; +%rename(buffer) gr_make_buffer; +%ignore gr_buffer; + +gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item); + +class gr_buffer { + public: + ~gr_buffer (); + + private: + gr_buffer (int nitems, size_t sizeof_item); +}; + + +class gr_buffer_reader; +typedef boost::shared_ptr gr_buffer_reader_sptr; +%template(gr_buffer_reader_sptr) boost::shared_ptr; +%ignore gr_buffer_reader; + +%rename(buffer_add_reader) gr_buffer_add_reader; +gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + +class gr_buffer_reader { + public: + ~gr_buffer_reader (); + + private: + friend class gr_buffer; + gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index); +}; + + +%rename(buffer_ncurrently_allocated) gr_buffer_ncurrently_allocated; +long gr_buffer_ncurrently_allocated (); + +%rename(buffer_reader_ncurrently_allocated) gr_buffer_reader_ncurrently_allocated; +long gr_buffer_reader_ncurrently_allocated (); + diff --git a/gnuradio-core/src/lib/runtime/gr_complex.h b/gnuradio-core/src/lib/runtime/gr_complex.h new file mode 100644 index 00000000..242b2f54 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_complex.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_COMPLEX_H +#define INCLUDED_GR_COMPLEX_H + +#include +typedef std::complex gr_complex; +typedef std::complex gr_complexd; + + +inline bool is_complex (gr_complex x) { return true;} +inline bool is_complex (gr_complexd x) { return true;} +inline bool is_complex (float x) { return false;} +inline bool is_complex (double x) { return false;} +inline bool is_complex (int x) { return false;} +inline bool is_complex (char x) { return false;} +inline bool is_complex (short x) { return false;} + + +// this doesn't really belong here, but there are worse places for it... + +#define ASSERT_COMPLEXES_EQUAL(expected,actual,delta) \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.real(), actual.real(), delta); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.imag(), actual.imag(), delta); + +#endif /* INCLUDED_GR_COMPLEX_H */ + diff --git a/gnuradio-core/src/lib/runtime/gr_dispatcher.cc b/gnuradio-core/src/lib/runtime/gr_dispatcher.cc new file mode 100644 index 00000000..c2a1eb50 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.cc @@ -0,0 +1,192 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SELECT +# ifdef HAVE_SYS_SELECT_H +# include +# else +# ifdef HAVE_SYS_TIME_H +# include +# endif +# ifdef HAVE_SYS_TYPES_H +# include +# endif +# ifdef HAVE_UNISTD_H +# include +# endif +# endif +#endif + + +static gr_dispatcher_sptr s_singleton; + +gr_dispatcher_sptr +gr_make_dispatcher() +{ + return gr_dispatcher_sptr(new gr_dispatcher()); +} + +gr_dispatcher_sptr +gr_dispatcher_singleton() +{ + if (s_singleton) + return s_singleton; + + s_singleton = gr_make_dispatcher(); + return s_singleton; +} + +#if !defined(HAVE_SELECT) // Stub it out + +gr_dispatcher::gr_dispatcher() +{ +} + +gr_dispatcher::~gr_dispatcher() +{ +} + +bool +gr_dispatcher::add_handler(gr_select_handler_sptr handler) +{ + return true; +} + +bool +gr_dispatcher::del_handler(gr_select_handler_sptr handler) +{ + return true; +} + +bool +gr_dispatcher::del_handler(gr_select_handler *handler) +{ + return true; +} + +void +gr_dispatcher::loop(double timeout) +{ +} + +#else // defined(HAVE_SELECT) + +gr_dispatcher::gr_dispatcher() + : d_handler(FD_SETSIZE), d_max_index(-1) +{ +} + +gr_dispatcher::~gr_dispatcher() +{ +} + +bool +gr_dispatcher::add_handler(gr_select_handler_sptr handler) +{ + int fd = handler->fd(); + if (fd < 0 || fd >= FD_SETSIZE) + return false; + + d_max_index = std::max(d_max_index, fd); + d_handler[fd] = handler; + return true; +} + +bool +gr_dispatcher::del_handler(gr_select_handler_sptr handler) +{ + return del_handler(handler.get()); +} + +bool +gr_dispatcher::del_handler(gr_select_handler *handler) +{ + int fd = handler->fd(); + if (fd < 0 || fd >= FD_SETSIZE) + return false; + + d_handler[fd].reset(); + + if (fd == d_max_index){ + int i; + for (i = fd - 1; i >= 0 && !d_handler[i]; i--) + ; + d_max_index = i; + } + return true; +} + + +void +gr_dispatcher::loop(double timeout) +{ + struct timeval master; + struct timeval tmp; + fd_set rd_set; + fd_set wr_set; + + double secs = floor (timeout); + master.tv_sec = (long) secs; + master.tv_usec = (long) ((timeout - secs) * 1e6); + + while (d_max_index >= 0){ + FD_ZERO(&rd_set); + FD_ZERO(&wr_set); + + for (int i = 0; i <= d_max_index; i++){ + if (d_handler[i] && d_handler[i]->readable()) + FD_SET(i, &rd_set); + if (d_handler[i] && d_handler[i]->writable()) + FD_SET(i, &wr_set); + } + + tmp = master; + int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp); + if (retval == 0) // timed out with nothing ready + continue; + if (retval < 0){ + if (errno == EINTR) + continue; + perror ("gr_dispatcher/select"); + return; + } + + for (int i = 0; i <= d_max_index; i++){ + if (FD_ISSET(i, &rd_set)) + if (d_handler[i]) + d_handler[i]->handle_read(); + if (FD_ISSET(i, &wr_set)) + if (d_handler[i]) + d_handler[i]->handle_write(); + } + } +} + +#endif diff --git a/gnuradio-core/src/lib/runtime/gr_dispatcher.h b/gnuradio-core/src/lib/runtime/gr_dispatcher.h new file mode 100644 index 00000000..a3d85797 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DISPATCHER_H +#define INCLUDED_GR_DISPATCHER_H + +#include +#include + +class gr_dispatcher; +typedef boost::shared_ptr gr_dispatcher_sptr; + +gr_dispatcher_sptr gr_dispatcher_singleton(); +gr_dispatcher_sptr gr_make_dispatcher(); + +/*! + * \brief invoke callbacks based on select. + * + * \sa gr_select_handler + */ +class gr_dispatcher +{ + gr_dispatcher(); + friend gr_dispatcher_sptr gr_make_dispatcher(); + + std::vector d_handler; + int d_max_index; + +public: + ~gr_dispatcher(); + + bool add_handler(gr_select_handler_sptr handler); + bool del_handler(gr_select_handler_sptr handler); + bool del_handler(gr_select_handler *handler); + + /*! + * \brief Event dispatching loop. + * + * Enter a polling loop that only terminates after all gr_select_handlers + * have been removed. \p timeout sets the timeout parameter to the select() + * call, measured in seconds. + * + * \param timeout maximum number of seconds to block in select. + */ + void loop(double timeout=10); +}; + +#endif /* INCLUDED_GR_DISPATCHER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_dispatcher.i b/gnuradio-core/src/lib/runtime/gr_dispatcher.i new file mode 100644 index 00000000..5feca757 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.i @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_dispatcher; +typedef boost::shared_ptr gr_dispatcher_sptr; +%template(gr_dispatcher_sptr) boost::shared_ptr; + +%rename(dispatcher) gr_make_dispatcher; +gr_dispatcher_sptr gr_make_dispatcher(); + +%rename(dispatcher_singleton) gr_dispatcher_singleton; +gr_dispatcher_sptr gr_dispatcher_singleton(); + +/*! + * \brief invoke callbacks based on select. + * + * \sa gr_select_handler + */ +class gr_dispatcher +{ + gr_dispatcher(); + +public: + ~gr_dispatcher(); + + /*! + * \brief Event dispatching loop. + * + * Enter a polling loop that only terminates after all gr_select_handlers + * have been removed. \p timeout sets the timeout parameter to the select() + * call, measured in seconds. + * + * \param timeout maximum number of seconds to block in select. + */ + void loop(double timeout=10); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.cc b/gnuradio-core/src/lib/runtime/gr_error_handler.cc new file mode 100644 index 00000000..a3148cfd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.cc @@ -0,0 +1,244 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* + * This code is based on error.cc from the "Click Modular Router". + * Original copyright follows: + */ +/* + * error.{cc,hh} -- flexible classes for error reporting + * Eddie Kohler + * + * Copyright (c) 1999-2000 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef HAVE_IO_H +#include +#endif + +static gr_error_handler *s_default_handler = 0; +static gr_error_handler *s_silent_handler = 0; + +bool +gr_error_handler::has_default_handler() +{ + return s_default_handler != 0; +} + +void +gr_error_handler::set_default_handler(gr_error_handler *errh) +{ + s_default_handler = errh; +} + +gr_error_handler * +gr_error_handler::default_handler() +{ + assert (s_default_handler != 0); + return s_default_handler; +} + +gr_error_handler * +gr_error_handler::silent_handler() +{ + assert (s_silent_handler != 0); + return s_silent_handler; +} + +// ---------------------------------------------------------------- + +gr_error_handler::~gr_error_handler() +{ + // nop +} + +void +gr_error_handler::debug(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_DEBUG, format, val); + va_end(val); +} + +void +gr_error_handler::message(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_MESSAGE, format, val); + va_end(val); +} + +void +gr_error_handler::warning(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_WARNING, format, val); + va_end(val); +} + +void +gr_error_handler::error(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_ERROR, format, val); + va_end(val); +} + +void +gr_error_handler::fatal(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_FATAL, format, val); + va_end(val); +} + +void +gr_error_handler::verror(seriousness s, const char *format, va_list val) +{ + std::string text = make_text(s, format, val); + handle_text(s, text); + count_error(s); +} + +void +gr_error_handler::verror_text(seriousness s, const std::string &text) +{ + // text is already made + handle_text(s, text); + count_error(s); +} + +std::string +gr_error_handler::make_text(seriousness s, const char *format, va_list val) +{ + char text_buf[4096]; + vsnprintf(text_buf, sizeof(text_buf), format, val); + text_buf[sizeof(text_buf)-1] = 0; + return text_buf; +} + +// ---------------------------------------------------------------- + +void +gr_base_error_handler::count_error(seriousness s) +{ + if (s < ERR_WARNING) + /* do nothing */; + else if (s < ERR_ERROR) + d_nwarnings++; + else + d_nerrors++; +} + +// ---------------------------------------------------------------- + +gr_file_error_handler::gr_file_error_handler(FILE *file) + : d_file(file), d_fd(-1) +{ +} + +gr_file_error_handler::gr_file_error_handler(int file_descriptor) +{ + d_fd = dup(file_descriptor); // so we can fclose it + if (d_fd == -1){ + perror("gr_file_error_handler:dup"); + throw std::invalid_argument("gr_file_error_handler:dup"); + } + d_file = fdopen(d_fd, "w"); + if (d_file == 0){ + perror("gr_file_error_handler:fdopen"); + throw std::invalid_argument("gr_file_error_handler:fdopen"); + } +} + +gr_file_error_handler::~gr_file_error_handler() +{ + if (d_fd != -1){ + fclose(d_file); + } +} + +void +gr_file_error_handler::handle_text(seriousness s, const std::string &text) +{ + if (text.length() <= 0) + return; + + fwrite(text.data(), 1, text.length(), d_file); + if (text[text.length()-1] != '\n') + fwrite("\n", 1, 1, d_file); + + if (d_fd != -1) + fflush(d_file); // keep synced with any other users of fd +} + + +// ---------------------------------------------------------------- +// static error handlers +// + +class gr_silent_error_handler : public gr_base_error_handler +{ +public: + gr_silent_error_handler() {} + void handle_text(seriousness s, const std::string &str); +}; + +void +gr_silent_error_handler::handle_text(seriousness s, const std::string &str) +{ + // nop +} + +class force_init { +public: + force_init() + { + s_default_handler = new gr_file_error_handler(stdout); + s_silent_handler = new gr_silent_error_handler(); + } +}; + +static force_init kludge; diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.h b/gnuradio-core/src/lib/runtime/gr_error_handler.h new file mode 100644 index 00000000..275db64c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.h @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* + * This code is based on error.hh from the "Click Modular Router". + * Original copyright follows: + */ +/* + * error.{cc,hh} -- flexible classes for error reporting + * Eddie Kohler + * + * Copyright (c) 1999-2000 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#ifndef INCLUDED_GR_ERROR_HANDLER_H +#define INCLUDED_GR_ERROR_HANDLER_H + +#include +#include + +/*! + * \brief abstract error handler + */ +class gr_error_handler { +public: + enum seriousness { + ERR_DEBUG = 0x00000000, + ERR_MESSAGE = 0x00010000, + ERR_WARNING = 0x00020000, + ERR_ERROR = 0x00030000, + ERR_FATAL = 0x00040000 + }; + + gr_error_handler() {} + virtual ~gr_error_handler(); + + static gr_error_handler *default_handler(); + static gr_error_handler *silent_handler(); + + static bool has_default_handler(); + static void set_default_handler(gr_error_handler *errh); + + void debug(const char *format, ...); + void message(const char *format, ...); + void warning(const char *format, ...); + void error(const char *format, ...); + void fatal(const char *format, ...); + + virtual int nwarnings() const = 0; + virtual int nerrors() const = 0; + virtual void reset_counts() = 0; + + void verror(seriousness s, const char *format, va_list); + void verror_text(seriousness s, const std::string &text); + +protected: + virtual void count_error(seriousness s) = 0; + virtual void handle_text(seriousness s, const std::string &str) = 0; + std::string make_text(seriousness s, const char *format, va_list); +}; + + +class gr_base_error_handler : public gr_error_handler { + int d_nwarnings; + int d_nerrors; + +public: + gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {} + int nwarnings() const { return d_nwarnings; } + int nerrors() const { return d_nerrors; } + void reset_counts() { d_nwarnings = d_nerrors = 0; } + void count_error(seriousness s); +}; + +class gr_file_error_handler : public gr_base_error_handler { + FILE *d_file; + int d_fd; +public: + gr_file_error_handler(FILE *file); + gr_file_error_handler(int file_descriptor); + ~gr_file_error_handler(); + + void handle_text(seriousness s, const std::string &str); +}; + +#endif /* INCLUDED_GR_ERROR_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.i b/gnuradio-core/src/lib/runtime/gr_error_handler.i new file mode 100644 index 00000000..d0e61496 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.i @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%rename(error_handler) gr_error_handler; +%rename(file_error_handler) gr_file_error_handler; + +class gr_error_handler { +public: + enum seriousness { + ERR_DEBUG = 0x00000000, + ERR_MESSAGE = 0x00010000, + ERR_WARNING = 0x00020000, + ERR_ERROR = 0x00030000, + ERR_FATAL = 0x00040000 + }; + + gr_error_handler() {} + virtual ~gr_error_handler(); + + static gr_error_handler *default_handler(); + static gr_error_handler *silent_handler(); + + static bool has_default_handler(); + static void set_default_handler(gr_error_handler *errh); + + virtual int nwarnings() const = 0; + virtual int nerrors() const = 0; + virtual void reset_counts() = 0; + + void verror_text(seriousness s, const std::string &text); +}; + +%ignore gr_base_error_handler; +class gr_base_error_handler : public gr_error_handler { + int d_nwarnings; + int d_nerrors; + +public: + gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {} + int nwarnings() const { return d_nwarnings; } + int nerrors() const { return d_nerrors; } + void reset_counts() { d_nwarnings = d_nerrors = 0; } + void count_error(seriousness s); +}; + +class gr_file_error_handler : public gr_base_error_handler { +public: + gr_file_error_handler(int file_descriptor); + ~gr_file_error_handler(); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.cc b/gnuradio-core/src/lib/runtime/gr_io_signature.cc new file mode 100644 index 00000000..7277108c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.cc @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +gr_io_signature::gr_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item) +{ + if (min_streams < 0 + || (max_streams != IO_INFINITE && max_streams < min_streams)) + throw std::invalid_argument ("gr_io_signature"); + + d_min_streams = min_streams; + d_max_streams = max_streams; + d_sizeof_stream_item = sizeof_stream_item; +} + +gr_io_signature::~gr_io_signature () +{ + // NOP for now + // std::cout << "destroying gr_io_signature: " << this << '\n'; +} + +gr_io_signature_sptr +gr_make_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item) +{ + return gr_io_signature_sptr (new gr_io_signature (min_streams, max_streams, + sizeof_stream_item)); +} + + diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.h b/gnuradio-core/src/lib/runtime/gr_io_signature.h new file mode 100644 index 00000000..e0d97907 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_IO_SIGNATURE_H +#define INCLUDED_IO_SIGNATURE_H + +#include + +/*! + * \brief i/o signature for input and output ports. + * + * For now, we restrict all streams to be the same type. + * We can fix this later. + */ + +class gr_io_signature { + public: + + static const int IO_INFINITE = -1; + + ~gr_io_signature (); + + int min_streams () const { return d_min_streams; } + int max_streams () const { return d_max_streams; } + size_t sizeof_stream_item (int index) const { return d_sizeof_stream_item; } + + // ---------------------------------------------------------------------------- + + private: + + int d_min_streams; + int d_max_streams; + size_t d_sizeof_stream_item; + + gr_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item); + + friend gr_io_signature_sptr gr_make_io_signature (int min_streams, + int max_streams, + size_t sizeof_stream_item); +}; + +gr_io_signature_sptr +gr_make_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item); + + +#endif /* INCLUDED_IO_SIGNATURE_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.i b/gnuradio-core/src/lib/runtime/gr_io_signature.i new file mode 100644 index 00000000..601142e2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.i @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_io_signature; +typedef boost::shared_ptr gr_io_signature_sptr; +%template(gr_io_signature_sptr) boost::shared_ptr; + +%rename(io_signature) gr_make_io_signature; + +gr_io_signature_sptr +gr_make_io_signature (int min_streams, + int max_streams, + size_t sizeof_stream_item); + +class gr_io_signature { + public: + + // disabled. Suspected bug in SWIG 1.3.24 + // static const int IO_INFINITE = -1; + + ~gr_io_signature (); + + int min_streams () const { return d_min_streams; } + int max_streams () const { return d_max_streams; } + size_t sizeof_stream_item (int index) const { return d_sizeof_stream_item; } + + private: + gr_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item); +}; + diff --git a/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc b/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc new file mode 100644 index 00000000..c6da0978 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc @@ -0,0 +1,186 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +gr_local_sighandler::gr_local_sighandler (int signum, + void (*new_handler)(int)) + : d_signum (signum) +{ +#ifdef HAVE_SIGACTION + struct sigaction new_action; + memset (&new_action, 0, sizeof (new_action)); + + new_action.sa_handler = new_handler; + sigemptyset (&new_action.sa_mask); + new_action.sa_flags = 0; + + if (sigaction (d_signum, &new_action, &d_old_action) < 0){ + perror ("sigaction (install new)"); + throw std::runtime_error ("sigaction"); + } +#endif +} + +gr_local_sighandler::~gr_local_sighandler () +{ +#ifdef HAVE_SIGACTION + if (sigaction (d_signum, &d_old_action, 0) < 0){ + perror ("sigaction (restore old)"); + throw std::runtime_error ("sigaction"); + } +#endif +} + +void +gr_local_sighandler::throw_signal (int signum) +{ + throw gr_signal (signum); +} + +/* + * Semi-hideous way to may a signal number into a signal name + */ + +#define SIGNAME(x) case x: return #x + +std::string +gr_signal::name () const +{ + char tmp[128]; + + switch (signal ()){ +#ifdef SIGHUP + SIGNAME (SIGHUP); +#endif +#ifdef SIGINT + SIGNAME (SIGINT); +#endif +#ifdef SIGQUIT + SIGNAME (SIGQUIT); +#endif +#ifdef SIGILL + SIGNAME (SIGILL); +#endif +#ifdef SIGTRAP + SIGNAME (SIGTRAP); +#endif +#ifdef SIGABRT + SIGNAME (SIGABRT); +#endif +#ifdef SIGBUS + SIGNAME (SIGBUS); +#endif +#ifdef SIGFPE + SIGNAME (SIGFPE); +#endif +#ifdef SIGKILL + SIGNAME (SIGKILL); +#endif +#ifdef SIGUSR1 + SIGNAME (SIGUSR1); +#endif +#ifdef SIGSEGV + SIGNAME (SIGSEGV); +#endif +#ifdef SIGUSR2 + SIGNAME (SIGUSR2); +#endif +#ifdef SIGPIPE + SIGNAME (SIGPIPE); +#endif +#ifdef SIGALRM + SIGNAME (SIGALRM); +#endif +#ifdef SIGTERM + SIGNAME (SIGTERM); +#endif +#ifdef SIGSTKFLT + SIGNAME (SIGSTKFLT); +#endif +#ifdef SIGCHLD + SIGNAME (SIGCHLD); +#endif +#ifdef SIGCONT + SIGNAME (SIGCONT); +#endif +#ifdef SIGSTOP + SIGNAME (SIGSTOP); +#endif +#ifdef SIGTSTP + SIGNAME (SIGTSTP); +#endif +#ifdef SIGTTIN + SIGNAME (SIGTTIN); +#endif +#ifdef SIGTTOU + SIGNAME (SIGTTOU); +#endif +#ifdef SIGURG + SIGNAME (SIGURG); +#endif +#ifdef SIGXCPU + SIGNAME (SIGXCPU); +#endif +#ifdef SIGXFSZ + SIGNAME (SIGXFSZ); +#endif +#ifdef SIGVTALRM + SIGNAME (SIGVTALRM); +#endif +#ifdef SIGPROF + SIGNAME (SIGPROF); +#endif +#ifdef SIGWINCH + SIGNAME (SIGWINCH); +#endif +#ifdef SIGIO + SIGNAME (SIGIO); +#endif +#ifdef SIGPWR + SIGNAME (SIGPWR); +#endif +#ifdef SIGSYS + SIGNAME (SIGSYS); +#endif + default: +#if defined (HAVE_SNPRINTF) +#if defined (SIGRTMIN) && defined (SIGRTMAX) + if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){ + snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ()); + return tmp; + } +#endif + snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ()); + return tmp; +#else + return "Unknown signal"; +#endif + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_local_sighandler.h b/gnuradio-core/src/lib/runtime/gr_local_sighandler.h new file mode 100644 index 00000000..69eb65d8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_local_sighandler.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_LOCAL_SIGHANDLER_H +#define INCLUDED_GR_LOCAL_SIGHANDLER_H + +#include +#include + +/*! + * \brief Get and set signal handler. + * + * Constructor installs new handler, destructor reinstalls + * original value. + */ +class gr_local_sighandler { + int d_signum; +#ifdef HAVE_SIGACTION + struct sigaction d_old_action; +#endif +public: + gr_local_sighandler (int signum, void (*new_handler)(int)); + ~gr_local_sighandler (); + + /* throw gr_signal (signum) */ + static void throw_signal (int signum); +}; + +/*! + * \brief Representation of signal. + */ +class gr_signal +{ + int d_signum; +public: + gr_signal (int signum) : d_signum (signum) {} + int signal () const { return d_signum; } + std::string name () const; +}; + +#endif /* INCLUDED_GR_LOCAL_SIGHANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_message.cc b/gnuradio-core/src/lib/runtime/gr_message.cc new file mode 100644 index 00000000..e9427e64 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +static long s_ncurrently_allocated = 0; + +gr_message_sptr +gr_make_message (long type, double arg1, double arg2, size_t length) +{ + return gr_message_sptr (new gr_message (type, arg1, arg2, length)); +} + +gr_message_sptr +gr_make_message_from_string(const std::string s, long type, double arg1, double arg2) +{ + gr_message_sptr m = gr_make_message(type, arg1, arg2, s.size()); + memcpy(m->msg(), s.data(), s.size()); + return m; +} + + +gr_message::gr_message (long type, double arg1, double arg2, size_t length) + : d_type(type), d_arg1(arg1), d_arg2(arg2) +{ + if (length == 0) + d_buf_start = d_msg_start = d_msg_end = d_buf_end = 0; + else { + d_buf_start = new unsigned char [length]; + d_msg_start = d_buf_start; + d_msg_end = d_buf_end = d_buf_start + length; + } + s_ncurrently_allocated++; +} + +gr_message::~gr_message () +{ + assert (d_next == 0); + delete [] d_buf_start; + d_msg_start = d_msg_end = d_buf_end = 0; + s_ncurrently_allocated--; +} + +std::string +gr_message::to_string() const +{ + return std::string((char *)d_msg_start, length()); +} + +long +gr_message_ncurrently_allocated () +{ + return s_ncurrently_allocated; +} diff --git a/gnuradio-core/src/lib/runtime/gr_message.h b/gnuradio-core/src/lib/runtime/gr_message.h new file mode 100644 index 00000000..272a82ee --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MESSAGE_H +#define INCLUDED_GR_MESSAGE_H + +#include +#include + +class gr_message; +typedef boost::shared_ptr gr_message_sptr; + +/*! + * \brief public constructor for gr_message + */ +gr_message_sptr +gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + +gr_message_sptr +gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0); + +/*! + * \brief Message. + * + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ +class gr_message { + gr_message_sptr d_next; // link field for msg queue + long d_type; // type of the message + double d_arg1; // optional arg1 + double d_arg2; // optional arg2 + + unsigned char *d_buf_start; // start of allocated buffer + unsigned char *d_msg_start; // where the msg starts + unsigned char *d_msg_end; // one beyond end of msg + unsigned char *d_buf_end; // one beyond end of allocated buffer + + gr_message (long type, double arg1, double arg2, size_t length); + + friend gr_message_sptr + gr_make_message (long type, double arg1, double arg2, size_t length); + + friend gr_message_sptr + gr_make_message_from_string (const std::string s, long type, double arg1, double arg2); + + friend class gr_msg_queue; + + unsigned char *buf_data() const { return d_buf_start; } + size_t buf_len() const { return d_buf_end - d_buf_start; } + +public: + ~gr_message (); + + long type() const { return d_type; } + double arg1() const { return d_arg1; } + double arg2() const { return d_arg2; } + + void set_type(long type) { d_type = type; } + void set_arg1(double arg1) { d_arg1 = arg1; } + void set_arg2(double arg2) { d_arg2 = arg2; } + + unsigned char *msg() const { return d_msg_start; } + size_t length() const { return d_msg_end - d_msg_start; } + std::string to_string() const; + +}; + +long gr_message_ncurrently_allocated (); + +#endif /* INCLUDED_GR_MESSAGE_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_message.i b/gnuradio-core/src/lib/runtime/gr_message.i new file mode 100644 index 00000000..19d5d1cd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.i @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_message; +typedef boost::shared_ptr gr_message_sptr; +%template(gr_message_sptr) boost::shared_ptr; + +%rename(message_from_string) gr_make_message_from_string; +gr_message_sptr +gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0); + +%rename(message) gr_make_message; +gr_message_sptr +gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + +/*! + * \brief Message. + * + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ +class gr_message { + gr_message (long type, double arg1, double arg2, size_t length); + + unsigned char *buf_data() const { return d_buf_start; } + size_t buf_len() const { return d_buf_end - d_buf_start; } + +public: + ~gr_message (); + + long type() const { return d_type; } + double arg1() const { return d_arg1; } + double arg2() const { return d_arg2; } + + void set_type(long type) { d_type = type; } + void set_arg1(double arg1) { d_arg1 = arg1; } + void set_arg2(double arg2) { d_arg2 = arg2; } + + size_t length() const; + std::string to_string() const; + +}; + +%rename(message_ncurrently_allocated) gr_message_ncurrently_allocated; +long gr_message_ncurrently_allocated(); + diff --git a/gnuradio-core/src/lib/runtime/gr_msg_handler.cc b/gnuradio-core/src/lib/runtime/gr_msg_handler.cc new file mode 100644 index 00000000..98007e23 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.cc @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +gr_msg_handler::~gr_msg_handler () +{ +} diff --git a/gnuradio-core/src/lib/runtime/gr_msg_handler.h b/gnuradio-core/src/lib/runtime/gr_msg_handler.h new file mode 100644 index 00000000..15aab338 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MSG_HANDLER_H +#define INCLUDED_GR_MSG_HANDLER_H + +#include + +class gr_msg_handler; +typedef boost::shared_ptr gr_msg_handler_sptr; + +/*! + * \brief abstract class of message handlers + */ +class gr_msg_handler { +public: + virtual ~gr_msg_handler (); + + //! handle \p msg + virtual void handle (gr_message_sptr msg) = 0; +}; + +#endif /* INCLUDED_GR_MSG_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_msg_handler.i b/gnuradio-core/src/lib/runtime/gr_msg_handler.i new file mode 100644 index 00000000..5571665a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/*! + * \brief abstract class of message handlers + */ +class gr_msg_handler { +public: + virtual ~gr_msg_handler () = 0; + + //! handle \p msg + virtual void handle (gr_message_sptr msg) = 0; +}; diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.cc b/gnuradio-core/src/lib/runtime/gr_msg_queue.cc new file mode 100644 index 00000000..6b53fc7e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.cc @@ -0,0 +1,127 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + + +gr_msg_queue_sptr +gr_make_msg_queue(unsigned int limit) +{ + return gr_msg_queue_sptr (new gr_msg_queue(limit)); +} + + +gr_msg_queue::gr_msg_queue(unsigned int limit) + : d_not_empty(&d_mutex), d_not_full(&d_mutex), + /*d_head(0), d_tail(0),*/ d_count(0), d_limit(limit) +{ +} + +gr_msg_queue::~gr_msg_queue() +{ + flush (); +} + +void +gr_msg_queue::insert_tail(gr_message_sptr msg) +{ + if (msg->d_next) + throw std::invalid_argument("gr_msg_queue::insert_tail: msg already in queue"); + + omni_mutex_lock l(d_mutex); + + while (full_p()) + d_not_full.wait(); + + if (d_tail == 0){ + d_tail = d_head = msg; + //msg->d_next = 0; + msg->d_next.reset(); + } + else { + d_tail->d_next = msg; + d_tail = msg; + //msg->d_next = 0; + msg->d_next.reset(); + } + d_count++; + d_not_empty.signal(); +} + +gr_message_sptr +gr_msg_queue::delete_head() +{ + omni_mutex_lock l(d_mutex); + gr_message_sptr m; + + while ((m = d_head) == 0) + d_not_empty.wait(); + + d_head = m->d_next; + if (d_head == 0){ + //d_tail = 0; + d_tail.reset(); + } + + d_count--; + // m->d_next = 0; + m->d_next.reset(); + d_not_full.signal(); + return m; +} + +gr_message_sptr +gr_msg_queue::delete_head_nowait() +{ + omni_mutex_lock l(d_mutex); + gr_message_sptr m; + + if ((m = d_head) == 0){ + //return 0; + return gr_message_sptr(); + } + + d_head = m->d_next; + if (d_head == 0){ + //d_tail = 0; + d_tail.reset(); + } + + d_count--; + //m->d_next = 0; + m->d_next.reset(); + d_not_full.signal(); + return m; +} + +void +gr_msg_queue::flush() +{ + gr_message_sptr m; + + while ((m = delete_head_nowait ()) != 0) + ; +} diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.h b/gnuradio-core/src/lib/runtime/gr_msg_queue.h new file mode 100644 index 00000000..6a9147ee --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MSG_QUEUE_H +#define INCLUDED_GR_MSG_QUEUE_H + +#include +#include + +class gr_msg_queue; +typedef boost::shared_ptr gr_msg_queue_sptr; + +gr_msg_queue_sptr gr_make_msg_queue(unsigned int limit=0); + +/*! + * \brief thread-safe message queue + */ +class gr_msg_queue : public gr_msg_handler { + omni_mutex d_mutex; + omni_condition d_not_empty; + omni_condition d_not_full; + gr_message_sptr d_head; + gr_message_sptr d_tail; + unsigned int d_count; // # of messages in queue. + unsigned int d_limit; // max # of messages in queue. 0 -> unbounded + +public: + gr_msg_queue(unsigned int limit); + ~gr_msg_queue(); + + //! Generic msg_handler method: insert the message. + void handle(gr_message_sptr msg) { insert_tail (msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + void insert_tail(gr_message_sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + gr_message_sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + gr_message_sptr delete_head_nowait(); + + //! Delete all messages from the queue + void flush(); + + //! is the queue empty? + bool empty_p() const { return d_count == 0; } + + //! is the queue full? + bool full_p() const { return d_limit != 0 && d_count >= d_limit; } + + //! return number of messages in queue + unsigned int count() const { return d_count; } + + //! return limit on number of message in queue. 0 -> unbounded + unsigned int limit() const { return d_limit; } + +}; + +#endif /* INCLUDED_GR_MSG_QUEUE_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.i b/gnuradio-core/src/lib/runtime/gr_msg_queue.i new file mode 100644 index 00000000..28292d66 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.i @@ -0,0 +1,111 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_msg_queue; +typedef boost::shared_ptr gr_msg_queue_sptr; +%template(gr_msg_queue_sptr) boost::shared_ptr; + +%rename(msg_queue) gr_make_msg_queue; +gr_msg_queue_sptr gr_make_msg_queue(unsigned limit=0); + +/*! + * \brief thread-safe message queue + */ +%ignore gr_msg_queue; +class gr_msg_queue : public gr_msg_handler { + omni_mutex d_mutex; + omni_condition d_cond; + gr_message_sptr d_head; + gr_message_sptr d_tail; + int d_count; + +public: + gr_msg_queue(); + ~gr_msg_queue(); + + //! Generic msg_handler method: insert the message. + //void handle(gr_message_sptr msg) { insert_tail (msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + //void insert_tail(gr_message_sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + //gr_message_sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + gr_message_sptr delete_head_nowait(); + + //! is the queue empty? + bool empty_p() const; + + //! is the queue full? + bool full_p() const; + + //! return number of messages in queue + unsigned int count() const; + + //! Delete all messages from the queue + void flush(); +}; + +/* + * The following kludge-o-rama releases the Python global interpreter + * lock around these potentially blocking calls. We don't want + * libgnuradio-core to be dependent on Python, thus we create these + * functions that serve as replacements for the normal C++ delete_head + * and insert_tail methods. The %pythoncode smashes these new C++ + * functions into the gr.msg_queue wrapper class, so that everything + * appears normal. (An evil laugh is heard in the distance...) + */ +%inline { + gr_message_sptr gr_py_msg_queue__delete_head(gr_msg_queue_sptr q) { + gr_message_sptr msg; + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + msg = q->delete_head(); // possibly blocking call + Py_END_ALLOW_THREADS; // acquire global interpreter lock + return msg; + } + + void gr_py_msg_queue__insert_tail(gr_msg_queue_sptr q, gr_message_sptr msg) { + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + q->insert_tail(msg); // possibly blocking call + Py_END_ALLOW_THREADS; // acquire global interpreter lock + } +} + +// smash in new python delete_head and insert_tail methods... +%pythoncode %{ +gr_msg_queue_sptr.delete_head = gr_py_msg_queue__delete_head +gr_msg_queue_sptr.insert_tail = gr_py_msg_queue__insert_tail +gr_msg_queue_sptr.handle = gr_py_msg_queue__insert_tail +%} diff --git a/gnuradio-core/src/lib/runtime/gr_pagesize.cc b/gnuradio-core/src/lib/runtime/gr_pagesize.cc new file mode 100644 index 00000000..dec40678 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_pagesize.cc @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#if defined(_WIN32) && defined(HAVE_GETPAGESIZE) +extern "C" size_t getpagesize(void); +#endif + +int +gr_pagesize () +{ + static int s_pagesize = -1; + + if (s_pagesize == -1){ +#if defined(HAVE_GETPAGESIZE) + s_pagesize = getpagesize (); +#elif defined (HAVE_SYSCONF) + s_pagesize = sysconf (_SC_PAGESIZE); + if (s_pagesize == -1){ + perror ("_SC_PAGESIZE"); + s_pagesize = 4096; + } +#else + fprintf (stderr, "gr_pagesize: no info; setting pagesize = 4096\n"); + s_pagesize = 4096; +#endif + } + return s_pagesize; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_pagesize.h b/gnuradio-core/src/lib/runtime/gr_pagesize.h new file mode 100644 index 00000000..a5cadb70 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_pagesize.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_PAGESIZE_H_ +#define _GR_PAGESIZE_H_ + +/*! + * \brief return the page size in bytes + */ + +int gr_pagesize (); + + +#endif /* _GR_PAGESIZE_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_preferences.cc b/gnuradio-core/src/lib/runtime/gr_preferences.cc new file mode 100644 index 00000000..85431444 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_preferences.cc @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef MKDIR_TAKES_ONE_ARG +#define gr_mkdir(pathname, mode) mkdir(pathname) +#else +#define gr_mkdir(pathname, mode) mkdir((pathname), (mode)) +#endif + +/* + * The simplest thing that could possibly work: + * the key is the filename; the value is the file contents. + */ + +static const char * +pathname (const char *key) +{ + static char buf[200]; + snprintf (buf, sizeof (buf), "%s/.gnuradio/prefs/%s", getenv ("HOME"), key); + return buf; +} + +static void +ensure_dir_path () +{ + char path[200]; + struct stat statbuf; + + snprintf (path, sizeof (path), "%s/.gnuradio/prefs", getenv ("HOME")); + if (stat (path, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + return; + + // blindly try to make it // FIXME make this robust. C++ SUCKS! + + snprintf (path, sizeof (path), "%s/.gnuradio", getenv ("HOME")); + gr_mkdir (path, 0750); + snprintf (path, sizeof (path), "%s/.gnuradio/prefs", getenv ("HOME")); + gr_mkdir (path, 0750); +} + +const char * +gr_preferences::get (const char *key) +{ + static char buf[1024]; + + FILE *fp = fopen (pathname (key), "r"); + if (fp == 0) + return 0; + + memset (buf, 0, sizeof (buf)); + fread (buf, 1, sizeof (buf) - 1, fp); + fclose (fp); + return buf; +} + +void +gr_preferences::set (const char *key, const char *value) +{ + ensure_dir_path (); + + FILE *fp = fopen (pathname (key), "w"); + if (fp == 0){ + perror (pathname (key)); + return; + } + + fwrite (value, 1, strlen (value), fp); + fclose (fp); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_preferences.h b/gnuradio-core/src/lib/runtime/gr_preferences.h new file mode 100644 index 00000000..5a7cad45 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_preferences.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_PREFERENCES_H_ +#define _GR_PREFERENCES_H_ + +class gr_preferences { + public: + static const char *get (const char *key); + static void set (const char *key, const char *value); +}; + +#endif /* _GR_PREFERENCES_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_realtime.cc b/gnuradio-core/src/lib/runtime/gr_realtime.cc new file mode 100644 index 00000000..4f23ea0c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#ifdef HAVE_SCHED_H +#include +#endif + +#include +#include +#include + +#if defined(HAVE_SCHED_SETSCHEDULER) + +gr_rt_status_t +gr_enable_realtime_scheduling() +{ + int policy = SCHED_FIFO; + int pri = (sched_get_priority_max (policy) - sched_get_priority_min (policy)) / 2; + int pid = 0; // this process + + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = pri; + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ + if (errno == EPERM) + return RT_NO_PRIVS; + else { + perror ("sched_setscheduler: failed to set real time priority"); + return RT_OTHER_ERROR; + } + } + //printf("SCHED_FIFO enabled with priority = %d\n", pri); + return RT_OK; +} + +// #elif // could try negative niceness + +#else + +gr_rt_status_t +gr_enable_realtime_scheduling() +{ + return RT_NOT_IMPLEMENTED; +} + +#endif diff --git a/gnuradio-core/src/lib/runtime/gr_realtime.h b/gnuradio-core/src/lib/runtime/gr_realtime.h new file mode 100644 index 00000000..3aeafa53 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.h @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_REALTIME_H +#define INCLUDED_GR_REALTIME_H + +typedef enum { + RT_OK = 0, + RT_NOT_IMPLEMENTED, + RT_NO_PRIVS, + RT_OTHER_ERROR +} gr_rt_status_t; + +/*! + * \brief If possible, enable high-priority "real time" scheduling. + */ +gr_rt_status_t +gr_enable_realtime_scheduling(); + +#endif /* INCLUDED_GR_REALTIME_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_realtime.i b/gnuradio-core/src/lib/runtime/gr_realtime.i new file mode 100644 index 00000000..cb43e051 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.i @@ -0,0 +1,4 @@ +%rename(enable_realtime_scheduling) gr_enable_realtime_scheduling; + +%include + diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.h b/gnuradio-core/src/lib/runtime/gr_runtime.h new file mode 100644 index 00000000..f138e6ac --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_H +#define INCLUDED_GR_RUNTIME_H + +#include + +/* + * typedefs for smart pointers we use throughout the runtime system + */ + +class gr_block; +class gr_block_detail; +class gr_io_signature; +class gr_buffer; +class gr_buffer_reader; + +typedef boost::shared_ptr gr_block_sptr; +typedef boost::shared_ptr gr_block_detail_sptr; +typedef boost::shared_ptr gr_io_signature_sptr; +typedef boost::shared_ptr gr_buffer_sptr; +typedef boost::shared_ptr gr_buffer_reader_sptr; + +#endif /* INCLUDED_GR_RUNTIME_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_select_handler.cc b/gnuradio-core/src/lib/runtime/gr_select_handler.cc new file mode 100644 index 00000000..d85883a6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_select_handler.cc @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +gr_select_handler::gr_select_handler(int fd) + : d_fd(fd) +{ +} + +gr_select_handler::~gr_select_handler() +{ +} diff --git a/gnuradio-core/src/lib/runtime/gr_select_handler.h b/gnuradio-core/src/lib/runtime/gr_select_handler.h new file mode 100644 index 00000000..d07ff007 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_select_handler.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SELECT_HANDLER_H +#define INCLUDED_GR_SELECT_HANDLER_H + +#include + +class gr_select_handler; +typedef boost::shared_ptr gr_select_handler_sptr; + + +/*! + * \brief Abstract handler for select based notification. + * + * \sa gr_dispatcher + */ +class gr_select_handler +{ + int d_fd; + +protected: + gr_select_handler(int file_descriptor); + +public: + virtual ~gr_select_handler(); + + int fd() const { return d_fd; } + int file_descriptor() const { return d_fd; } + + /*! + * \brief Called when file_descriptor is readable. + * + * Called when the dispatcher detects that file_descriptor can + * be read without blocking. + */ + virtual void handle_read() = 0; + + /*! + * \brief Called when file_descriptor is writable. + * + * Called when dispatcher detects that file descriptor can be + * written without blocking. + */ + virtual void handle_write() = 0; + + /*! + * Called each time around the dispatcher loop to determine whether + * this handler's file descriptor should be added to the list on which + * read events can occur. The default method returns true, indicating + * that by default, all handlers are interested in read events. + */ + virtual bool readable() { return true; } + + /*! + * Called each time around the dispatcher loop to determine whether + * this handler's file descriptor should be added to the list on which + * write events can occur. The default method returns true, indicating + * that by default, all handlers are interested in write events. + */ + virtual bool writable() { return true; } +}; + +#endif /* INCLUDED_GR_SELECT_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc new file mode 100644 index 00000000..3d401557 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc @@ -0,0 +1,360 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +// must be defined to either 0 or 1 +#define ENABLE_LOGGING 0 + +#if (ENABLE_LOGGING) +#define LOG(x) do { x; } while(0) +#else +#define LOG(x) do {;} while(0) +#endif + +static int which_scheduler = 0; + + +std::ostream& +operator << (std::ostream& os, const gr_block *m) +{ + os << "name() << " (" << m->unique_id() << ")>"; + return os; +} + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector &blocks) +{ + return + gr_single_threaded_scheduler_sptr (new gr_single_threaded_scheduler (blocks)); +} + +gr_single_threaded_scheduler::gr_single_threaded_scheduler ( + const std::vector &blocks) + : d_blocks (blocks), d_enabled (true), d_log(0) +{ + if (ENABLE_LOGGING){ + char name[100]; + snprintf(name, sizeof(name), "sst-%d.log", which_scheduler++); + d_log = new std::ofstream(name); + *d_log << "gr_single_threaded_scheduler: " + << d_blocks.size () + << " blocks\n"; + } +} + +gr_single_threaded_scheduler::~gr_single_threaded_scheduler () +{ + if (ENABLE_LOGGING) + delete d_log; +} + +void +gr_single_threaded_scheduler::run () +{ + d_enabled = true; + main_loop (); +} + + +inline static unsigned int +round_up (unsigned int n, unsigned int multiple) +{ + return ((n + multiple - 1) / multiple) * multiple; +} + +inline static unsigned int +round_down (unsigned int n, unsigned int multiple) +{ + return (n / multiple) * multiple; +} + +// +// Return minimum available write space in all our downstream buffers +// or -1 if we're output blocked and the output we're blocked +// on is done. +// +static int +min_available_space (gr_block_detail *d, int output_multiple) +{ + int min_space = std::numeric_limits::max(); + + for (int i = 0; i < d->noutputs (); i++){ + int n = round_down (d->output(i)->space_available (), output_multiple); + if (n == 0){ // We're blocked on output. + if (d->output(i)->done()){ // Downstream is done, therefore we're done. + return -1; + } + return 0; + } + min_space = std::min (min_space, n); + } + return min_space; +} + +void +gr_single_threaded_scheduler::main_loop () +{ + static const int DEFAULT_CAPACITY = 16; + + int noutput_items; + gr_vector_int ninput_items_required (DEFAULT_CAPACITY); + gr_vector_int ninput_items (DEFAULT_CAPACITY); + gr_vector_const_void_star input_items (DEFAULT_CAPACITY); + gr_vector_void_star output_items (DEFAULT_CAPACITY); + unsigned int bi; + unsigned int nalive; + int max_items_avail; + bool made_progress_last_pass; + bool making_progress; + + for (unsigned i = 0; i < d_blocks.size (); i++) + d_blocks[i]->detail()->set_done (false); // reset any done flags + + for (unsigned i = 0; i < d_blocks.size (); i++) // enable any drivers, etc. + d_blocks[i]->start(); + + + bi = 0; + made_progress_last_pass = true; + making_progress = false; + + // Loop while there are still blocks alive + + nalive = d_blocks.size (); + while (d_enabled && nalive > 0){ + + gr_block *m = d_blocks[bi].get (); + gr_block_detail *d = m->detail().get (); + + LOG(*d_log << std::endl << m); + + if (d->done ()) + goto next_block; + + if (d->source_p ()){ + // Invoke sources as a last resort. As long as the previous pass + // made progress, don't call a source. + if (made_progress_last_pass){ + LOG(*d_log << " Skipping source\n"); + goto next_block; + } + + ninput_items_required.resize (0); + ninput_items.resize (0); + input_items.resize (0); + output_items.resize (d->noutputs ()); + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple ()); + LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); + if (noutput_items == -1) // we're done + goto were_done; + + if (noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + goto next_block; + } + + goto setup_call_to_work; // jump to common code + } + + else if (d->sink_p ()){ + ninput_items_required.resize (d->ninputs ()); + ninput_items.resize (d->ninputs ()); + input_items.resize (d->ninputs ()); + output_items.resize (0); + LOG(*d_log << " sink\n"); + + max_items_avail = 0; + for (int i = 0; i < d->ninputs (); i++){ + ninput_items[i] = d->input(i)->items_available(); + //if (ninput_items[i] == 0 && d->input(i)->done()) + if (ninput_items[i] < m->output_multiple() && d->input(i)->done()) + goto were_done; + + max_items_avail = std::max (max_items_avail, ninput_items[i]); + } + + // take a swag at how much output we can sink + noutput_items = (int) (max_items_avail * m->relative_rate ()); + noutput_items = round_down (noutput_items, m->output_multiple ()); + LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); + LOG(*d_log << " noutput_items = " << noutput_items << std::endl); + + if (noutput_items == 0){ // we're blocked on input + LOG(*d_log << " BLKD_IN\n"); + goto next_block; + } + + goto try_again; // Jump to code shared with regular case. + } + + else { + // do the regular thing + ninput_items_required.resize (d->ninputs ()); + ninput_items.resize (d->ninputs ()); + input_items.resize (d->ninputs ()); + output_items.resize (d->noutputs ()); + + max_items_avail = 0; + for (int i = 0; i < d->ninputs (); i++){ + ninput_items[i] = d->input(i)->items_available (); + max_items_avail = std::max (max_items_avail, ninput_items[i]); + } + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple ()); + if (ENABLE_LOGGING){ + *d_log << " regular "; + if (m->relative_rate() >= 1.0) + *d_log << "1:" << m->relative_rate() << std::endl; + else + *d_log << 1.0/m->relative_rate() << ":1\n"; + *d_log << " max_items_avail = " << max_items_avail << std::endl; + *d_log << " noutput_items = " << noutput_items << std::endl; + } + if (noutput_items == -1) // we're done + goto were_done; + + if (noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + goto next_block; + } + +#if 0 + // Compute best estimate of noutput_items that we can really use. + noutput_items = + std::min ((unsigned) noutput_items, + std::max ((unsigned) m->output_multiple(), + round_up ((unsigned) (max_items_avail * m->relative_rate()), + m->output_multiple ()))); + + LOG(*d_log << " revised noutput_items = " << noutput_items << std::endl); +#endif + + try_again: + if (m->fixed_rate()){ + // try to work it forward starting with max_items_avail. + // We want to try to consume all the input we've got. + int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); + reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple()); + if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) + noutput_items = reqd_noutput_items; + } + + // ask the block how much input they need to produce noutput_items + m->forecast (noutput_items, ninput_items_required); + + // See if we've got sufficient input available + + int i; + for (i = 0; i < d->ninputs (); i++) + if (ninput_items_required[i] > ninput_items[i]) // not enough + break; + + if (i < d->ninputs ()){ // not enough input on input[i] + // if we can, try reducing the size of our output request + if (noutput_items > m->output_multiple ()){ + noutput_items /= 2; + noutput_items = round_up (noutput_items, m->output_multiple ()); + goto try_again; + } + + // We're blocked on input + LOG(*d_log << " BLKD_IN\n"); + if (d->input(i)->done()) // If the upstream block is done, we're done + goto were_done; + + // Is it possible to ever fulfill this request? + if (ninput_items_required[i] > d->input(i)->max_possible_items_available ()){ + // Nope, never going to happen... + std::cerr << "\nsched: name() + << " (" << m->unique_id() << ")>" + << " is requesting more input data\n" + << " than we can provide.\n" + << " ninput_items_required = " + << ninput_items_required[i] << "\n" + << " max_possible_items_available = " + << d->input(i)->max_possible_items_available() << "\n" + << " If this is a filter, consider reducing the number of taps.\n"; + goto were_done; + } + + goto next_block; + } + + // We've got enough data on each input to produce noutput_items. + // Finish setting up the call to work. + + for (int i = 0; i < d->ninputs (); i++) + input_items[i] = d->input(i)->read_pointer(); + + setup_call_to_work: + + for (int i = 0; i < d->noutputs (); i++) + output_items[i] = d->output(i)->write_pointer(); + + // Do the actual work of the block + int n = m->general_work (noutput_items, ninput_items, + input_items, output_items); + LOG(*d_log << " general_work: noutput_items = " << noutput_items + << " result = " << n << std::endl); + + if (n == -1) // block is done + goto were_done; + + d->produce_each (n); // advance write pointers + if (n > 0) + making_progress = true; + + goto next_block; + } + assert (0); + + were_done: + LOG(*d_log << " were_done\n"); + d->set_done (true); + nalive--; + + next_block: + if (++bi >= d_blocks.size ()){ + bi = 0; + made_progress_last_pass = making_progress; + making_progress = false; + } + } + + for (unsigned i = 0; i < d_blocks.size (); i++) // disable any drivers, etc. + d_blocks[i]->stop(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h new file mode 100644 index 00000000..1272831e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H +#define INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H + +#include +#include + +class gr_single_threaded_scheduler; +typedef boost::shared_ptr gr_single_threaded_scheduler_sptr; + + +/*! + * \brief Simple scheduler for stream computations. + * \ingroup internal + */ + +class gr_single_threaded_scheduler { + public: + ~gr_single_threaded_scheduler (); + + void run (); + void stop () { d_enabled = false; } + + private: + const std::vector d_blocks; + volatile bool d_enabled; + std::ofstream *d_log; + + gr_single_threaded_scheduler (const std::vector &blocks); + + void main_loop (); + + friend gr_single_threaded_scheduler_sptr + gr_make_single_threaded_scheduler (const std::vector &blocks); +}; + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector &blocks); + +#endif /* INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i new file mode 100644 index 00000000..40058228 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +class gr_single_threaded_scheduler; +typedef boost::shared_ptr gr_single_threaded_scheduler_sptr; +%template(gr_single_threaded_scheduler_sptr) boost::shared_ptr; +%rename(single_threaded_scheduler) gr_make_single_threaded_scheduler; +%ignore gr_single_threaded_scheduler; + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector &modules); + +class gr_single_threaded_scheduler { + public: + ~gr_single_threaded_scheduler (); + + // void run (); + void stop (); + + private: + gr_single_threaded_scheduler (const std::vector &modules); +}; + +%inline { + void sts_pyrun (gr_single_threaded_scheduler_sptr s) { + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + s->run (); + Py_END_ALLOW_THREADS; // acquire global interpreter lock + } +} + diff --git a/gnuradio-core/src/lib/runtime/gr_swig_block_magic.i b/gnuradio-core/src/lib/runtime/gr_swig_block_magic.i new file mode 100644 index 00000000..ca4f6e60 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_swig_block_magic.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%define GR_SWIG_BLOCK_MAGIC(PKG, BASE_NAME) +_GR_SWIG_BLOCK_MAGIC_HELPER(PKG, PKG ## _ ## BASE_NAME, BASE_NAME) +%enddef + +%define _GR_SWIG_BLOCK_MAGIC_HELPER(PKG, NAME, BASE_NAME) +class NAME; +typedef boost::shared_ptr NAME ## _sptr; +%template(NAME ## _sptr) boost::shared_ptr; +%rename(BASE_NAME) PKG ## _make_ ## BASE_NAME; +%inline { + gr_block_sptr NAME ## _block (NAME ## _sptr r) + { + return gr_block_sptr (r); + } +} + +%pythoncode %{ +NAME ## _sptr.block = lambda self: NAME ## _block (self) +NAME ## _sptr.__repr__ = lambda self: "" % (self.name(), self.unique_id ()) +%} + +%ignore NAME; +%enddef diff --git a/gnuradio-core/src/lib/runtime/gr_timer.h b/gnuradio-core/src/lib/runtime/gr_timer.h new file mode 100644 index 00000000..709b9847 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_timer.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_TIMER_H +#define INCLUDED_GR_TIMER_H + +#include + +class gr_timer; + +typedef boost::shared_ptr gr_timer_sptr; + +typedef void (*gr_timer_hook)(gr_timer *, void *); + +/*! + * \brief create a timeout. + * + * gr_timer_hook is called when timer fires. + */ +gr_timer_sptr gr_make_timer (gr_timer_hook, void *); + +/*! + * \brief implement timeouts + */ +class gr_timer { + double d_expiry; + double d_period; + gr_timer_hook d_hook; + void *d_hook_arg; + + friend gr_timer_sptr gr_make_timer (gr_timer_hook, void *); + + gr_timer (...); + +public: + ~gr_timer (); + + //! return absolute current time (seconds since the epoc). + static double now (); + + /*! + * \brief schedule timer to fire at abs_when + * \param abs_when absolute time in seconds since the epoc. + */ + void schedule_at (double abs_when); + + /*! + * \brief schedule timer to fire rel_when seconds from now. + * \param rel_when relative time in seconds from now. + */ + void schedule_after (double rel_when); // relative time in seconds + + /*! + * \brief schedule a periodic timeout. + * \param abs_when absolute time to fire first time + * \param period time between firings + */ + void schedule_periodic (double abs_when, double period); + + //! cancel timer + void unschedule (); +}; + +#endif /* INCLUDED_GR_TIMER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_tmp_path.cc b/gnuradio-core/src/lib/runtime/gr_tmp_path.cc new file mode 100644 index 00000000..7eb03b5d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tmp_path.cc @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +const char * +gr_tmp_path () +{ + static char *pp = 0; + + if (pp) + return pp; + + char *s = getenv ("TMP"); + if (s){ + pp = strdup (s); + return pp; + } + +#ifdef P_tmpdir + if (P_tmpdir){ + pp = strdup (P_tmpdir); + return pp; + } +#endif + + pp = strdup ("/tmp"); + return pp; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_tmp_path.h b/gnuradio-core/src/lib/runtime/gr_tmp_path.h new file mode 100644 index 00000000..742ce056 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tmp_path.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_TMP_PATH_H_ +#define _GR_TMP_PATH_H_ + +/*! + * \brief return directory portion of pathname used for temporary files. + */ +const char *gr_tmp_path (); + +#endif /* _GR_TMP_PATH_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_types.h b/gnuradio-core/src/lib/runtime/gr_types.h new file mode 100644 index 00000000..370ca564 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_types.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_TYPES_H +#define INCLUDED_GR_TYPES_H + +#include +#include +#include // size_t + +#include + +typedef std::vector gr_vector_int; +typedef std::vector gr_vector_float; +typedef std::vector gr_vector_double; +typedef std::vector gr_vector_void_star; +typedef std::vector gr_vector_const_void_star; + +/* + * #include must be placed beforehand + * in the source file including gr_types.h for + * the following to work correctly + */ +#ifdef HAVE_STDINT_H +#include +typedef int16_t gr_int16; +typedef int32_t gr_int32; +typedef int64_t gr_int64; +typedef uint16_t gr_uint16; +typedef uint32_t gr_uint32; +typedef uint64_t gr_uint64; +#else +/* + * Note: these defaults may be wrong on 64-bit systems + */ +typedef short gr_int16; +typedef int gr_int32; +typedef long long gr_int64; +typedef unsigned short gr_uint16; +typedef unsigned int gr_uint32; +typedef unsigned long long gr_uint64; +#endif /* HAVE_STDINT_H */ + +#endif /* INCLUDED_GR_TYPES_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc new file mode 100644 index 00000000..3586c4c7 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc @@ -0,0 +1,291 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include + +// all the factories we know about +#include +#include +#include +#include + +static const char *FACTORY_PREF_KEY = "gr_vmcircbuf_default_factory"; + +gr_vmcircbuf::~gr_vmcircbuf () +{ +} + +gr_vmcircbuf_factory::~gr_vmcircbuf_factory () +{ +} + +// ---------------------------------------------------------------- + +static gr_vmcircbuf_factory *s_default_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_sysconfig::get_default_factory () +{ + if (s_default_factory) + return s_default_factory; + + bool verbose = false; + + std::vector all = all_factories (); + + const char *name = gr_preferences::get (FACTORY_PREF_KEY); + + if (name){ + for (unsigned int i = 0; i < all.size (); i++){ + if (strcmp (name, all[i]->name ()) == 0){ + s_default_factory = all[i]; + if (verbose) + fprintf (stderr, "gr_vmcircbuf_sysconfig: using %s\n", + s_default_factory->name ()); + return s_default_factory; + } + } + } + + // either we don't have a default, or the default named is not in our + // list of factories. Find the first factory that works. + + if (verbose) + fprintf (stderr, "gr_vmcircbuf_sysconfig: finding a working factory...\n"); + + for (unsigned int i = 0; i < all.size (); i++){ + if (test_factory (all[i], verbose)){ + set_default_factory (all[i]); + return s_default_factory; + } + } + + // We're screwed! + + fprintf (stderr, "gr_vmcircbuf_sysconfig: unable to find a working factory!\n"); + throw std::runtime_error ("gr_vmcircbuf_sysconfig"); +} + +std::vector +gr_vmcircbuf_sysconfig::all_factories () +{ + std::vector result; + + result.push_back (gr_vmcircbuf_createfilemapping_factory::singleton ()); + result.push_back (gr_vmcircbuf_sysv_shm_factory::singleton ()); + result.push_back (gr_vmcircbuf_mmap_shm_open_factory::singleton ()); + result.push_back (gr_vmcircbuf_mmap_tmpfile_factory::singleton ()); + + return result; +} + +void +gr_vmcircbuf_sysconfig::set_default_factory (gr_vmcircbuf_factory *f) +{ + gr_preferences::set (FACTORY_PREF_KEY, f->name ()); + s_default_factory = f; +} + + +// ------------------------------------------------------------------------ +// test code for vmcircbuf factories +// ------------------------------------------------------------------------ + +static void +init_buffer (gr_vmcircbuf *c, int counter, int size) +{ + unsigned int *p = (unsigned int *) c->pointer_to_first_copy (); + for (unsigned int i = 0; i < size / sizeof (int); i++) + p[i] = counter + i; +} + +static bool +check_mapping (gr_vmcircbuf *c, int counter, int size, char *msg, bool verbose) +{ + bool ok = true; + + if (verbose) + fprintf (stderr, "... %s", msg); + + unsigned int *p1 = (unsigned int *) c->pointer_to_first_copy (); + unsigned int *p2 = (unsigned int *) c->pointer_to_second_copy (); + + // fprintf (stderr, "p1 = %p, p2 = %p\n", p1, p2); + + for (unsigned int i = 0; i < size / sizeof (int); i++){ + if (p1[i] != counter + i){ + ok = false; + if (verbose) + fprintf (stderr, " p1[%d] == %u, expected %u\n", i, p1[i], counter + i); + break; + } + if (p2[i] != counter + i){ + if (verbose) + fprintf (stderr, " p2[%d] == %u, expected %u\n", i, p2[i], counter + i); + ok = false; + break; + } + } + + if (ok && verbose){ + fprintf (stderr, " OK\n"); + } + return ok; +} + +static char * +memsize (int size) +{ + static char buf[100]; + if (size >= (1 << 20)){ + snprintf (buf, sizeof (buf), "%dMB", size / (1 << 20)); + } + else if (size >= (1 << 10)){ + snprintf (buf, sizeof (buf), "%dKB", size / (1 << 10)); + } + else { + snprintf (buf, sizeof (buf), "%d", size); + } + return buf; +} + +static bool +test_a_bunch (gr_vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose) +{ + bool ok = true; + int counter[n]; + gr_vmcircbuf *c[n]; + int cum_size = 0; + + for (int i = 0; i < n; i++){ + counter[i] = *start_ptr; + *start_ptr += size; + if ((c[i] = factory->make (size)) == 0){ + if (verbose) + fprintf (stderr, + "Failed to allocate gr_vmcircbuf number %d of size %d (cum = %s)\n", + i + 1, size, memsize (cum_size)); + return false; + } + init_buffer (c[i], counter[i], size); + cum_size += size; + } + + for (int i = 0; i < n; i++){ + char msg[100]; + snprintf (msg, sizeof (msg), "test_a_bunch_%dx%s[%d]", n, memsize (size), i); + ok &= check_mapping (c[i], counter[i], size, msg, verbose); + } + + for (int i = 0; i < n; i++){ + delete c[i]; + c[i] = 0; + } + + return ok; +} + +static bool +standard_tests (gr_vmcircbuf_factory *f, int verbose) +{ + if (verbose >= 1) + fprintf (stderr, "Testing %s...\n", f->name ()); + + bool v = verbose >= 2; + int granularity = f->granularity (); + int start = 0; + bool ok = true; + + ok &= test_a_bunch (f, 1, 1 * granularity, &start, v); // 1 x 4KB = 4KB + + if (ok){ + ok &= test_a_bunch (f, 64, 4 * granularity, &start, v); // 256 x 16KB = 4MB + ok &= test_a_bunch (f, 32, 4 * (1L << 20), &start, v); // 32 x 4MB = 64MB + ok &= test_a_bunch (f, 256, 256 * (1L << 10), &start, v); // 256 x 256KB = 64MB + } + + if (verbose >= 1) + fprintf (stderr, "....... %s: %s", f->name (), ok ? "OK\n" : "Doesn't work\n"); + + return ok; +} + +bool +gr_vmcircbuf_sysconfig::test_factory (gr_vmcircbuf_factory *f, int verbose) +{ + // Install local signal handlers for SIGSEGV and SIGBUS. + // If something goes wrong, these signals may be invoked. + +#ifdef SIGSEGV + gr_local_sighandler sigsegv (SIGSEGV, gr_local_sighandler::throw_signal); +#endif +#ifdef SIGBUS + gr_local_sighandler sigbus (SIGBUS, gr_local_sighandler::throw_signal); +#endif +#ifdef SIGSYS + gr_local_sighandler sigsys (SIGSYS, gr_local_sighandler::throw_signal); +#endif + + try { + return standard_tests (f, verbose); + } + catch (gr_signal &sig){ + if (verbose){ + fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n"); + fprintf (stderr, + "gr_vmcircbuf_factory::test_factory (%s): caught %s\n", + f->name (), sig.name().c_str()); + return false; + } + } + catch (...){ + if (verbose){ + fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n"); + fprintf (stderr, + "gr_vmcircbuf_factory::test_factory (%s): some kind of uncaught exception\n", + f->name ()); + } + return false; + } + return false; // never gets here. shut compiler up. +} + +bool +gr_vmcircbuf_sysconfig::test_all_factories (int verbose) +{ + bool ok = false; + + std::vector all = all_factories (); + + for (unsigned int i = 0; i < all.size (); i++) + ok |= test_factory (all[i], verbose); + + return ok; +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h new file mode 100644 index 00000000..e2af9358 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_H_ +#define _GR_VMCIRCBUF_H_ + +#include + +/*! + * \brief abstract class to implement doubly mapped virtual memory circular buffers + */ +class gr_vmcircbuf { + protected: + int d_size; + char *d_base; + + // CREATORS + gr_vmcircbuf (int size) : d_size (size), d_base (0) {}; + + public: + virtual ~gr_vmcircbuf (); + + // ACCESSORS + void *pointer_to_first_copy () const { return d_base; } + void *pointer_to_second_copy () const { return d_base + d_size; } +}; + +/*! + * \brief abstract factory for creating circular buffers + */ +class gr_vmcircbuf_factory { + protected: + gr_vmcircbuf_factory () {}; + virtual ~gr_vmcircbuf_factory (); + + public: + + /*! + * \brief return name of this factory + */ + virtual const char *name () const = 0; + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity () = 0; + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size) = 0; +}; + +/* + * \brief pulls together all implementations of gr_vmcircbuf + */ +class gr_vmcircbuf_sysconfig { + public: + + /* + * \brief return the single instance of the default factory. + * + * returns the default factory to use if it's already defined, + * else find the first working factory and use it. + */ + static gr_vmcircbuf_factory *get_default_factory (); + + + static int granularity () { return get_default_factory()->granularity(); } + static gr_vmcircbuf *make (int size) { return get_default_factory()->make(size); } + + + // N.B. not all factories are guaranteed to work. + // It's too hard to check everything at config time, so we check at runtime + static std::vector all_factories (); + + // make this factory the default + static void set_default_factory (gr_vmcircbuf_factory *f); + + /*! + * \brief Does this factory really work? + * + * verbose = 0: silent + * verbose = 1: names of factories tested and results + * verbose = 2: all intermediate results + */ + static bool test_factory (gr_vmcircbuf_factory *f, int verbose); + + /*! + * \brief Test all factories, return true if at least one of them works + * verbose = 0: silent + * verbose = 1: names of factories tested and results + * verbose = 2: all intermediate results + */ + static bool test_all_factories (int verbose); +}; + + +#endif /* _GR_VMCIRCBUF_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc new file mode 100644 index 00000000..8f3540b4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc @@ -0,0 +1,191 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include +#include + + +gr_vmcircbuf_createfilemapping::gr_vmcircbuf_createfilemapping (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_CREATEFILEMAPPING) + fprintf (stderr, "%s: createfilemapping is not available\n",__FUNCTION__); + throw std::runtime_error ("gr_vmcircbuf_createfilemapping"); +#else + static int s_seg_counter = 0; + + if (size <= 0 || (size % gr_pagesize ()) != 0){ + fprintf (stderr, "gr_vmcircbuf_createfilemapping: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_createfilemapping"); + } + + char seg_name[1024]; + snprintf (seg_name, sizeof (seg_name), "/gnuradio-%d-%d", getpid (), s_seg_counter); + + d_handle = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + size, // buffer size + seg_name); // name of mapping object + + s_seg_counter++; + if (d_handle == NULL || d_handle == INVALID_HANDLE_VALUE){ + char msg[1024]; + snprintf (msg, sizeof (msg), "gr_vmcircbuf_mmap_createfilemapping: CreateFileMapping [%s] :%d", seg_name,(int)GetLastError()); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + int i = 0; + d_first_copy = d_second_copy = NULL; + + while (i++ < 8 && d_second_copy == NULL){ + // keep the first map allocation to force allocation in a new address + // space + LPVOID first_tmp = d_first_copy; + + d_first_copy = MapViewOfFile((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size); + + if (d_first_copy == NULL){ + if (first_tmp) + UnmapViewOfFile(first_tmp); + + CloseHandle(d_handle); // cleanup + char msg[1024]; + snprintf (msg, sizeof (msg), + "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFile (1) :%d", (int)GetLastError()); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + // NOTE: d_second_copy will be NULL if MapViewFileEx() fails to allocate the + // requested address space + d_second_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size, + (char *)d_first_copy + size);//(LPVOID) ((char *)d_first_copy + size)); + + if (first_tmp) + UnmapViewOfFile(first_tmp); + +#ifdef DEBUG + fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: contiguous? mmap %p %p %p %p, %d\n", + (char *)d_first_copy, (char *)d_second_copy, size, (char *)d_first_copy + size,i); +#endif + } + + if (d_second_copy == NULL){ // cleanup + fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: non contiguous mmap - %p %p %p %p\n", + d_first_copy, d_second_copy, size, (char *)d_first_copy + size); + UnmapViewOfFile(d_first_copy); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + // Now remember the important stuff + d_base = (char *) d_first_copy; + d_size = size; +#endif /*HAVE_CREATEFILEMAPPING*/ +} + +gr_vmcircbuf_createfilemapping::~gr_vmcircbuf_createfilemapping () +{ +#ifdef HAVE_CREATEFILEMAPPING + if (UnmapViewOfFile(d_first_copy) == 0) + { + perror ("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_first_copy)"); + } + d_base=NULL; + if (UnmapViewOfFile(d_second_copy) == 0) + { + perror ("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_second_copy)"); + } + //d_second=NULL; + CloseHandle(d_handle); +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_createfilemapping_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_createfilemapping_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + s_the_factory = new gr_vmcircbuf_createfilemapping_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_createfilemapping_factory::granularity () +{ +#ifdef HAVE_CREATEFILEMAPPING + // return 65536;//TODO, check, is this needed or can we just use gr_pagesize() + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + //fprintf(stderr,"win32 AllocationGranularity %p\n",(int)system_info.dwAllocationGranularity); + return (int)system_info.dwAllocationGranularity; +#else + return gr_pagesize (); +#endif +} + +gr_vmcircbuf * +gr_vmcircbuf_createfilemapping_factory::make (int size) +{ + try + { + return new gr_vmcircbuf_createfilemapping (size); + } + catch (...) + { + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h new file mode 100644 index 00000000..f7113cf4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ +#define _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ + +#include + +#ifdef HAVE_CREATEFILEMAPPING +#include +#endif +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class gr_vmcircbuf_createfilemapping : public gr_vmcircbuf +{ + public: + // CREATORS + gr_vmcircbuf_createfilemapping (int size); + virtual ~gr_vmcircbuf_createfilemapping (); +#ifdef HAVE_CREATEFILEMAPPING + private: + HANDLE d_handle; + LPVOID d_first_copy; + LPVOID d_second_copy; +#endif +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class gr_vmcircbuf_createfilemapping_factory : public gr_vmcircbuf_factory +{ + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_createfilemapping_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc new file mode 100644 index 00000000..65fa1183 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc @@ -0,0 +1,205 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include + + +gr_vmcircbuf_mmap_shm_open::gr_vmcircbuf_mmap_shm_open (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_MMAP) || !defined(HAVE_SHM_OPEN) + fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: mmap or shm_open is not available\n"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); +#else + static int s_seg_counter = 0; + + if (size <= 0 || (size % gr_pagesize ()) != 0){ + fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + int shm_fd = -1; + char seg_name[1024]; + static bool portable_format = true; + + // open a new named shared memory segment + + while (1){ + if (portable_format){ + + // This is the POSIX recommended "portable format". + // Of course the "portable format" doesn't work on some systems... + + snprintf (seg_name, sizeof (seg_name), + "/gnuradio-%d-%d", getpid (), s_seg_counter); + } + else { + + // Where the "portable format" doesn't work, we try building + // a full filesystem pathname pointing into a suitable temporary directory. + + snprintf (seg_name, sizeof (seg_name), + "%s/gnuradio-%d-%d", gr_tmp_path (), getpid (), s_seg_counter); + } + + shm_fd = shm_open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (shm_fd == -1 && errno == EACCES && portable_format){ + portable_format = false; + continue; // try again using "non-portable format" + } + + s_seg_counter++; + + if (shm_fd == -1){ + if (errno == EEXIST) // Named segment already exists (shouldn't happen). Try again + continue; + + char msg[1024]; + snprintf (msg, sizeof (msg), "gr_vmcircbuf_mmap_shm_open: shm_open [%s]", seg_name); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + break; + } + + // We've got a new shared memory segment fd open. + // Now set it's length to 2x what we really want and mmap it in. + + if (ftruncate (shm_fd, (off_t) 2 * size) == -1){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + void *first_copy = mmap (0, 2 * size, + PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, (off_t) 0); + + if (first_copy == MAP_FAILED){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: mmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + // unmap the 2nd half + if (munmap ((char *) first_copy + size, size) == -1){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: munmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + // map the first half into the now available hole where the + // second half used to be. + + void *second_copy = mmap ((char *) first_copy + size, size, + PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, (off_t) 0); + + if (second_copy == MAP_FAILED){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: mmap (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + +#if 0 // OS/X doesn't allow you to resize the segment + + // cut the shared memory segment down to size + if (ftruncate (shm_fd, (off_t) size) == -1){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } +#endif + + close (shm_fd); // fd no longer needed. The mapping is retained. + + if (shm_unlink (seg_name) == -1){ // unlink the seg_name. + perror ("gr_vmcircbuf_mmap_shm_open: shm_unlink"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + // Now remember the important stuff + + d_base = (char *) first_copy; + d_size = size; +#endif +} + +gr_vmcircbuf_mmap_shm_open::~gr_vmcircbuf_mmap_shm_open () +{ +#if defined(HAVE_MMAP) + if (munmap (d_base, 2 * d_size) == -1){ + perror ("gr_vmcircbuf_mmap_shm_open: munmap (2)"); + } +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_mmap_shm_open_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_mmap_shm_open_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + + s_the_factory = new gr_vmcircbuf_mmap_shm_open_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_mmap_shm_open_factory::granularity () +{ + return gr_pagesize (); +} + +gr_vmcircbuf * +gr_vmcircbuf_mmap_shm_open_factory::make (int size) +{ + try { + return new gr_vmcircbuf_mmap_shm_open (size); + } + catch (...){ + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h new file mode 100644 index 00000000..4b1feaff --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ +#define _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ + +#include + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class gr_vmcircbuf_mmap_shm_open : public gr_vmcircbuf { + public: + + // CREATORS + + gr_vmcircbuf_mmap_shm_open (int size); + virtual ~gr_vmcircbuf_mmap_shm_open (); +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class gr_vmcircbuf_mmap_shm_open_factory : public gr_vmcircbuf_factory { + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_mmap_shm_open_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc new file mode 100644 index 00000000..a07df779 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc @@ -0,0 +1,198 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include +#include +#include + + +gr_vmcircbuf_mmap_tmpfile::gr_vmcircbuf_mmap_tmpfile (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_MMAP) + fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: mmap or mkstemp is not available\n"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); +#else + + if (size <= 0 || (size % gr_pagesize ()) != 0){ + fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + int seg_fd = -1; + char seg_name[1024]; + + static int s_seg_counter = 0; + + + // open a temporary file that we'll map in a bit later + + while (1){ + snprintf (seg_name, sizeof (seg_name), + "%s/gnuradio-%d-%d-XXXXXX", gr_tmp_path (), getpid (), s_seg_counter); + s_seg_counter++; + + seg_fd = open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (seg_fd == -1){ + if (errno == EEXIST) // File already exists (shouldn't happen). Try again + continue; + + char msg[1024]; + snprintf (msg, sizeof (msg), + "gr_vmcircbuf_mmap_tmpfile: open [%s]", seg_name); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + break; + } + + if (unlink (seg_name) == -1){ + perror ("gr_vmcircbuf_mmap_tmpfile: unlink"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // We've got a valid file descriptor to a tmp file. + // Now set it's length to 2x what we really want and mmap it in. + + if (ftruncate (seg_fd, (off_t) 2 * size) == -1){ + close (seg_fd); // cleanup + perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + void *first_copy = mmap (0, 2 * size, + PROT_READ | PROT_WRITE, MAP_SHARED, + seg_fd, (off_t) 0); + + if (first_copy == MAP_FAILED){ + close (seg_fd); // cleanup + perror ("gr_vmcircbuf_mmap_tmpfile: mmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // unmap the 2nd half + if (munmap ((char *) first_copy + size, size) == -1){ + close (seg_fd); // cleanup + perror ("gr_vmcircbuf_mmap_tmpfile: munmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // map the first half into the now available hole where the + // second half used to be. + + void *second_copy = mmap ((char *) first_copy + size, size, + PROT_READ | PROT_WRITE, MAP_SHARED, + seg_fd, (off_t) 0); + + if (second_copy == MAP_FAILED){ + munmap(first_copy, size); // cleanup + close (seg_fd); + perror ("gr_vmcircbuf_mmap_tmpfile: mmap (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // check for contiguity + if ((char *) second_copy != (char *) first_copy + size){ + munmap(first_copy, size); // cleanup + munmap(second_copy, size); + close (seg_fd); + perror ("gr_vmcircbuf_mmap_tmpfile: non-contiguous second copy"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // cut the tmp file down to size + if (ftruncate (seg_fd, (off_t) size) == -1){ + munmap(first_copy, size); // cleanup + munmap(second_copy, size); + close (seg_fd); + perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + close (seg_fd); // fd no longer needed. The mapping is retained. + + // Now remember the important stuff + + d_base = (char *) first_copy; + d_size = size; +#endif +} + +gr_vmcircbuf_mmap_tmpfile::~gr_vmcircbuf_mmap_tmpfile () +{ +#if defined(HAVE_MMAP) + if (munmap (d_base, 2 * d_size) == -1){ + perror ("gr_vmcircbuf_mmap_tmpfile: munmap (2)"); + } +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_mmap_tmpfile_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_mmap_tmpfile_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + + s_the_factory = new gr_vmcircbuf_mmap_tmpfile_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_mmap_tmpfile_factory::granularity () +{ + return gr_pagesize (); +} + +gr_vmcircbuf * +gr_vmcircbuf_mmap_tmpfile_factory::make (int size) +{ + try { + return new gr_vmcircbuf_mmap_tmpfile (size); + } + catch (...){ + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h new file mode 100644 index 00000000..3b9f5dba --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_MMAP_TMPFILE_H_ +#define _GR_VMCIRCBUF_MMAP_TMPFILE_H_ + +#include + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class gr_vmcircbuf_mmap_tmpfile : public gr_vmcircbuf { + public: + + // CREATORS + + gr_vmcircbuf_mmap_tmpfile (int size); + virtual ~gr_vmcircbuf_mmap_tmpfile (); +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class gr_vmcircbuf_mmap_tmpfile_factory : public gr_vmcircbuf_factory { + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_mmap_tmpfile_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_MMAP_TMPFILE_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc new file mode 100644 index 00000000..4b6fcfe3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc @@ -0,0 +1,192 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_IPC_H +#include +#endif +#ifdef HAVE_SYS_SHM_H +#include +#endif +#include +#include +#include + + +gr_vmcircbuf_sysv_shm::gr_vmcircbuf_sysv_shm (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_SYS_SHM_H) + fprintf (stderr, "gr_vmcircbuf_sysv_shm: sysv shared memory is not available\n"); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); +#else + + int pagesize = gr_pagesize(); + + if (size <= 0 || (size % pagesize) != 0){ + fprintf (stderr, "gr_vmcircbuf_sysv_shm: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + int shmid_guard = -1; + int shmid1 = -1; + int shmid2 = -1; + + // We use this as a guard page. We'll map it read-only on both ends of the buffer. + // Ideally we'd map it no access, but I don't think that's possible with SysV + if ((shmid_guard = shmget (IPC_PRIVATE, pagesize, IPC_CREAT | 0400)) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmget (0)"); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + if ((shmid2 = shmget (IPC_PRIVATE, 2 * size + 2 * pagesize, IPC_CREAT | 0700)) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmget (1)"); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + if ((shmid1 = shmget (IPC_PRIVATE, size, IPC_CREAT | 0700)) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmget (2)"); + shmctl (shmid2, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + void *first_copy = shmat (shmid2, 0, 0); + if (first_copy == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (1)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid2, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + shmctl (shmid2, IPC_RMID, 0); + + // There may be a race between our detach and attach. + // + // If the system allocates all shared memory segments at the same + // virtual addresses in all processes and if the system allocates + // some other segment to first_copy or first_copoy + size between + // our detach and attach, the attaches below could fail [I've never + // seen it fail for this reason]. + + shmdt (first_copy); + + // first read-only guard page + if (shmat (shmid_guard, first_copy, SHM_RDONLY) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (2)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + // first copy + if (shmat (shmid1, (char *) first_copy + pagesize, 0) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (3)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + shmdt (first_copy); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + // second copy + if (shmat (shmid1, (char *) first_copy + pagesize + size, 0) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (4)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + shmdt ((char *)first_copy + pagesize); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + // second read-only guard page + if (shmat (shmid_guard, (char *) first_copy + pagesize + 2 * size, SHM_RDONLY) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (5)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + shmdt (first_copy); + shmdt ((char *)first_copy + pagesize); + shmdt ((char *)first_copy + pagesize + size); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + shmctl (shmid1, IPC_RMID, 0); + shmctl (shmid_guard, IPC_RMID, 0); + + // Now remember the important stuff + + d_base = (char *) first_copy + pagesize; + d_size = size; +#endif +} + +gr_vmcircbuf_sysv_shm::~gr_vmcircbuf_sysv_shm () +{ +#if defined(HAVE_SYS_SHM_H) + if (shmdt (d_base - gr_pagesize()) == -1 + || shmdt (d_base) == -1 + || shmdt (d_base + d_size) == -1 + || shmdt (d_base + 2 * d_size) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmdt (2)"); + } +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_sysv_shm_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_sysv_shm_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + + s_the_factory = new gr_vmcircbuf_sysv_shm_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_sysv_shm_factory::granularity () +{ + return gr_pagesize (); +} + +gr_vmcircbuf * +gr_vmcircbuf_sysv_shm_factory::make (int size) +{ + try { + return new gr_vmcircbuf_sysv_shm (size); + } + catch (...){ + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h new file mode 100644 index 00000000..9a8c128a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_SYSV_SHM_H_ +#define _GR_VMCIRCBUF_SYSV_SHM_H_ + +#include + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class gr_vmcircbuf_sysv_shm : public gr_vmcircbuf { + public: + + // CREATORS + + gr_vmcircbuf_sysv_shm (int size); + virtual ~gr_vmcircbuf_sysv_shm (); +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class gr_vmcircbuf_sysv_shm_factory : public gr_vmcircbuf_factory { + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_sysv_shm_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_SYSV_SHM_H_ */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_block.cc new file mode 100644 index 00000000..e3a21be3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.cc @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + + +// ---------------------------------------------------------------- + + +void +qa_gr_block::t0 () +{ + // test creation of sources + gr_block_sptr src1 (gr_make_null_source (sizeof (int))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_source"), src1->name ()); + CPPUNIT_ASSERT_EQUAL (0, src1->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src1->output_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src1->output_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (sizeof (int), + src1->output_signature()->sizeof_stream_item (0)); + + gr_block_sptr src2 (gr_make_null_source (sizeof (short))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_source"), src2->name ()); + CPPUNIT_ASSERT_EQUAL (0, src2->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src2->output_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src2->output_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (sizeof (short), + src2->output_signature()->sizeof_stream_item (0)); +} + + +void +qa_gr_block::t1 () +{ + // test creation of sinks + gr_block_sptr dst1 (gr_make_null_sink (sizeof (int))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_sink"), dst1->name ()); + CPPUNIT_ASSERT_EQUAL (1, dst1->input_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, dst1->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (sizeof (int), + dst1->input_signature()->sizeof_stream_item (0)); + + CPPUNIT_ASSERT_EQUAL (0, dst1->output_signature()->max_streams ()); + + gr_block_sptr dst2 (gr_make_null_sink (sizeof (short))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_sink"), dst2->name ()); + CPPUNIT_ASSERT_EQUAL (1, dst2->input_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, dst2->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (sizeof (short), + dst2->input_signature()->sizeof_stream_item (0)); + CPPUNIT_ASSERT_EQUAL (0, dst2->output_signature()->max_streams ()); +} + +void +qa_gr_block::t2 () +{ +} + +void +qa_gr_block::t3 () +{ +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_block.h b/gnuradio-core/src/lib/runtime/qa_gr_block.h new file mode 100644 index 00000000..6e308251 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_QA_GR_BLOCK_H +#define INCLUDED_QA_GR_BLOCK_H + +#include +#include +#include + +class qa_gr_block : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_block); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* INCLUDED_QA_GR_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_buffer.cc b/gnuradio-core/src/lib/runtime/qa_gr_buffer.cc new file mode 100644 index 00000000..5c549d0b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_buffer.cc @@ -0,0 +1,307 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +static void +leak_check (void f ()) +{ + long buffer_count = gr_buffer_ncurrently_allocated (); + long buffer_reader_count = gr_buffer_reader_ncurrently_allocated (); + + f (); + + CPPUNIT_ASSERT_EQUAL (buffer_reader_count, gr_buffer_reader_ncurrently_allocated ()); + CPPUNIT_ASSERT_EQUAL (buffer_count, gr_buffer_ncurrently_allocated ()); +} + + +// ---------------------------------------------------------------------------- +// test single writer, no readers... +// + +static void +t0_body () +{ + int nitems = 4000 / sizeof (int); + int counter = 0; + + gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int))); + + int last_sa; + int sa; + + sa = buf->space_available (); + CPPUNIT_ASSERT (sa > 0); + last_sa = sa; + + for (int i = 0; i < 5; i++){ + sa = buf->space_available (); + CPPUNIT_ASSERT_EQUAL (last_sa, sa); + last_sa = sa; + + int *p = (int *) buf->write_pointer (); + CPPUNIT_ASSERT (p != 0); + + for (int j = 0; j < sa; j++) + *p++ = counter++; + + buf->update_write_pointer (sa); + } +} + +// ---------------------------------------------------------------------------- +// test single writer, single reader +// + +static void +t1_body () + { + int nitems = 4000 / sizeof (int); + int write_counter = 0; + int read_counter = 0; + + gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int))); + gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 1)); + + + int sa; + + // write 1/3 of buffer + + sa = buf->space_available (); + CPPUNIT_ASSERT (sa > 0); + + int *p = (int *) buf->write_pointer (); + CPPUNIT_ASSERT (p != 0); + + for (int j = 0; j < sa/3; j++){ + *p++ = write_counter++; + } + buf->update_write_pointer (sa/3); + + + // write the next 1/3 (1/2 of what's left) + + sa = buf->space_available (); + CPPUNIT_ASSERT (sa > 0); + + p = (int *) buf->write_pointer (); + CPPUNIT_ASSERT (p != 0); + + for (int j = 0; j < sa/2; j++){ + *p++ = write_counter++; + } + buf->update_write_pointer (sa/2); + + + // check that we can read it OK + + int ia = r1->items_available (); + CPPUNIT_ASSERT_EQUAL (write_counter, ia); + + int *rp = (int *) r1->read_pointer (); + CPPUNIT_ASSERT (rp != 0); + + for (int i = 0; i < ia/2; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (ia/2); + + // read the rest + + ia = r1->items_available (); + rp = (int *) r1->read_pointer (); + CPPUNIT_ASSERT (rp != 0); + + for (int i = 0; i < ia; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (ia); +} + +// ---------------------------------------------------------------------------- +// single writer, single reader: check wrap-around +// + +static void +t2_body () +{ + // 64K is the largest granularity we've seen so far (MS windows file mapping). + // This allows a bit of "white box testing" + + int nitems = (64 * (1L << 10)) / sizeof (int); // 64K worth of ints + + gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int))); + gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 1)); + + int read_counter = 0; + int write_counter = 0; + int n; + int *wp = 0; + int *rp = 0; + + // Write 3/4 of buffer + + n = (int) (buf->space_available () * 0.75); + wp = (int *) buf->write_pointer (); + + for (int i = 0; i < n; i++) + *wp++ = write_counter++; + buf->update_write_pointer (n); + + // Now read it all + + int m = r1->items_available (); + CPPUNIT_ASSERT_EQUAL (n, m); + rp = (int *) r1->read_pointer (); + + for (int i = 0; i < m; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (m); + + // Now write as much as we can. + // This will wrap around the buffer + + n = buf->space_available (); + CPPUNIT_ASSERT_EQUAL (nitems - 1, n); // white box test + wp = (int *) buf->write_pointer (); + + for (int i = 0; i < n; i++) + *wp++ = write_counter++; + buf->update_write_pointer (n); + + // now read it all + + m = r1->items_available (); + CPPUNIT_ASSERT_EQUAL (n, m); + rp = (int *) r1->read_pointer (); + + for (int i = 0; i < m; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (m); + +} + +// ---------------------------------------------------------------------------- +// single writer, N readers, randomized order and lengths +// ---------------------------------------------------------------------------- + +static void +t3_body () +{ + int nitems = (64 * (1L << 10)) / sizeof (int); + + static const int N = 5; + gr_buffer_sptr buf (gr_make_buffer (nitems, sizeof (int))); + gr_buffer_reader_sptr reader[N]; + int read_counter[N]; + int write_counter = 0; + gr_random random; + + for (int i = 0; i < N; i++){ + read_counter[i] = 0; + reader[i] = gr_buffer_add_reader (buf, 1); + } + + for (int lc = 0; lc < 1000; lc++){ + + // write some + + int n = (int) (buf->space_available () * random.ran1 ()); + int *wp = (int *) buf->write_pointer (); + + for (int i = 0; i < n; i++) + *wp++ = write_counter++; + + buf->update_write_pointer (n); + + // pick a random reader and read some + + int r = (int) (N * random.ran1 ()); + CPPUNIT_ASSERT (0 <= r && r < N); + + int m = reader[r]->items_available (); + int *rp = (int *) reader[r]->read_pointer (); + + for (int i = 0; i < m; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter[r], *rp); + read_counter[r]++; + rp++; + } + reader[r]->update_read_pointer (m); + } +} + + +// ---------------------------------------------------------------------------- + +void +qa_gr_buffer::t0 () +{ + leak_check (t0_body); +} + +void +qa_gr_buffer::t1 () +{ + leak_check (t1_body); +} + +void +qa_gr_buffer::t2 () +{ + leak_check (t2_body); +} + +void +qa_gr_buffer::t3 () +{ + leak_check (t3_body); +} + +void +qa_gr_buffer::t4 () +{ +} + +void +qa_gr_buffer::t5 () +{ +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_buffer.h b/gnuradio-core/src/lib/runtime/qa_gr_buffer.h new file mode 100644 index 00000000..700629cc --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_buffer.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_QA_GR_BUFFER_H +#define INCLUDED_QA_GR_BUFFER_H + +#include +#include + +class qa_gr_buffer : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_buffer); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST_SUITE_END (); + + + private: + + void t0 (); + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); +}; + + + +#endif /* INCLUDED_QA_GR_BUFFER_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc new file mode 100644 index 00000000..c180e7b7 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +void +qa_gr_io_signature::t0 () +{ + gr_make_io_signature (1, 1, sizeof (int)); +} + +void +qa_gr_io_signature::t1 () +{ + gr_make_io_signature (3, 1, sizeof (int)); // throws std::invalid_argument +} + +void +qa_gr_io_signature::t2 () +{ + gr_io_signature_sptr p = + gr_make_io_signature (3, gr_io_signature::IO_INFINITE, sizeof (int)); + + CPPUNIT_ASSERT_EQUAL (p->min_streams (), 3); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item (0), sizeof (int)); +} + +void +qa_gr_io_signature::t3 () +{ +} + diff --git a/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h new file mode 100644 index 00000000..225ce806 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_QA_GR_IO_SIGNATURE_H +#define INCLUDED_QA_GR_IO_SIGNATURE_H + +#include +#include +#include + +class qa_gr_io_signature : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_io_signature); + CPPUNIT_TEST (t0); + CPPUNIT_TEST_EXCEPTION (t1, std::invalid_argument); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_IO_SIGNATURE_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc new file mode 100644 index 00000000..f3c815a0 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +void +qa_gr_vmcircbuf::test_all () +{ + int verbose = 1; // summary + + bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose); + + CPPUNIT_ASSERT_EQUAL (true, ok); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h new file mode 100644 index 00000000..41f69c35 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_GR_VMCIRCBUF_H_ +#define _QA_GR_VMCIRCBUF_H_ + +#include +#include + +class qa_gr_vmcircbuf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_vmcircbuf); + CPPUNIT_TEST (test_all); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_all (); +}; + + +#endif /* _QA_GR_VMCIRCBUF_H_ */ diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc new file mode 100644 index 00000000..668628f2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc @@ -0,0 +1,49 @@ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +CppUnit::TestSuite * +qa_runtime::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("runtime"); + + s->addTest (qa_gr_vmcircbuf::suite ()); + s->addTest (qa_gr_io_signature::suite ()); + s->addTest (qa_gr_block::suite ()); + s->addTest (qa_gr_buffer::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.h b/gnuradio-core/src/lib/runtime/qa_runtime.h new file mode 100644 index 00000000..5862b1ea --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_runtime.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_RUNTIME_H_ +#define _QA_RUNTIME_H_ + +#include + +//! collect all the tests for the runtime directory + +class qa_runtime { + public: + //! return suite of tests for all of runtime directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_RUNTIME_H_ */ diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i new file mode 100644 index 00000000..d8dd34f1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include diff --git a/gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc b/gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc new file mode 100644 index 00000000..26bfa6d2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +gr_block_sptr +foo (gr_vector_source_i_sptr s) +{ + return gr_block_sptr (s); +} + +typedef gr_shared_block_sptr gr_vector_source_i_ptrX; +//typedef boost::shared_ptr gr_vector_source_i_ptrX; + +gr_vector_source_i_ptrX +bar (gr_vector_source_i *s) +{ + return gr_vector_source_i_ptrX (s); +} + +gr_block_sptr +baz_1 (gr_vector_source_i_ptrX s) +{ + return gr_block_sptr (s); +} + +#if 0 +gr_block_sptr +baz_2 (gr_vector_source_i_ptrX s) +{ + return s.block_sptr (); +} +#endif diff --git a/gnuradio-core/src/lib/swig/Makefile.am b/gnuradio-core/src/lib/swig/Makefile.am new file mode 100644 index 00000000..77bd0308 --- /dev/null +++ b/gnuradio-core/src/lib/swig/Makefile.am @@ -0,0 +1,111 @@ +# +# Copyright 2001,2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff in the gr subdirectory of the python pkg dir. +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/gr + +grgrpythondir = $(grpythondir)/gr +grgrlibdir = $(grpyexecdir)/gr + + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) -I$(srcdir) + + +EXTRA_DIST = gen-swig-bug-fix + + +LOCAL_IFILES = \ + gnuradio.i \ + shared_ptr.i + +ALL_IFILES = \ + $(LOCAL_IFILES) + + +BUILT_SOURCES = \ + gnuradio_swig_python.cc \ + gnuradio_swig_python.py \ + gnuradio_swig_python.h \ + gnuradio_swig_bug_workaround.h + +grgrpython_PYTHON = \ + gnuradio_swig_python.py + + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(INCLUDES) + + +# ---------------------------------------------------------------- +# _gnuradio_swig_python contains all the glue that implements +# the gnuradio.gr python package + +grgrlib_LTLIBRARIES = \ + _gnuradio_swig_python.la + +_gnuradio_swig_python_la_SOURCES = \ + gnuradio_swig_python.cc + + +_gnuradio_swig_python_la_LIBADD = \ + $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core.la \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +_gnuradio_swig_python_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) + + +# KLUDGE: Force runtime include of gnuradio_swig_python.d dependency file. +# This is not guaranteed to be portable, but will probably work. +# If it works, we have accurate dependencies for our swig stuff, which is good. +@am__include@ @am__quote@./gnuradio_swig_python.d@am__quote@ + +gnuradio_swig_python.cc gnuradio_swig_python.py gnuradio_swig_python.h : gnuradio.i + if $(SWIG) $(SWIGPYTHONARGS) -MMD -MF gnuradio_swig_python.Td -module gnuradio_swig_python -o gnuradio_swig_python.cc $< ;\ + then if test $(host_os) = mingw32; \ + then sed 's,\\\\,/,g' gnuradio_swig_python.d; rm -f gnuradio_swig_python.Td; \ + else mv -f gnuradio_swig_python.Td gnuradio_swig_python.d; fi \ + else rm -f gnuradio_swig_python.Td; exit 1; fi + +gnuradio_swig_bug_workaround.h : gnuradio_swig_python.cc $(srcdir)/gen-swig-bug-fix + $(srcdir)/gen-swig-bug-fix $< $@ + + +# ---------------------------------------------------------------- + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done + + +grinclude_HEADERS = \ + gnuradio_swig_bug_workaround.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc + +DISTCLEANFILES = gnuradio_swig_python.d diff --git a/gnuradio-core/src/lib/swig/atsc.i b/gnuradio-core/src/lib/swig/atsc.i new file mode 100644 index 00000000..4e8bf48f --- /dev/null +++ b/gnuradio-core/src/lib/swig/atsc.i @@ -0,0 +1,136 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +%} + +// from atsc_types.h +class plinfo; +class atsc_mpeg_packet; +class atsc_mpeg_packet_no_sync; +class atsc_mpeg_packet_rs_encoded; +class atsc_data_segment; +class atsc_soft_data_segment; + +%include + + +// leave out the VrHistoryProc and pretend we're directly derived from VrSigProc + +// %template(VrHistoryProc_1) VrHistoryProc; + +class GrAtscRandomizer : public VrSigProc +// class GrAtscRandomizer : public VrHistoryProc +{ +public: + GrAtscRandomizer (); + ~GrAtscRandomizer (); +}; + +class GrAtscRSEncoder : public VrSigProc +{ +public: + GrAtscRSEncoder (); + ~GrAtscRSEncoder (); +}; + +class GrAtscInterleaver : public VrSigProc +{ +public: + GrAtscInterleaver (); + ~GrAtscInterleaver (); +}; + +class GrAtscTrellisEncoder : public VrSigProc +{ +public: + GrAtscTrellisEncoder (); + ~GrAtscTrellisEncoder (); +}; + +class GrAtscFieldSyncMux : public VrSigProc +{ +public: + GrAtscFieldSyncMux (); + ~GrAtscFieldSyncMux (); +}; + +template +class GrAtscSymbolMapper : public VrSigProc +{ +public: + GrAtscSymbolMapper (); + ~GrAtscSymbolMapper (); +}; + +%template(GrAtscSymbolMapperF) GrAtscSymbolMapper; + +template +class GrWeaverModHead : public VrSigProc +{ +public: + GrWeaverModHead (int interp_factor); + ~GrWeaverModHead (); +}; + +%template(GrWeaverModHeadFF) GrWeaverModHead; + +template +class GrWeaverModTail : public VrSigProc { +public: + GrWeaverModTail (float freq, float gain); + ~GrWeaverModTail (); + + //! frequency is in Hz + void set_freq (float frequency); + void set_gain (float g); +}; + +%template(GrWeaverModTailFS) GrWeaverModTail; + +class GrAtscConvert2xTo20 : public VrSigProc +{ +public: + GrAtscConvert2xTo20 (); + ~GrAtscConvert2xTo20 (); +}; + + +#if 0 // FIXME +%template(VrSource_mpeg_packet) VrSource; +%template(VrFileSource_mpeg_packet) VrFileSource; + +%template(VrSink_mpeg_packet) VrSink; +%template(VrFileSink_mpeg_packet) VrFileSink; +#endif diff --git a/gnuradio-core/src/lib/swig/gen-swig-bug-fix b/gnuradio-core/src/lib/swig/gen-swig-bug-fix new file mode 100755 index 00000000..36332cc5 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gen-swig-bug-fix @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import sys +import re + +def write_header (f): + f.write ('''/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H +#define INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H + +/* + * This include files works around a bug in SWIG 1.3.21 and 22 + * where it fails to emit these declarations when doing + * %import "gnuradio.i" + */ + +''') + +def write_trailer (f): + f.write (''' +#endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */ +''') + +def doit (input, output): + re_RULES_BEGIN = re.compile ('RULES \(BEGIN\)') + re_RULES_END = re.compile ('RULES \(END\)') + re_RETURN = re.compile ('^\s*return') + re_NOT_ID = re.compile ('[^a-zA-Z0-9_]') + words = {} + + write_header (output) + for line in input: + if re_RULES_BEGIN.search (line): + break + + for line in input: + if re_RULES_END.search (line): + break + if not re_RETURN.match (line): + continue + line = re_NOT_ID.sub (' ', line) + line = re.sub (' +', ' ', line) + for w in line.split (' '): + words[w] = 1 + + for w in ('', 'return', 'void', 'x'): + del words[w] + + wl = words.keys() + wl.sort () + for w in wl: + output.write ('class ' + w + ';\n') + + write_trailer (output) + + +def main (): + if len (sys.argv) != 3: + sys.stderr.write ("usage: %s gnuradio_swig_python.cc gnuradio_swig_bug_workaround.h\n" + % (sys.argv[0],)) + sys.exit (1) + input_filename = sys.argv[1] + output_filename = sys.argv[2] + input = open (input_filename, "r") + output = open (output_filename, "w") + doit (input, output) + +if __name__ == '__main__': + main () + diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i new file mode 100644 index 00000000..b8c58538 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio.i @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +//////////////////////////////////////////////////////////////////////// +// gnuradio.i +// SWIG interface definition +//////////////////////////////////////////////////////////////////////// + + +#ifndef SWIGIMPORTED +// we set the module name on the command line (not any more) +%module(directors="1") gnuradio_swig_python +#endif + +//////////////////////////////////////////////////////////////////////// +// Headers + + +%{ +#include +#include // size_t +%} + +%feature("autodoc","1"); + +%include +%include +%include + + +typedef std::complex gr_complex; +typedef std::complex gr_complexd; + + +// instantiate the required template specializations + +namespace std { + %template() vector; + %template() vector; + %template() vector; + %template() vector; + %template() vector; + %template() vector; + %template() vector >; +}; + +//////////////////////////////////////////////////////////////////////// + +%constant int sizeof_char = sizeof(char); +%constant int sizeof_short = sizeof(short); +%constant int sizeof_int = sizeof(int); +%constant int sizeof_float = sizeof(float); +%constant int sizeof_double = sizeof(double); +%constant int sizeof_gr_complex = sizeof(gr_complex); + +//////////////////////////////////////////////////////////////////////// + +%include +%include +%include +%include + +// %include + +//////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-core/src/lib/swig/shared_ptr.i b/gnuradio-core/src/lib/swig/shared_ptr.i new file mode 100644 index 00000000..9663033a --- /dev/null +++ b/gnuradio-core/src/lib/swig/shared_ptr.i @@ -0,0 +1,43 @@ +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +// +// This is highly hacked up version of boost::shared_ptr +// We just need enough to get SWIG to "do the right thing" and +// generate "Smart Pointer" code. +// + +namespace boost { + +template class shared_ptr +{ +public: + + shared_ptr() + { + } + + shared_ptr (T * p) + { + } + + + T * operator-> () // never throws + { + return px; + } + + +private: + + T * px; // contained pointer + int pn; + +}; // shared_ptr + +}; \ No newline at end of file diff --git a/gnuradio-core/src/python/Makefile.am b/gnuradio-core/src/python/Makefile.am new file mode 100644 index 00000000..99f86026 --- /dev/null +++ b/gnuradio-core/src/python/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = gnuradio bin + +noinst_PYTHON = \ + build_utils.py \ + build_utils_codes.py + diff --git a/gnuradio-core/src/python/bin/Makefile.am b/gnuradio-core/src/python/bin/Makefile.am new file mode 100644 index 00000000..3e9b9076 --- /dev/null +++ b/gnuradio-core/src/python/bin/Makefile.am @@ -0,0 +1,30 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + + +EXTRA_DIST = microtune.py + +bin_SCRIPTS = \ + microtune.py + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/bin/microtune.py b/gnuradio-core/src/python/bin/microtune.py new file mode 100755 index 00000000..0e799c93 --- /dev/null +++ b/gnuradio-core/src/python/bin/microtune.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- Python -*- + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink +from optparse import OptionParser +from gnuradio import eng_notation + + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option ("-g", "--gain", type="eng_float", default=-1, + help="set front end gain to GAIN [0,1000]") + parser.add_option ("-f", "--freq", type="eng_float", default=-1, + help="set front end center frequency to FREQ") + parser.add_option ("-t", "--type", type="string", default="4937", + help="select eval board type {4937 or 4702}") + parser.add_option ("-p", "--port", type="int", default=0, + help="parallel port eval board is attached to") + (options, args) = parser.parse_args () + + if options.type == "4937": + front_end = gr.microtune_4937_eval_board (options.port) + elif options.type == "4702": + front_end = gr.microtune_4702_eval_board (options.port) + else: + raise RuntimeError, "Invalid board type. Must be either -t 4937 or -t 4702" + + if options.gain != -1: + front_end.set_AGC (options.gain) + + if options.freq != -1: + if options.freq < 1e6: + options.freq = options.freq * 1e6 + + actual = front_end.set_RF_freq (options.freq) + print "microtune: actual freq = %s" % (eng_notation.num_to_str (actual),) + + +if __name__ == '__main__': + main () diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py new file mode 100644 index 00000000..18cfc2e7 --- /dev/null +++ b/gnuradio-core/src/python/build_utils.py @@ -0,0 +1,163 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +"""Misc utilities used at build time +""" + +import re, os, os.path +from build_utils_codes import * + + +# set srcdir to the directory that contains Makefile.am +try: + srcdir = os.environ['srcdir'] +except KeyError, e: + srcdir = "." +srcdir = srcdir + '/' + + +name_dict = {} + +def log_output_name (name): + (base, ext) = os.path.splitext (name) + ext = ext[1:] # drop the leading '.' + + entry = name_dict.setdefault (ext, []) + entry.append (name) + +def open_and_log_name (name, dir): + f = open (name, dir) + log_output_name (name) + return f + +def expand_template (d, template_filename, extra = ""): + '''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file + ''' + output_extension = extract_extension (template_filename) + template = open_src (template_filename, 'r') + output_name = d['NAME'] + extra + '.' + output_extension + log_output_name (output_name) + output = open (output_name, 'w') + do_substitution (d, template, output) + template.close () + output.close () + +def output_glue (dirname): + output_makefile_fragment () + output_ifile_include (dirname) + +def output_makefile_fragment (): + f = open ('Makefile.gen', 'w') + f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n') + output_subfrag (f, 'h') + output_subfrag (f, 'i') + output_subfrag (f, 'cc') + f.close () + +def output_ifile_include (dirname): + f = open ('%s_generated.i' % (dirname,), 'w') + f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n') + files = name_dict.setdefault ('i', []) + files.sort () + f.write ('%{\n') + for file in files: + f.write ('#include <%s>\n' % (file[0:-1] + 'h',)) + f.write ('%}\n\n') + for file in files: + f.write ('%%include <%s>\n' % (file,)) + +def output_subfrag (f, ext): + files = name_dict.setdefault (ext, []) + files.sort () + f.write ("GENERATED_%s =" % (ext.upper ())) + for file in files: + f.write (" \\\n\t%s" % (file,)) + f.write ("\n\n") + + +def extract_extension (template_name): + # template name is something like: GrFIRfilterXXX.h.t + # we return everything between the penultimate . and .t + mo = re.search (r'\.([a-z]+)\.t$', template_name) + if not mo: + raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,) + return mo.group (1) + +def open_src (name, mode): + global srcdir + return open (os.path.join (srcdir, name), mode) + +def do_substitution (d, in_file, out_file): + def repl (match_obj): + key = match_obj.group (1) + # print key + return d[key] + + inp = in_file.read () + out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp) + out_file.write (out) + + + +copyright = '''/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +''' + +def is_complex (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c': + return '1' + else: + return '0' + + +def standard_dict (name, code3): + d = {} + d['NAME'] = name + d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper () + d['BASE_NAME'] = re.sub ('^gr_', '', name) + d['SPTR_NAME'] = '%s_sptr' % name + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be over written' + d['COPYRIGHT'] = copyright + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d diff --git a/gnuradio-core/src/python/build_utils_codes.py b/gnuradio-core/src/python/build_utils_codes.py new file mode 100644 index 00000000..f4215f2b --- /dev/null +++ b/gnuradio-core/src/python/build_utils_codes.py @@ -0,0 +1,52 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def i_code (code3): + return code3[0] + +def o_code (code3): + if len (code3) >= 2: + return code3[1] + else: + return code3[0] + +def tap_code (code3): + if len (code3) >= 3: + return code3[2] + else: + return code3[0] + +def i_type (code3): + return char_to_type[i_code (code3)] + +def o_type (code3): + return char_to_type[o_code (code3)] + +def tap_type (code3): + return char_to_type[tap_code (code3)] + + +char_to_type = {} +char_to_type['s'] = 'short' +char_to_type['i'] = 'int' +char_to_type['f'] = 'float' +char_to_type['c'] = 'gr_complex' +char_to_type['b'] = 'unsigned char' diff --git a/gnuradio-core/src/python/gnuradio/Makefile.am b/gnuradio-core/src/python/gnuradio/Makefile.am new file mode 100644 index 00000000..3222c5db --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/Makefile.am @@ -0,0 +1,36 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = gr gru gruimpl blks blksimpl + +grpython_PYTHON = \ + __init__.py \ + audio.py \ + eng_notation.py \ + eng_option.py \ + packet_utils.py \ + gr_unittest.py \ + optfir.py \ + window.py + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/gnuradio/__init__.py b/gnuradio-core/src/python/gnuradio/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/audio.py b/gnuradio-core/src/python/gnuradio/audio.py new file mode 100644 index 00000000..5a9d09c7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/audio.py @@ -0,0 +1,88 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +This is the 'generic' audio or soundcard interface. + +The behavior of this module is controlled by the [audio] audio_module +configuration parameter. If it is 'auto' we attempt to import modules +from the known_modules list, using the first one imported successfully. + +If [audio] audio_module is not 'auto', we assume it's the name of +an audio module and attempt to import it. +""" + +__all__ = ['source', 'sink'] + +from gnuradio import gr +import sys + +source = None +sink = None + + +known_modules = ( + 'audio_alsa', 'audio_oss', 'audio_osx', 'audio_jack', 'audio_portaudio') + + +def try_import(name): + """ + Build a blob of code and try to execute it. + If it succeeds we will have set the globals source and sink + as side effects. + + returns True or False + """ + global source, sink + full_name = "gnuradio." + name + code = """ +import %s +source = %s.source +sink = %s.sink +""" % (full_name, full_name, full_name) + try: + exec code in globals() + return True + except ImportError: + return False + + +def __init__ (): + p = gr.prefs() # get preferences (config file) object + verbose = p.get_bool('audio', 'verbose', False) + module = p.get_string('audio', 'audio_module', 'auto') + + if module == 'auto': # search our list for the first one that we can import + for m in known_modules: + if try_import(m): + if verbose: sys.stderr.write('audio: using %s\n' % (m,)) + return + raise ImportError, 'Unable to locate an audio module.' + + else: # use the one the user specified + if try_import(module): + if verbose: sys.stderr.write('audio: using %s\n' % (module,)) + else: + msg = 'Failed to import user-specified audio module %s' % (module,) + if verbose: sys.stderr.write('audio: %s\n' % (msg,)) + raise ImportError, msg + +__init__() diff --git a/gnuradio-core/src/python/gnuradio/blks/Makefile.am b/gnuradio-core/src/python/gnuradio/blks/Makefile.am new file mode 100644 index 00000000..17574d77 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# EXTRA_DIST = run_tests.in +# TESTS = run_tests + +grblkspythondir = $(grpythondir)/blks + +grblkspython_PYTHON = \ + __init__.py + + +noinst_PYTHON = + +CLEANFILES = *.pyc *.pyo diff --git a/gnuradio-core/src/python/gnuradio/blks/__init__.py b/gnuradio-core/src/python/gnuradio/blks/__init__.py new file mode 100644 index 00000000..4cc10ebb --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks/__init__.py @@ -0,0 +1,37 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import glob +import os.path + +# Semi-hideous kludge to import everything in the blksimpl directory +# into the gnuradio.blks namespace. This keeps us from having to remember +# to manually update this file. + +for p in __path__: + filenames = glob.glob (os.path.join (p, "..", "blksimpl", "*.py")) + for f in filenames: + f = os.path.basename(f).lower() + f = f[:-3] + if f == '__init__': + continue + # print f + exec "from gnuradio.blksimpl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am new file mode 100644 index 00000000..415920b2 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am @@ -0,0 +1,49 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# EXTRA_DIST = run_tests.in +# TESTS = run_tests + +grblkspythondir = $(grpythondir)/blksimpl + +grblkspython_PYTHON = \ + __init__.py \ + am_demod.py \ + filterbank.py \ + fm_demod.py \ + fm_emph.py \ + gmsk2.py \ + gmsk2_pkt.py \ + nbfm_rx.py \ + nbfm_tx.py \ + pkt.py \ + rational_resampler.py \ + standard_squelch.py \ + wfm_rcv.py \ + wfm_rcv_pll.py \ + wfm_tx.py + + +noinst_PYTHON = + +CLEANFILES = *.pyc *.pyo diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/__init__.py b/gnuradio-core/src/python/gnuradio/blksimpl/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py b/gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py new file mode 100644 index 00000000..309f5e65 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py @@ -0,0 +1,75 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, optfir + +class am_demod_cf(gr.hier_block): + """ + Generalized AM demodulation block with audio filtering. + + This block demodulates a band-limited, complex down-converted AM + channel into the the original baseband signal, applying low pass + filtering to the audio output. It produces a float stream in the + range [-1.0, +1.0]. + + @param fg: flowgraph + @param channel_rate: incoming sample rate of the AM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + @param audio_pass: audio low pass filter passband frequency + @type audio_pass: float + @param audio_stop: audio low pass filter stop frequency + @type audio_stop: float + """ + def __init__(self, fg, channel_rate, audio_decim, audio_pass, audio_stop): + MAG = gr.complex_to_mag() + DCR = gr.add_const_ff(-1.0) + + audio_taps = optfir.low_pass(0.5, # Filter gain + channel_rate, # Sample rate + audio_pass, # Audio passband + audio_stop, # Audio stopband + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = gr.fir_filter_fff(audio_decim, audio_taps) + + fg.connect(MAG, DCR, LPF) + gr.hier_block.__init__(self, fg, MAG, LPF) + +class demod_10k0a3e_cf(am_demod_cf): + """ + AM demodulation block, 10 KHz channel. + + This block demodulates an AM channel conformant to 10K0A3E emission + standards, such as broadcast band AM transmissions. + + @param fg: flowgraph + @param channel_rate: incoming sample rate of the AM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, fg, channel_rate, audio_decim): + am_demod_cf.__init__(self, fg, channel_rate, audio_decim, + 5000, # Audio passband + 5500) # Audio stopband + \ No newline at end of file diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real b/gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real new file mode 100644 index 00000000..1b3a14f3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Digital voice Tx and Rx using GSM 13kbit vocoder and GMSK. + +Runs channel at 32kbit/sec. Currently uses fake channel coding, +but there's room for a rate 1/2 coder. +""" + +from gnuradio import gr, gru +from gnuradio.blksimpl.gmsk import gmsk_mod, gmsk_demod + +from gnuradio.vocoder import gsm_full_rate + +# Size of gsm full rate speech encoder output packet in bytes + +GSM_FRAME_SIZE = 33 + +# Size of packet in bytes that we send to GMSK modulator: +# +# Target: 256kS/sec air rate. +# +# 256kS 1 sym 1 bit 1 byte 0.020 sec 80 bytes +# ---- * ----- * ----- * ------ * --------- = -------- +# sec 8 S 1 sym 8 bits frame frame +# +# gr_simple_framer add 10 bytes of overhead. + +AIR_FRAME_SIZE = 70 + + +class digital_voice_tx(gr.hier_block): + """ + Hierarchical block for digital voice tranmission. + + The input is 8kS/sec floating point audio in the range [-1,+1] + The output is 256kS/sec GMSK modulated complex baseband signal in the range [-1,+1]. + """ + def __init__(self, fg): + samples_per_symbol = 8 + symbol_rate = 32000 + bt = 0.3 # Gaussian filter bandwidth * symbol time + + src_scale = gr.multiply_const_ff(32767) + f2s = gr.float_to_short() + voice_coder = gsm_full_rate.encode_sp() + + channel_coder = gr.fake_channel_encoder_pp(GSM_FRAME_SIZE, AIR_FRAME_SIZE) + p2s = gr.parallel_to_serial(gr.sizeof_char, AIR_FRAME_SIZE) + + mod = gmsk_mod(fg, sps=samples_per_symbol, + symbol_rate=symbol_rate, bt=bt, + p_size=AIR_FRAME_SIZE) + + fg.connect(src_scale, f2s, voice_coder, channel_coder, p2s, mod) + gr.hier_block.__init__(self, fg, src_scale, mod) + + +class digital_voice_rx(gr.hier_block): + """ + Hierarchical block for digital voice reception. + + The input is 256kS/sec GMSK modulated complex baseband signal. + The output is 8kS/sec floating point audio in the range [-1,+1] + """ + def __init__(self, fg): + samples_per_symbol = 8 + symbol_rate = 32000 + + demod = gmsk_demod(fg, sps=samples_per_symbol, + symbol_rate=symbol_rate, + p_size=AIR_FRAME_SIZE) + + s2p = gr.serial_to_parallel(gr.sizeof_char, AIR_FRAME_SIZE) + channel_decoder = gr.fake_channel_decoder_pp(AIR_FRAME_SIZE, GSM_FRAME_SIZE) + + voice_decoder = gsm_full_rate.decode_ps() + s2f = gr.short_to_float () + sink_scale = gr.multiply_const_ff(1.0/32767.) + + fg.connect(demod, s2p, channel_decoder, voice_decoder, s2f, sink_scale) + gr.hier_block.__init__(self, fg, demod, sink_scale) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py b/gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py new file mode 100644 index 00000000..bd23f793 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py @@ -0,0 +1,160 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import sys +from gnuradio import gr, gru + +def _generate_synthesis_taps(mpoints): + return [] # FIXME + + +def _split_taps(taps, mpoints): + assert (len(taps) % mpoints) == 0 + result = [list() for x in range(mpoints)] + for i in xrange(len(taps)): + (result[i % mpoints]).append(taps[i]) + return [tuple(x) for x in result] + + +class synthesis_filterbank(gr.hier_block): + """ + Uniformly modulated polyphase DFT filter bank: synthesis + + See http://cnx.rice.edu/content/m10424/latest + """ + def __init__(self, fg, mpoints, taps=None): + """ + Takes M complex streams in, produces single complex stream out + that runs at M times the input sample rate + + @param fg: flow_graph + @param mpoints: number of freq bins/interpolation factor/subbands + @param taps: filter taps for subband filter + + The channel spacing is equal to the input sample rate. + The total bandwidth and output sample rate are equal the input + sample rate * nchannels. + + Output stream to frequency mapping: + + channel zero is at zero frequency. + + if mpoints is odd: + + Channels with increasing positive frequencies come from + channels 1 through (N-1)/2. + + Channel (N+1)/2 is the maximum negative frequency, and + frequency increases through N-1 which is one channel lower + than the zero frequency. + + if mpoints is even: + + Channels with increasing positive frequencies come from + channels 1 through (N/2)-1. + + Channel (N/2) is evenly split between the max positive and + negative bins. + + Channel (N/2)+1 is the maximum negative frequency, and + frequency increases through N-1 which is one channel lower + than the zero frequency. + + Channels near the frequency extremes end up getting cut + off by subsequent filters and therefore have diminished + utility. + """ + item_size = gr.sizeof_gr_complex + + if taps is None: + taps = _generate_synthesis_taps(mpoints) + + # pad taps to multiple of mpoints + r = len(taps) % mpoints + if r != 0: + taps = taps + (mpoints - r) * (0,) + + # split in mpoints separate set of taps + sub_taps = _split_taps(taps, mpoints) + + self.ss2v = gr.streams_to_vector(item_size, mpoints) + self.ifft = gr.fft_vcc(mpoints, False, []) + self.v2ss = gr.vector_to_streams(item_size, mpoints) + # mpoints filters go in here... + self.ss2s = gr.streams_to_stream(item_size, mpoints) + + fg.connect(self.ss2v, self.ifft, self.v2ss) + + # build mpoints fir filters... + for i in range(mpoints): + f = gr.fft_filter_ccc(1, sub_taps[i]) + fg.connect((self.v2ss, i), f) + fg.connect(f, (self.ss2s, i)) + + gr.hier_block.__init__(self, fg, self.ss2v, self.ss2s) + + +class analysis_filterbank(gr.hier_block): + """ + Uniformly modulated polyphase DFT filter bank: analysis + + See http://cnx.rice.edu/content/m10424/latest + """ + def __init__(self, fg, mpoints, taps=None): + """ + Takes 1 complex stream in, produces M complex streams out + that runs at 1/M times the input sample rate + + @param fg: flow_graph + @param mpoints: number of freq bins/interpolation factor/subbands + @param taps: filter taps for subband filter + + Same channel to frequency mapping as described above. + """ + item_size = gr.sizeof_gr_complex + + if taps is None: + taps = _generate_synthesis_taps(mpoints) + + # pad taps to multiple of mpoints + r = len(taps) % mpoints + if r != 0: + taps = taps + (mpoints - r) * (0,) + + # split in mpoints separate set of taps + sub_taps = _split_taps(taps, mpoints) + + # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps) + + self.s2ss = gr.stream_to_streams(item_size, mpoints) + # filters here + self.ss2v = gr.streams_to_vector(item_size, mpoints) + self.fft = gr.fft_vcc(mpoints, True, []) + self.v2ss = gr.vector_to_streams(item_size, mpoints) + + # build mpoints fir filters... + for i in range(mpoints): + f = gr.fft_filter_ccc(1, sub_taps[mpoints-i-1]) + fg.connect((self.s2ss, i), f) + fg.connect(f, (self.ss2v, i)) + + fg.connect(self.ss2v, self.fft, self.v2ss) + gr.hier_block.__init__(self, fg, self.s2ss, self.v2ss) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py b/gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py new file mode 100644 index 00000000..9487e0f0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py @@ -0,0 +1,122 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_deemph +from math import pi + +class fm_demod_cf(gr.hier_block): + """ + Generalized FM demodulation block with deemphasis and audio + filtering. + + This block demodulates a band-limited, complex down-converted FM + channel into the the original baseband signal, optionally applying + deemphasis. Low pass filtering is done on the resultant signal. It + produces an output float strem in the range of [-1.0, +1.0]. + + @param fg: flowgraph + @param channel_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param deviation: maximum FM deviation (default = 5000) + @type deviation: float + @param audio_decim: input to output decimation rate + @type audio_decim: integer + @param audio_pass: audio low pass filter passband frequency + @type audio_pass: float + @param audio_stop: audio low pass filter stop frequency + @type audio_stop: float + @param gain: gain applied to audio output (default = 1.0) + @type gain: float + @param tau: deemphasis time constant (default = 75e-6), specify 'None' + to prevent deemphasis + """ + def __init__(self, fg, channel_rate, audio_decim, deviation, + audio_pass, audio_stop, gain=1.0, tau=75e-6): + + """ + # Equalizer for ~100 us delay + delay = 100e-6 + num_taps = int(channel_rate*delay) + + mu = 1e-4/num_taps + print "CMA: delay =", delay, "n =", num_taps, "mu =", mu + CMA = gr.cma_equalizer_cc(num_taps, 1.0, mu) + """ + k = channel_rate/(2*pi*deviation) + QUAD = gr.quadrature_demod_cf(k) + + audio_taps = optfir.low_pass(gain, # Filter gain + channel_rate, # Sample rate + audio_pass, # Audio passband + audio_stop, # Audio stopband + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = gr.fir_filter_fff(audio_decim, audio_taps) + + if tau is not None: + DEEMPH = fm_deemph(fg, channel_rate, tau) + fg.connect(QUAD, DEEMPH, LPF) + else: + fg.connect(QUAD, LPF) + + gr.hier_block.__init__(self, fg, QUAD, LPF) + +class demod_20k0f3e_cf(fm_demod_cf): + """ + NBFM demodulation block, 20 KHz channels + + This block demodulates a complex, downconverted, narrowband FM + channel conforming to 20K0F3E emission standards, outputting + floats in the range [-1.0, +1.0]. + + @param fg: flowgraph + @param sample_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, fg, channel_rate, audio_decim): + fm_demod_cf.__init__(self, fg, channel_rate, audio_decim, + 5000, # Deviation + 3000, # Audio passband frequency + 4000) # Audio stopband frequency + +class demod_200kf3e_cf(fm_demod_cf): + """ + WFM demodulation block, mono. + + This block demodulates a complex, downconverted, wideband FM + channel conforming to 200KF3E emission standards, outputting + floats in the range [-1.0, +1.0]. + + @param fg: flowgraph + @param sample_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, fg, channel_rate, audio_decim): + fm_demod_cf.__init__(self, fg, channel_rate, audio_decim, + 75000, # Deviation + 15000, # Audio passband + 16000, # Audio stopband + 20.0) # Audio gain diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py b/gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py new file mode 100644 index 00000000..5c256f5d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py @@ -0,0 +1,145 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +import math + + +# +# 1 +# H(s) = ------- +# 1 + s +# +# tau is the RC time constant. +# critical frequency: w_p = 1/tau +# +# We prewarp and use the bilinear z-transform to get our IIR coefficients. +# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis +# + +class fm_deemph(gr.hier_block): + """ + FM Deemphasis IIR filter. + """ + def __init__(self, fg, fs, tau=75e-6): + """ + @param fg: flow graph + @type fg: gr.flow_graph + @param fs: sampling frequency in Hz + @type fs: float + @param tau: Time constant in seconds (75us in US, 50us in EUR) + @type tau: float + """ + w_p = 1/tau + w_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq + + a1 = (w_pp - 1)/(w_pp + 1) + b0 = w_pp/(1 + w_pp) + b1 = b0 + + btaps = [b0, b1] + ataps = [1, a1] + + if 0: + print "btaps =", btaps + print "ataps =", ataps + global plot1 + plot1 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True) + + deemph = gr.iir_filter_ffd(btaps, ataps) + gr.hier_block.__init__(self, fg, deemph, deemph) + +# +# 1 + s*t1 +# H(s) = ---------- +# 1 + s*t2 +# +# I think this is the right transfer function. +# +# +# This fine ASCII rendition is based on Figure 5-15 +# in "Digital and Analog Communication Systems", Leon W. Couch II +# +# +# R1 +# +-----||------+ +# | | +# o------+ +-----+--------o +# | C1 | | +# +----/\/\/\/--+ \ +# / +# \ R2 +# / +# \ +# | +# o--------------------------+--------o +# +# f1 = 1/(2*pi*t1) = 1/(2*pi*R1*C) +# +# 1 R1 + R2 +# f2 = ------- = ------------ +# 2*pi*t2 2*pi*R1*R2*C +# +# t1 is 75us in US, 50us in EUR +# f2 should be higher than our audio bandwidth. +# +# +# The Bode plot looks like this: +# +# +# /---------------- +# / +# / <-- slope = 20dB/decade +# / +# -------------/ +# f1 f2 +# +# We prewarp and use the bilinear z-transform to get our IIR coefficients. +# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis +# + +class fm_preemph(gr.hier_block): + """ + FM Preemphasis IIR filter. + """ + def __init__(self, fg, fs, tau=75e-6): + """ + @param fg: flow graph + @type fg: gr.flow_graph + @param fs: sampling frequency in Hz + @type fs: float + @param tau: Time constant in seconds (75us in US, 50us in EUR) + @type tau: float + """ + + # FIXME make this compute the right answer + + btaps = [1] + ataps = [1] + + if 0: + print "btaps =", btaps + print "ataps =", ataps + global plot2 + plot2 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True) + + preemph = gr.iir_filter_ffd(btaps, ataps) + gr.hier_block.__init__(self, fg, preemph, preemph) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py new file mode 100644 index 00000000..68d18967 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py @@ -0,0 +1,159 @@ +# +# GMSK modulation and demodulation. +# +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# See gnuradio-examples/python/gmsk2 for examples + +from gnuradio import gr +from math import pi +import Numeric + +# ///////////////////////////////////////////////////////////////////////////// +# GMSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + +class gmsk2_mod(gr.hier_block): + + def __init__(self, fg, spb = 2, bt = 0.3): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) + modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param bt: Gaussian filter bandwidth * symbol time + @type bt: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 4 * spb # up to 3 bits in filter at once + sensitivity = (pi / 2) / spb # phase change per bit = pi / 2 + + # Turn it into NRZ data. + self.nrz = gr.bytes_to_syms() + + # Form Gaussian filter + + # Generate Gaussian response (Needs to be convolved with window below). + self.gaussian_taps = gr.firdes.gaussian( + 1, # gain + spb, # symbol_rate + bt, # bandwidth * symbol time + ntaps # number of taps + ) + + self.sqwave = (1,) * spb # rectangular window + self.taps = Numeric.convolve(Numeric.array(self.gaussian_taps),Numeric.array(self.sqwave)) + self.gaussian_filter = gr.interp_fir_filter_fff(spb, self.taps) + + # FM modulation + self.fmmod = gr.frequency_modulator_fc(sensitivity) + + # Connect + fg.connect(self.nrz, self.gaussian_filter, self.fmmod) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.nrz, self.fmmod) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +class gmsk2_demod(gr.hier_block): + + def __init__(self, fg, spb=2, omega=None, gain_mu=0.03, mu=0.5, + omega_relative_limit=0.000200, freq_error=0.0): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) + demodulation. + + The input is the complex modulated signal at baseband. + The output is a stream of symbols ready to be sliced at zero. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud + @type spb: integer + + Clock recovery parameters. These all have reasonble defaults. + + @param omega: nominal relative freq (defaults to spb) + @type omega: float + @param gain_mu: controls rate of mu adjustment + @type gain_mu: float + @param mu: fractional delay [0.0, 1.0] + @type mu: float + @param omega_relative_limit: sets max variation in omega + @type omega_relative_limit: float, typically 0.000200 (200 ppm) + @param freq_error: bit rate error as a fraction + @param float + """ + if spb < 2: + raise TypeError, "sbp >= 2" + self.spb = spb + + if omega is None: + omega = spb*(1+freq_error) + + gain_omega = .25*gain_mu*gain_mu # critically damped + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1, 1000) + + # Demodulate FM + sensitivity = (pi / 2) / spb + self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity) + + alpha = 0.0008 + + # the clock recovery block tracks the symbol clock and resamples as needed. + # the output of the block is a stream of soft symbols (float) + self.clock_recovery = gr.clock_recovery_mm_ff(omega, gain_omega, mu, gain_mu, + omega_relative_limit) + + # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample + self.slicer = gr.binary_slicer_fb() + + fg.connect(self.preamp, self.agc, self.fmdemod, self.clock_recovery, self.slicer) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.slicer) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py new file mode 100644 index 00000000..af586239 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py @@ -0,0 +1,174 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from math import pi +import Numeric + +from gnuradio import gr, packet_utils +import gnuradio.gr.gr_threading as _threading +import gmsk2 + + +def _deprecation_warning(old_name, new_name): + print '#' + print '# Warning: %s is deprecated and will be removed soon.' % (old_name,) + print '# Please use the modulation independent block, %s.' % (new_name,) + print "#" + + +# ///////////////////////////////////////////////////////////////////////////// +# GMSK mod/demod with packets as i/o +# ///////////////////////////////////////////////////////////////////////////// + +class gmsk2_mod_pkts(gr.hier_block): + """ + GSM modulator that is a GNU Radio source. + + Send packets by calling send_pkt + """ + def __init__(self, fg, access_code=None, msgq_limit=2, pad_for_usrp=True, *args, **kwargs): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) modulation. + + Packets to be sent are enqueued by calling send_pkt. + The output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's between 1 and 64 long + @param msgq_limit: maximum number of messages in message queue + @type msgq_limit: int + @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples + + See gmsk_mod for remaining parameters + """ + _deprecation_warning('gmsk2_mod_pkts', 'mod_pkts') + + self.pad_for_usrp = pad_for_usrp + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + # accepts messages from the outside world + self.pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) + self.gmsk_mod = gmsk2.gmsk2_mod(fg, *args, **kwargs) + fg.connect(self.pkt_input, self.gmsk_mod) + gr.hier_block.__init__(self, fg, None, self.gmsk_mod) + + def send_pkt(self, payload='', eof=False): + """ + Send the payload. + + @param payload: data to send + @type payload: string + """ + if eof: + msg = gr.message(1) # tell self.pkt_input we're not sending any more packets + else: + # print "original_payload =", string_to_hex_list(payload) + pkt = packet_utils.make_packet(payload, + self.gmsk_mod.samples_per_baud(), + self.gmsk_mod.bits_per_baud(), + self._access_code, + self.pad_for_usrp) + #print "pkt =", string_to_hex_list(pkt) + msg = gr.message_from_string(pkt) + self.pkt_input.msgq().insert_tail(msg) + + + +class gmsk2_demod_pkts(gr.hier_block): + """ + GSM demodulator that is a GNU Radio sink. + + The input is complex baseband. When packets are demodulated, they are passed to the + app via the callback. + """ + + def __init__(self, fg, access_code=None, callback=None, threshold=-1, *args, **kwargs): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) + demodulation. + + The input is the complex modulated signal at baseband. + Demodulated packets are sent to the handler. + + @param fg: flow graph + @type fg: flow graph + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's + @param callback: function of two args: ok, payload + @type callback: ok: bool; payload: string + @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default) + @type threshold: int + + See gmsk_demod for remaining parameters. + """ + + _deprecation_warning('gmsk2_demod_pkts', 'demod_pkts') + + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + if threshold == -1: + threshold = 12 # FIXME raise exception + + self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY + self.gmsk_demod = gmsk2.gmsk2_demod(fg, *args, **kwargs) + self.correlator = gr.correlate_access_code_bb(access_code, threshold) + + self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + fg.connect(self.gmsk_demod, self.correlator, self.framer_sink) + + gr.hier_block.__init__(self, fg, self.gmsk_demod, None) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + + def carrier_sensed(self): + """ + Return True if we detect carrier. + """ + return False # FIXME + + +class _queue_watcher_thread(_threading.Thread): + def __init__(self, rcvd_pktq, callback): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.rcvd_pktq = rcvd_pktq + self.callback = callback + self.keep_running = True + self.start() + + #def stop(self): + # self.keep_running = False + + def run(self): + while self.keep_running: + msg = self.rcvd_pktq.delete_head() + ok, payload = packet_utils.unmake_packet(msg.to_string()) + if self.callback: + self.callback(ok, payload) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py new file mode 100644 index 00000000..39059ec9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py @@ -0,0 +1,87 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_deemph +from gnuradio.blksimpl.standard_squelch import standard_squelch + +class nbfm_rx(gr.hier_block): + def __init__(self, fg, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): + """ + Narrow Band FM Receiver. + + Takes a single complex baseband input stream and produces a single + float output stream of audio sample in the range [-1, +1]. + + @param fg: flow graph + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 5e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + + Exported sub-blocks (attributes): + squelch + quad_demod + deemph + audio_filter + """ + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + squelch_threshold = 20 # dB + #self.squelch = gr.simple_squelch_cc(squelch_threshold, 0.001) + + # FM Demodulator input: complex; output: float + k = quad_rate/(2*math.pi*max_dev) + self.quad_demod = gr.quadrature_demod_cf(k) + + # FM Deemphasis IIR filter + self.deemph = fm_deemph (fg, quad_rate, tau=tau) + + # compute FIR taps for audio filter + audio_decim = quad_rate // audio_rate + audio_taps = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + 4.5e3, # Audio LPF cutoff + 2.5e3, # Transition band + gr.firdes.WIN_HAMMING) # filter type + + print "len(audio_taps) =", len(audio_taps) + + # Decimating audio filter + # input: float; output: float; taps: float + self.audio_filter = gr.fir_filter_fff(audio_decim, audio_taps) + + fg.connect(self.quad_demod, self.deemph, self.audio_filter) + + gr.hier_block.__init__(self, fg, self.quad_demod, self.audio_filter) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py new file mode 100644 index 00000000..2f636b67 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py @@ -0,0 +1,95 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_preemph + +#from gnuradio import ctcss + +class nbfm_tx(gr.hier_block): + def __init__(self, fg, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): + """ + Narrow Band FM Transmitter. + + Takes a single float input stream of audio samples in the range [-1,+1] + and produces a single FM modulated complex baseband output. + + @param fg: flow graph + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 5e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + """ + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + + do_interp = audio_rate != quad_rate + + if do_interp: + interp_factor = quad_rate / audio_rate + interp_taps = optfir.low_pass (interp_factor, # gain + quad_rate, # Fs + 4500, # passband cutoff + 7000, # stopband cutoff + 0.1, # passband ripple dB + 40) # stopband atten dB + + #print "len(interp_taps) =", len(interp_taps) + self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps) + + self.preemph = fm_preemph (fg, quad_rate, tau=tau) + + k = 2 * math.pi * max_dev / quad_rate + self.modulator = gr.frequency_modulator_fc (k) + + if do_interp: + fg.connect (self.interpolator, self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.interpolator, self.modulator) + else: + fg.connect(self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.preemph, self.modulator) + + +#class ctcss_gen_f(gr.sig_source_f): +# def __init__(self, sample_rate, tone_freq): +# gr.sig_source_f.__init__(self, sample_rate, gr.SIN_WAVE, tone_freq, 0.1, 0.0) +# +# def set_tone (self, tone): +# gr.sig_source_f.set_frequency(self,tone) + +class ctcss_gen_f(gr.hier_block): + def __init__(self, fg, sample_rate, tone_freq): + self.plgen = gr.sig_source_f(sample_rate, gr.GR_SIN_WAVE, tone_freq, 0.1, 0.0) + + gr.hier_block.__init__(self, fg, self.plgen, self.plgen) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py new file mode 100644 index 00000000..3ebb7229 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py @@ -0,0 +1,156 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from math import pi +import Numeric + +from gnuradio import gr, packet_utils +import gnuradio.gr.gr_threading as _threading + + +# ///////////////////////////////////////////////////////////////////////////// +# mod/demod with packets as i/o +# ///////////////////////////////////////////////////////////////////////////// + +class mod_pkts(gr.hier_block): + """ + Wrap an arbitrary digital modulator in our packet handling framework. + + Send packets by calling send_pkt + """ + def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True): + """ + Hierarchical block for sending packets + + Packets to be sent are enqueued by calling send_pkt. + The output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param modulator: instance of modulator class (gr_block or hier_block) + @type modulator: complex baseband out + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's between 1 and 64 long + @param msgq_limit: maximum number of messages in message queue + @type msgq_limit: int + @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples + + See gmsk_mod for remaining parameters + """ + self._modulator = modulator + self._pad_for_usrp = pad_for_usrp + + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + # accepts messages from the outside world + self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) + fg.connect(self._pkt_input, self._modulator) + gr.hier_block.__init__(self, fg, None, self._modulator) + + def send_pkt(self, payload='', eof=False): + """ + Send the payload. + + @param payload: data to send + @type payload: string + """ + if eof: + msg = gr.message(1) # tell self._pkt_input we're not sending any more packets + else: + # print "original_payload =", string_to_hex_list(payload) + pkt = packet_utils.make_packet(payload, + self._modulator.samples_per_baud(), + self._modulator.bits_per_baud(), + self._access_code, + self._pad_for_usrp) + #print "pkt =", string_to_hex_list(pkt) + msg = gr.message_from_string(pkt) + self._pkt_input.msgq().insert_tail(msg) + + + +class demod_pkts(gr.hier_block): + """ + Wrap an arbitrary digital demodulator in our packet handling framework. + + The input is complex baseband. When packets are demodulated, they are passed to the + app via the callback. + """ + + def __init__(self, fg, demodulator, access_code=None, callback=None, threshold=-1): + """ + Hierarchical block for demodulating and deframing packets. + + The input is the complex modulated signal at baseband. + Demodulated packets are sent to the handler. + + @param fg: flow graph + @type fg: flow graph + @param demodulator: instance of demodulator class (gr_block or hier_block) + @type demodulator: complex baseband in + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's + @param callback: function of two args: ok, payload + @type callback: ok: bool; payload: string + @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default) + @type threshold: int + """ + + self._demodulator = demodulator + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + if threshold == -1: + threshold = 12 # FIXME raise exception + + self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY + self.correlator = gr.correlate_access_code_bb(access_code, threshold) + + self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + fg.connect(self._demodulator, self.correlator, self.framer_sink) + + gr.hier_block.__init__(self, fg, self._demodulator, None) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + + +class _queue_watcher_thread(_threading.Thread): + def __init__(self, rcvd_pktq, callback): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.rcvd_pktq = rcvd_pktq + self.callback = callback + self.keep_running = True + self.start() + + + def run(self): + while self.keep_running: + msg = self.rcvd_pktq.delete_head() + ok, payload = packet_utils.unmake_packet(msg.to_string()) + if self.callback: + self.callback(ok, payload) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py b/gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py new file mode 100644 index 00000000..8b928b10 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py @@ -0,0 +1,137 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru + +_plot = None + +def design_filter(interpolation, decimation, fractional_bw): + """ + Given the interpolation rate, decimation rate and a fractional bandwidth, + design a set of taps. + + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well. + @type fractional_bw: float + @returns: sequence of numbers + """ + + global _plot + + if fractional_bw >= 0.5 or fractional_bw <= 0: + raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)" + + beta = 5.0 + trans_width = 0.5 - fractional_bw + mid_transition_band = 0.5 - trans_width/2 + + taps = gr.firdes.low_pass(interpolation, # gain + 1, # Fs + mid_transition_band/interpolation, # trans mid point + trans_width/interpolation, # transition width + gr.firdes.WIN_KAISER, + beta # beta + ) + # print "len(resampler_taps) =", len(taps) + # _plot = gru.gnuplot_freqz(gru.freqz(taps, 1), 1) + + return taps + + + +class _rational_resampler_base(gr.hier_block): + """ + base class for all rational resampler variants. + """ + def __init__(self, resampler_base, fg, + interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter. + + Either taps or fractional_bw may be specified, but not both. + If neither is specified, a reasonable default, 0.4, is used as + the fractional_bw. + + @param fg: flow graph + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param taps: optional filter coefficients + @type taps: sequence + @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4) + @type fractional_bw: float + """ + + if not isinstance(interpolation, int) or interpolation < 1: + raise ValueError, "interpolation must be an integer >= 1" + + if not isinstance(decimation, int) or decimation < 1: + raise ValueError, "decimation must be an integer >= 1" + + if taps is None and fractional_bw is None: + fractional_bw = 0.4 + + d = gru.gcd(interpolation, decimation) + interpolation = interpolation // d + decimation = decimation // d + + if taps is None: + taps = design_filter(interpolation, decimation, fractional_bw) + + resampler = resampler_base(interpolation, decimation, taps) + gr.hier_block.__init__(self, fg, resampler, resampler) + + + +class rational_resampler_fff(_rational_resampler_base): + def __init__(self, fg, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + float input, float output and float taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_fff, fg, + interpolation, decimation, + taps, fractional_bw) + +class rational_resampler_ccf(_rational_resampler_base): + def __init__(self, fg, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and float taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccf, fg, + interpolation, decimation, + taps, fractional_bw) + +class rational_resampler_ccc(_rational_resampler_base): + def __init__(self, fg, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and complex taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccc, fg, + interpolation, decimation, + taps, fractional_bw) + diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py b/gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py new file mode 100644 index 00000000..2c80dd5a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py @@ -0,0 +1,73 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +from gnuradio import gr, optfir + +class standard_squelch(gr.hier_block): + def __init__(self, fg, audio_rate): + + self.input_node = gr.add_const_ff(0) # FIXME kludge + + self.low_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.9524,-0.9615)) + self.low_square = gr.multiply_ff() + self.low_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) # 100ms time constant + + self.hi_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.3597,-0.9615)) + self.hi_square = gr.multiply_ff() + self.hi_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + + self.sub = gr.sub_ff(); + self.add = gr.add_ff(); + self.gate = gr.threshold_ff(0.3,0.43,0) + self.squelch_lpf = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + + self.div = gr.divide_ff() + self.squelch_mult = gr.multiply_ff() + + fg.connect (self.input_node, (self.squelch_mult, 0)) + + fg.connect (self.input_node,self.low_iir) + fg.connect (self.low_iir,(self.low_square,0)) + fg.connect (self.low_iir,(self.low_square,1)) + fg.connect (self.low_square,self.low_smooth,(self.sub,0)) + fg.connect (self.low_smooth, (self.add,0)) + + fg.connect (self.input_node,self.hi_iir) + fg.connect (self.hi_iir,(self.hi_square,0)) + fg.connect (self.hi_iir,(self.hi_square,1)) + fg.connect (self.hi_square,self.hi_smooth,(self.sub,1)) + fg.connect (self.hi_smooth, (self.add,1)) + + fg.connect (self.sub, (self.div, 0)) + fg.connect (self.add, (self.div, 1)) + fg.connect (self.div, self.gate, self.squelch_lpf, (self.squelch_mult,1)) + + gr.hier_block.__init__(self, fg, self.input_node, self.squelch_mult) + + def set_threshold(self, threshold): + self.gate.set_hi(threshold) + + def threshold(self): + return self.gate.hi() + + def squelch_range(self): + return (0.0, 1.0, 1.0/100) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py new file mode 100644 index 00000000..55dbbaa0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py @@ -0,0 +1,72 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio.blksimpl.fm_emph import fm_deemph +import math + +class wfm_rcv(gr.hier_block): + def __init__ (self, fg, quad_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal (gr_complex). + The output is the demodulated audio (float). + + @param fg: flow graph. + @type fg: flow graph + @param quad_rate: input sample rate of complex baseband input. + @type quad_rate: float + @param audio_decimation: how much to decimate quad_rate to get to audio. + @type audio_decimation: integer + """ + volume = 20. + + max_dev = 75e3 + fm_demod_gain = quad_rate/(2*math.pi*max_dev) + audio_rate = quad_rate / audio_decimation + + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) + + # input: float; output: float + self.deemph = fm_deemph (fg, audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (self.fm_demod, self.audio_filter, self.deemph) + + gr.hier_block.__init__(self, + fg, + self.fm_demod, # head of the pipeline + self.deemph) # tail of the pipeline diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py new file mode 100644 index 00000000..d116090e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py @@ -0,0 +1,206 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio.blksimpl.fm_emph import fm_deemph +import math + +class wfm_rcv_pll(gr.hier_block): + def __init__ (self, fg, demod_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal (gr_complex). + The output is two streams of the demodulated audio (float) 0=Left, 1=Right. + + @param fg: flow graph. + @type fg: flow graph + @param demod_rate: input sample rate of complex baseband input. + @type demod_rate: float + @param audio_decimation: how much to decimate demod_rate to get to audio. + @type audio_decimation: integer + """ + + bandwidth = 200e3 + audio_rate = demod_rate / audio_decimation + + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + alpha = 0.25*bandwidth * math.pi / demod_rate + beta = alpha * alpha / 4.0 + max_freq = 2.0*math.pi*100e3/demod_rate + + self.fm_demod = gr.pll_freqdet_cf (alpha,beta,max_freq,-max_freq) + + # input: float; output: float + self.deemph_Left = fm_deemph (fg, audio_rate) + self.deemph_Right = fm_deemph (fg, audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0 , # gain + demod_rate, # sampling rate + 15000 , + width_of_transition_band, + gr.firdes.WIN_HAMMING) + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + if 1: + # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain + # We pick off the negative frequency half because we want to base band by it! + ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS + + stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0, + demod_rate, + -19020, + -18980, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs) + #print "stereo carrier filter ", stereo_carrier_filter_coeffs + #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate + + # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain + + stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0, + demod_rate, + 38000-15000/2, + 38000+15000/2, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs) + + # carrier is twice the picked off carrier so arrange to do a commplex multiply + + self.stereo_carrier_generator = gr.multiply_cc(); + + # Pick off the rds signal + + stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0, + demod_rate, + 57000 - 1500, + 57000 + 1500, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs) + self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs) + + + + + + + self.rds_carrier_generator = gr.multiply_cc(); + self.rds_signal_generator = gr.multiply_cc(); + self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex); + + + + alpha = 5 * 0.25 * math.pi / (audio_rate) + beta = alpha * alpha / 4.0 + max_freq = -2.0*math.pi*18990/audio_rate; + min_freq = -2.0*math.pi*19010/audio_rate; + + self.stereo_carrier_pll_recovery = gr.pll_carriertracking_cc(alpha,beta,max_freq,min_freq); + self.stereo_carrier_pll_recovery.squelch_enable(False); + + + # set up mixer (multiplier) to get the L-R signal at baseband + + self.stereo_basebander = gr.multiply_cc(); + + # pick off the real component of the basebanded L-R signal. The imaginary SHOULD be zero + + self.LmR_real = gr.complex_to_real(); + self.Make_Left = gr.add_ff(); + self.Make_Right = gr.sub_ff(); + + self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs) + + + if 1: + + # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier + fg.connect (self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0)) + # send the already filtered carrier to the otherside of the carrier + fg.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1)) + # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz. + + # send the new carrier to one side of the mixer (multiplier) + fg.connect (self.stereo_carrier_generator, (self.stereo_basebander,0)) + # send the demphasized audio to the DSBSC pick off filter, the complex + # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier + fg.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1)) + # the result is BASEBANDED DSBSC with phase zero! + + # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer + fg.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0)) + #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter + fg.connect (self.LmR_real,(self.Make_Right,1)) + + # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone + fg.connect (self.stereo_basebander,(self.rds_carrier_generator,0)) + fg.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) + # take signal, filter off rds, send into mixer 0 channel + fg.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) + # take rds_carrier_generator output and send into mixer 1 channel + fg.connect (self.rds_carrier_generator,(self.rds_signal_generator,1)) + # send basebanded rds signal and send into "processor" which for now is a null sink + fg.connect (self.rds_signal_generator,self_rds_signal_processor) + + + if 1: + # pick off the audio, L+R that is what we used to have and send it to the summer + fg.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1)) + # take the picked off L+R audio and send it to the PLUS side of the subtractor + fg.connect(self.audio_filter,(self.Make_Right, 0)) + # The result of Make_Left gets (L+R) + (L-R) and results in 2*L + # The result of Make_Right gets (L+R) - (L-R) and results in 2*R + + + # kludge the signals into a stereo channel + kludge = gr.kludge_copy(gr.sizeof_float) + fg.connect(self.Make_Left , self.deemph_Left, (kludge, 0)) + fg.connect(self.Make_Right, self.deemph_Right, (kludge, 1)) + + #send it to the audio system + gr.hier_block.__init__(self, + fg, + self.fm_demod, # head of the pipeline + kludge) # tail of the pipeline + else: + fg.connect (self.fm_demod, self.audio_filter) + gr.hier_block.__init__(self, + fg, + self.fm_demod, # head of the pipeline + self.audio_filter) # tail of the pipeline diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py new file mode 100644 index 00000000..50545557 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py @@ -0,0 +1,79 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_preemph + +class wfm_tx(gr.hier_block): + def __init__(self, fg, audio_rate, quad_rate, tau=75e-6, max_dev=75e3): + """ + Wide Band FM Transmitter. + + Takes a single float input stream of audio samples in the range [-1,+1] + and produces a single FM modulated complex baseband output. + + @param fg: flow graph + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 75e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + """ + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + + do_interp = audio_rate != quad_rate + + if do_interp: + interp_factor = quad_rate / audio_rate + interp_taps = optfir.low_pass (interp_factor, # gain + quad_rate, # Fs + 16000, # passband cutoff + 18000, # stopband cutoff + 0.1, # passband ripple dB + 40) # stopband atten dB + + print "len(interp_taps) =", len(interp_taps) + self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps) + + self.preemph = fm_preemph (fg, quad_rate, tau=tau) + + k = 2 * math.pi * max_dev / quad_rate + self.modulator = gr.frequency_modulator_fc (k) + + if do_interp: + fg.connect (self.interpolator, self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.interpolator, self.modulator) + else: + fg.connect(self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.preemph, self.modulator) diff --git a/gnuradio-core/src/python/gnuradio/eng_notation.py b/gnuradio-core/src/python/gnuradio/eng_notation.py new file mode 100644 index 00000000..72cd8931 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/eng_notation.py @@ -0,0 +1,71 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +scale_factor = {} +scale_factor['E'] = 1e18 +scale_factor['P'] = 1e15 +scale_factor['T'] = 1e12 +scale_factor['G'] = 1e9 +scale_factor['M'] = 1e6 +scale_factor['k'] = 1e3 +scale_factor['m'] = 1e-3 +scale_factor['u'] = 1e-6 +scale_factor['n'] = 1e-9 +scale_factor['p'] = 1e-12 +scale_factor['f'] = 1e-15 +scale_factor['a'] = 1e-18 + +def num_to_str (n): + '''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n''' + m = abs(n) + if m >= 1e9: + return "%gG" % (n * 1e-9) + elif m >= 1e6: + return "%gM" % (n * 1e-6) + elif m >= 1e3: + return "%gk" % (n * 1e-3) + elif m >= 1: + return "%g" % (n) + elif m >= 1e-3: + return "%gm" % (n * 1e3) + elif m >= 1e-6: + return "%gu" % (n * 1e6) # where's that mu when you need it (unicode?) + elif m >= 1e-9: + return "%gn" % (n * 1e9) + elif m >= 1e-12: + return "%gp" % (n * 1e12) + elif m >= 1e-15: + return "%gf" % (n * 1e15) + else: + return "%g" % (n) + + +def str_to_num (value): + '''Convert a string in engineering notation to a number. E.g., '15m' -> 15e-3''' + try: + scale = 1.0 + suffix = value[-1] + if scale_factor.has_key (suffix): + return float (value[0:-1]) * scale_factor[suffix] + return float (value) + except: + raise RuntimeError ( + "Invalid engineering notation value: %r" % (value,)) diff --git a/gnuradio-core/src/python/gnuradio/eng_option.py b/gnuradio-core/src/python/gnuradio/eng_option.py new file mode 100644 index 00000000..3e25c578 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/eng_option.py @@ -0,0 +1,80 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +'''Add support for engineering notation to optparse.OptionParser''' + +from copy import copy +from optparse import Option, OptionValueError + +scale_factor = {} +scale_factor['E'] = 1e18 +scale_factor['P'] = 1e15 +scale_factor['T'] = 1e12 +scale_factor['G'] = 1e9 +scale_factor['M'] = 1e6 +scale_factor['k'] = 1e3 +scale_factor['m'] = 1e-3 +scale_factor['u'] = 1e-6 +scale_factor['n'] = 1e-9 +scale_factor['p'] = 1e-12 +scale_factor['f'] = 1e-15 +scale_factor['a'] = 1e-18 + + +def check_eng_float (option, opt, value): + try: + scale = 1.0 + suffix = value[-1] + if scale_factor.has_key (suffix): + return float (value[0:-1]) * scale_factor[suffix] + return float (value) + except: + raise OptionValueError ( + "option %s: invalid engineering notation value: %r" % (opt, value)) + +def check_intx (option, opt, value): + try: + return int (value, 0) + except: + raise OptionValueError ( + "option %s: invalid integer value: %r" % (opt, value)) + +def check_subdev (option, opt, value): + """ + Value has the form: (A|B)(:0|1)? + + @returns a 2-tuple (0|1, 0|1) + """ + d = { 'A' : (0, 0), 'A:0' : (0, 0), 'A:1' : (0, 1), + 'B' : (1, 0), 'B:0' : (1, 0), 'B:1' : (1, 1) } + try: + return d[value.upper()] + except: + raise OptionValueError( + "option %s: invalid subdev: '%r', must be one of A, B, A:0, A:1, B:0, B:1" % (opt, value)) + +class eng_option (Option): + TYPES = Option.TYPES + ("eng_float", "intx", "subdev") + TYPE_CHECKER = copy (Option.TYPE_CHECKER) + TYPE_CHECKER["eng_float"] = check_eng_float + TYPE_CHECKER["intx"] = check_intx + TYPE_CHECKER["subdev"] = check_subdev + diff --git a/gnuradio-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am new file mode 100644 index 00000000..05dee29f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am @@ -0,0 +1,77 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +grgrpythondir = $(grpythondir)/gr + +grgrpython_PYTHON = \ + __init__.py \ + basic_flow_graph.py \ + exceptions.py \ + flow_graph.py \ + gr_threading.py \ + gr_threading_23.py \ + gr_threading_24.py \ + hier_block.py \ + prefs.py \ + scheduler.py + +noinst_PYTHON = \ + qa_add_and_friends.py \ + qa_basic_flow_graph.py \ + qa_complex_to_xxx.py \ + qa_correlate_access_code.py \ + qa_diff_encoder.py \ + qa_diff_phasor_cc.py \ + qa_feval.py \ + qa_fft_filter.py \ + qa_filter_delay_fc.py \ + qa_flow_graph.py \ + qa_frequency_modulator.py \ + qa_fsk_stuff.py \ + qa_head.py \ + qa_hilbert.py \ + qa_iir.py \ + qa_interleave.py \ + qa_interp_fir_filter.py \ + qa_kludge_copy.py \ + qa_kludged_imports.py \ + qa_message.py \ + qa_mute.py \ + qa_nlog10.py \ + qa_packed_to_unpacked.py \ + qa_pipe_fittings.py \ + qa_rational_resampler.py \ + qa_sig_source.py \ + qa_single_pole_iir.py \ + qa_single_pole_iir_cc.py \ + qa_unpack_k_bits.py + + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py new file mode 100644 index 00000000..5583c412 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py @@ -0,0 +1,40 @@ +# +# Copyright 2003,2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# The presence of this file turns this directory into a Python package + +# This is the main GNU Radio python module. +# We pull the swig output and the other modules into the gnuradio.gr namespace + +from gnuradio_swig_python import * +from basic_flow_graph import * +from flow_graph import * +from exceptions import * +from hier_block import * + + +# create a couple of aliases +serial_to_parallel = stream_to_vector +parallel_to_serial = vector_to_stream + +# Force the preference database to be initialized +from prefs import prefs + diff --git a/gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py new file mode 100644 index 00000000..1afc9629 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py @@ -0,0 +1,267 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio_swig_python import gr_block_sptr +import types +import hier_block + +def remove_duplicates (seq): + new = [] + for x in seq: + if not x in new: + new.append (x) + return new + + +class endpoint (object): + __slots__ = ['block', 'port'] + def __init__ (self, block, port): + self.block = block + self.port = port + + def __cmp__ (self, other): + if self.block == other.block and self.port == other.port: + return 0 + return 1 + + def __str__ (self): + return '' % (self.block, self.port) + +def expand_src_endpoint (src_endpoint): + # A src_endpoint is an output of a block + src_endpoint = coerce_endpoint (src_endpoint) + if isinstance (src_endpoint.block, hier_block.hier_block_base): + return expand_src_endpoint ( + coerce_endpoint (src_endpoint.block.resolve_output_port(src_endpoint.port))) + else: + return src_endpoint + +def expand_dst_endpoint (dst_endpoint): + # a dst_endpoint is the input to a block + dst_endpoint = coerce_endpoint (dst_endpoint) + if isinstance (dst_endpoint.block, hier_block.hier_block_base): + exp = [coerce_endpoint(x) for x in + dst_endpoint.block.resolve_input_port(dst_endpoint.port)] + return expand_dst_endpoints (exp) + else: + return [dst_endpoint] + +def expand_dst_endpoints (endpoint_list): + r = [] + for e in endpoint_list: + r.extend (expand_dst_endpoint (e)) + return r + + +def coerce_endpoint (x): + if isinstance (x, endpoint): + return x + elif isinstance (x, types.TupleType) and len (x) == 2: + return endpoint (x[0], x[1]) + elif hasattr (x, 'block'): # assume it's a block + return endpoint (x, 0) + elif isinstance(x, hier_block.hier_block_base): + return endpoint (x, 0) + else: + raise ValueError, "Not coercible to endpoint: %s" % (x,) + + +class edge (object): + __slots__ = ['src', 'dst'] + def __init__ (self, src_endpoint, dst_endpoint): + self.src = src_endpoint + self.dst = dst_endpoint + + def __cmp__ (self, other): + if self.src == other.src and self.dst == other.dst: + return 0 + return 1 + + def __repr__ (self): + return '' % (self.src, self.dst) + +class basic_flow_graph (object): + '''basic_flow_graph -- describe connections between blocks''' + # __slots__ is incompatible with weakrefs (for some reason!) + # __slots__ = ['edge_list'] + def __init__ (self): + self.edge_list = [] + + def connect (self, *points): + '''connect requires two or more arguments that can be coerced to endpoints. + If more than two arguments are provided, they are connected together successively. + ''' + if len (points) < 2: + raise ValueError, ("connect requires at least two endpoints; %d provided." % (len (points),)) + for i in range (1, len (points)): + self._connect (points[i-1], points[i]) + + def _connect (self, src_endpoint, dst_endpoint): + s = expand_src_endpoint (src_endpoint) + for d in expand_dst_endpoint (dst_endpoint): + self._connect_prim (s, d) + + def _connect_prim (self, src_endpoint, dst_endpoint): + src_endpoint = coerce_endpoint (src_endpoint) + dst_endpoint = coerce_endpoint (dst_endpoint) + self._check_valid_src_port (src_endpoint) + self._check_valid_dst_port (dst_endpoint) + self._check_dst_in_use (dst_endpoint) + self._check_type_match (src_endpoint, dst_endpoint) + self.edge_list.append (edge (src_endpoint, dst_endpoint)) + + def disconnect (self, src_endpoint, dst_endpoint): + s = expand_src_endpoint (src_endpoint) + for d in expand_dst_endpoint (dst_endpoint): + self._disconnect_prim (s, d) + + def _disconnect_prim (self, src_endpoint, dst_endpoint): + src_endpoint = coerce_endpoint (src_endpoint) + dst_endpoint = coerce_endpoint (dst_endpoint) + e = edge (src_endpoint, dst_endpoint) + self.edge_list.remove (e) + + def disconnect_all (self): + self.edge_list = [] + + def validate (self): + # check all blocks to ensure: + # (1a) their input ports are contiguously assigned + # (1b) the number of input ports is between min and max + # (2a) their output ports are contiguously assigned + # (2b) the number of output ports is between min and max + # (3) check_topology returns true + + for m in self.all_blocks (): + # print m + + edges = self.in_edges (m) + used_ports = [e.dst.port for e in edges] + ninputs = self._check_contiguity (m, m.input_signature (), used_ports, "input") + + edges = self.out_edges (m) + used_ports = [e.src.port for e in edges] + noutputs = self._check_contiguity (m, m.output_signature (), used_ports, "output") + + if not m.check_topology (ninputs, noutputs): + raise ValueError, ("%s::check_topology (%d, %d) failed" % (m, ninputs, noutputs)) + + + # --- public utilities --- + + def all_blocks (self): + '''return list of all blocks in the graph''' + all_blocks = [] + for edge in self.edge_list: + m = edge.src.block + if not m in all_blocks: + all_blocks.append (m) + m = edge.dst.block + if not m in all_blocks: + all_blocks.append (m) + return all_blocks + + def in_edges (self, m): + '''return list of all edges that have M as a destination''' + return [e for e in self.edge_list if e.dst.block == m] + + def out_edges (self, m): + '''return list of all edges that have M as a source''' + return [e for e in self.edge_list if e.src.block == m] + + def downstream_verticies (self, m): + return [e.dst.block for e in self.out_edges (m)] + + def downstream_verticies_port (self, m, port): + return [e.dst.block for e in self.out_edges(m) if e.src.port == port] + + def upstream_verticies (self, m): + return [e.src.block for e in self.in_edges (m)] + + def adjacent_verticies (self, m): + '''return list of all verticies adjacent to M''' + return self.downstream_verticies (m) + self.upstream_verticies (m) + + def sink_p (self, m): + '''return True iff this block is a sink''' + e = self.out_edges (m) + return len (e) == 0 + + def source_p (self, m): + '''return True iff this block is a source''' + e = self.in_edges (m) + return len (e) == 0 + + # --- internal methods --- + + def _check_dst_in_use (self, dst_endpoint): + '''Ensure that there is not already an endpoint that terminates at dst_endpoint.''' + x = [ep for ep in self.edge_list if ep.dst == dst_endpoint] + if x: # already in use + raise ValueError, ("destination endpoint already in use: %s" % (dst_endpoint)) + + def _check_valid_src_port (self, src_endpoint): + self._check_port (src_endpoint.block.output_signature(), src_endpoint.port) + + def _check_valid_dst_port (self, dst_endpoint): + self._check_port (dst_endpoint.block.input_signature(), dst_endpoint.port) + + def _check_port (self, signature, port): + if port < 0: + raise ValueError, 'port number out of range.' + if signature.max_streams () == -1: # infinite + return # OK + if port >= signature.max_streams (): + raise ValueError, 'port number out of range.' + + def _check_type_match (self, src_endpoint, dst_endpoint): + # for now, we just ensure that the stream item sizes match + src_sig = src_endpoint.block.output_signature () + dst_sig = dst_endpoint.block.input_signature () + src_size = src_sig.sizeof_stream_item (src_endpoint.port) + dst_size = dst_sig.sizeof_stream_item (dst_endpoint.port) + if src_size != dst_size: + raise ValueError, 'source and destination data sizes are different' + + def _check_contiguity (self, m, sig, used_ports, dir): + used_ports.sort () + used_ports = remove_duplicates (used_ports) + min_s = sig.min_streams () + + l = len (used_ports) + if l == 0: + if min_s == 0: + return l + raise ValueError, ("%s requires %d %s connections. It has none." % + (m, min_s, dir)) + + if used_ports[-1] + 1 < min_s: + raise ValueError, ("%s requires %d %s connections. It has %d." % + (m, min_s, dir, used_ports[-1] + 1)) + + if used_ports[-1] + 1 != l: + for i in range (l): + if used_ports[i] != i: + raise ValueError, ("%s %s port %d is not connected" % + (m, dir, i)) + + # print "%s ports: %s" % (dir, used_ports) + return l diff --git a/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py b/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py new file mode 100755 index 00000000..7b2f44c4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +import time +import random +from optparse import OptionParser +from gnuradio import gr +from gnuradio.eng_option import eng_option + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.uniform(-1000,1000), + random.uniform(-1000,1000))) + return tuple(result) + +def benchmark(name, creator, dec, ntaps, total_test_size, block_size): + block_size = 32768 + + fg = gr.flow_graph() + taps = make_random_complex_tuple(ntaps) + src = gr.vector_source_c(make_random_complex_tuple(block_size), True) + head = gr.head(gr.sizeof_gr_complex, int(total_test_size)) + op = creator(dec, taps) + dst = gr.null_sink(gr.sizeof_gr_complex) + fg.connect(src, head, op, dst) + start = time.time() + fg.run() + stop = time.time() + delta = stop - start + print "%16s: taps: %4d input: %4g, time: %6.3f taps/sec: %10.4g" % ( + name, ntaps, total_test_size, delta, ntaps*total_test_size/delta) + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-n", "--ntaps", type="int", default=256) + parser.add_option("-t", "--total-input-size", type="eng_float", default=40e6) + parser.add_option("-b", "--block-size", type="intx", default=50000) + parser.add_option("-d", "--decimation", type="int", default=1) + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + ntaps = options.ntaps + total_input_size = options.total_input_size + block_size = options.block_size + dec = options.decimation + + benchmark("gr.fir_filter_ccc", gr.fir_filter_ccc, + dec, ntaps, total_input_size, block_size) + benchmark("gr.fft_filter_ccc", gr.fft_filter_ccc, + dec, ntaps, total_input_size, block_size) + +if __name__ == '__main__': + main() diff --git a/gnuradio-core/src/python/gnuradio/gr/exceptions.py b/gnuradio-core/src/python/gnuradio/gr/exceptions.py new file mode 100644 index 00000000..0cbeb143 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/exceptions.py @@ -0,0 +1,27 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +class NotDAG (Exception): + """Not a directed acyclic graph""" + pass + +class CantHappen (Exception): + """Can't happen""" + pass diff --git a/gnuradio-core/src/python/gnuradio/gr/flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/flow_graph.py new file mode 100644 index 00000000..db9c5876 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/flow_graph.py @@ -0,0 +1,234 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio.gr.basic_flow_graph import remove_duplicates, endpoint, edge, \ + basic_flow_graph + +from gnuradio.gr.exceptions import * +from gnuradio_swig_python import buffer, buffer_add_reader, block_detail, \ + single_threaded_scheduler + +from gnuradio.gr.scheduler import scheduler + +_WHITE = 0 # graph coloring tags +_GRAY = 1 +_BLACK = 2 + +_flow_graph_debug = False + +def set_flow_graph_debug(on): + global _flow_graph_debug + _flow_graph_debug = on + + +class buffer_sizes (object): + """compute buffer sizes to use""" + def __init__ (self, flow_graph): + # We could scan the graph here and determine individual sizes + # based on relative_rate, number of readers, etc. + + # The simplest thing that could possibly work: all buffers same size + self.flow_graph = flow_graph + self.fixed_buffer_size = 32*1024 + + def allocate (self, m, index): + """allocate buffer for output index of block m""" + item_size = m.output_signature().sizeof_stream_item (index) + nitems = self.fixed_buffer_size / item_size + if nitems < 2 * m.output_multiple (): + nitems = 2 * m.output_multiple () + + # if any downstream blocks is a decimator and/or has a large output_multiple, + # ensure that we have a buffer at least 2 * their decimation_factor*output_multiple + for mdown in self.flow_graph.downstream_verticies_port(m, index): + decimation = int(1.0 / mdown.relative_rate()) + nitems = max(nitems, 2 * (decimation * mdown.output_multiple() + mdown.history())) + + return buffer (nitems, item_size) + + +class flow_graph (basic_flow_graph): + """add physical connection info to simple_flow_graph + """ + # __slots__ is incompatible with weakrefs (for some reason!) + # __slots__ = ['blocks', 'scheduler'] + + def __init__ (self): + basic_flow_graph.__init__ (self); + self.blocks = None + self.scheduler = None + + def __del__(self): + # print "\nflow_graph.__del__" + # this ensures that i/o devices such as the USRP get shutdown gracefully + self.stop() + + def start (self): + '''start graph, forking thread(s), return immediately''' + if self.scheduler: + raise RuntimeError, "Scheduler already running" + self._setup_connections () + + # cast down to gr_module_sptr + # t = [x.block () for x in self.topological_sort (self.blocks)] + self.scheduler = scheduler (self) + self.scheduler.start () + + def stop (self): + '''tells scheduler to stop and waits for it to happen''' + if self.scheduler: + self.scheduler.stop () + self.scheduler = None + + def wait (self): + '''waits for scheduler to stop''' + if self.scheduler: + self.scheduler.wait () + self.scheduler = None + + def is_running (self): + return not not self.scheduler + + def run (self): + '''start graph, wait for completion''' + self.start () + self.wait () + + def _setup_connections (self): + """given the basic flow graph, setup all the physical connections""" + self.validate () + self.blocks = self.all_blocks () + self._assign_details () + self._assign_buffers () + self._connect_inputs () + + def _assign_details (self): + for m in self.blocks: + edges = self.in_edges (m) + used_ports = remove_duplicates ([e.dst.port for e in edges]) + ninputs = len (used_ports) + + edges = self.out_edges (m) + used_ports = remove_duplicates ([e.src.port for e in edges]) + noutputs = len (used_ports) + + m.set_detail (block_detail (ninputs, noutputs)) + + def _assign_buffers (self): + """determine the buffer sizes to use, allocate them and attach to detail""" + sizes = buffer_sizes (self) + for m in self.blocks: + d = m.detail () + for index in range (d.noutputs ()): + d.set_output (index, sizes.allocate (m, index)) + + def _connect_inputs (self): + """connect all block inputs to appropriate upstream buffers""" + for m in self.blocks: + d = m.detail () + # print "%r history = %d" % (m, m.history()) + for e in self.in_edges(m): + # FYI, sources don't have any in_edges + our_port = e.dst.port + upstream_block = e.src.block + upstream_port = e.src.port + upstream_buffer = upstream_block.detail().output(upstream_port) + d.set_input(our_port, buffer_add_reader(upstream_buffer, m.history())) + + + def topological_sort (self, all_v): + ''' + Return a topologically sorted list of vertices. + This is basically a depth-first search with checks + for back edges (the non-DAG condition) + + ''' + + # it's correct without this sort, but this + # should give better ordering for cache utilization + all_v = self._sort_sources_first (all_v) + + output = [] + for v in all_v: + v.ts_color = _WHITE + for v in all_v: + if v.ts_color == _WHITE: + self._dfs_visit (v, output) + output.reverse () + return output + + def _dfs_visit (self, u, output): + # print "dfs_visit (enter): ", u + u.ts_color = _GRAY + for v in self.downstream_verticies (u): + if v.ts_color == _WHITE: # (u, v) is a tree edge + self._dfs_visit (v, output) + elif v.ts_color == _GRAY: # (u, v) is a back edge + raise NotDAG, "The graph is not an acyclic graph (It's got a loop)" + elif v.ts_color == _BLACK: # (u, v) is a cross or forward edge + pass + else: + raise CantHappen, "Invalid color on vertex" + u.ts_color = _BLACK + output.append (u) + # print "dfs_visit (exit): ", u, output + + def _sort_sources_first (self, all_v): + # the sort function is not guaranteed to be stable. + # We add the unique_id in to the key so we're guaranteed + # of reproducible results. This is important for the test + # code. There is often more than one valid topological sort. + # We want to force a reproducible choice. + x = [(not self.source_p(v), v.unique_id(), v) for v in all_v] + x.sort () + x = [v[2] for v in x] + # print "sorted: ", x + return x + + def partition_graph (self, all_v): + '''Return a list of lists of nodes that are connected. + The result is a list of disjoint graphs. + The sublists are topologically sorted. + ''' + result = [] + working_v = all_v[:] # make copy + while working_v: + rv = self._reachable_verticies (working_v[0], working_v) + result.append (self.topological_sort (rv)) + for v in rv: + working_v.remove (v) + if _flow_graph_debug: + print "partition_graph:", result + return result + + def _reachable_verticies (self, start, all_v): + for v in all_v: + v.ts_color = _WHITE + + self._reachable_dfs_visit (start) + return [v for v in all_v if v.ts_color == _BLACK] + + def _reachable_dfs_visit (self, u): + u.ts_color = _BLACK + for v in self.adjacent_verticies (u): + if v.ts_color == _WHITE: + self._reachable_dfs_visit (v) + return None diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py new file mode 100644 index 00000000..6a09a323 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py @@ -0,0 +1,35 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from sys import version_info as _version_info + +# import patched version of standard threading module + +if _version_info[0:2] == (2, 3): + #print "Importing gr_threading_23" + from gr_threading_23 import * +elif _version_info[0:2] == (2, 4): + #print "Importing gr_threading_24" + from gr_threading_24 import * +else: + # assume the patch was applied... + #print "Importing system provided threading" + from threading import * diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py new file mode 100644 index 00000000..dee8034c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py @@ -0,0 +1,724 @@ +"""Thread module emulating a subset of Java's threading model.""" + +# This started life as the threading.py module of Python 2.3 +# It's been patched to fix a problem with join, where a KeyboardInterrupt +# caused a lock to be left in the acquired state. + +import sys as _sys + +try: + import thread +except ImportError: + del _sys.modules[__name__] + raise + +from StringIO import StringIO as _StringIO +from time import time as _time, sleep as _sleep +from traceback import print_exc as _print_exc + +# Rename some stuff so "from threading import *" is safe +__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', + 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', + 'Timer', 'setprofile', 'settrace'] + +_start_new_thread = thread.start_new_thread +_allocate_lock = thread.allocate_lock +_get_ident = thread.get_ident +ThreadError = thread.error +del thread + + +# Debug support (adapted from ihooks.py). +# All the major classes here derive from _Verbose. We force that to +# be a new-style class so that all the major classes here are new-style. +# This helps debugging (type(instance) is more revealing for instances +# of new-style classes). + +_VERBOSE = False + +if __debug__: + + class _Verbose(object): + + def __init__(self, verbose=None): + if verbose is None: + verbose = _VERBOSE + self.__verbose = verbose + + def _note(self, format, *args): + if self.__verbose: + format = format % args + format = "%s: %s\n" % ( + currentThread().getName(), format) + _sys.stderr.write(format) + +else: + # Disable this when using "python -O" + class _Verbose(object): + def __init__(self, verbose=None): + pass + def _note(self, *args): + pass + +# Support for profile and trace hooks + +_profile_hook = None +_trace_hook = None + +def setprofile(func): + global _profile_hook + _profile_hook = func + +def settrace(func): + global _trace_hook + _trace_hook = func + +# Synchronization classes + +Lock = _allocate_lock + +def RLock(*args, **kwargs): + return _RLock(*args, **kwargs) + +class _RLock(_Verbose): + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__block = _allocate_lock() + self.__owner = None + self.__count = 0 + + def __repr__(self): + return "<%s(%s, %d)>" % ( + self.__class__.__name__, + self.__owner and self.__owner.getName(), + self.__count) + + def acquire(self, blocking=1): + me = currentThread() + if self.__owner is me: + self.__count = self.__count + 1 + if __debug__: + self._note("%s.acquire(%s): recursive success", self, blocking) + return 1 + rc = self.__block.acquire(blocking) + if rc: + self.__owner = me + self.__count = 1 + if __debug__: + self._note("%s.acquire(%s): initial succes", self, blocking) + else: + if __debug__: + self._note("%s.acquire(%s): failure", self, blocking) + return rc + + def release(self): + me = currentThread() + assert self.__owner is me, "release() of un-acquire()d lock" + self.__count = count = self.__count - 1 + if not count: + self.__owner = None + self.__block.release() + if __debug__: + self._note("%s.release(): final release", self) + else: + if __debug__: + self._note("%s.release(): non-final release", self) + + # Internal methods used by condition variables + + def _acquire_restore(self, (count, owner)): + self.__block.acquire() + self.__count = count + self.__owner = owner + if __debug__: + self._note("%s._acquire_restore()", self) + + def _release_save(self): + if __debug__: + self._note("%s._release_save()", self) + count = self.__count + self.__count = 0 + owner = self.__owner + self.__owner = None + self.__block.release() + return (count, owner) + + def _is_owned(self): + return self.__owner is currentThread() + + +def Condition(*args, **kwargs): + return _Condition(*args, **kwargs) + +class _Condition(_Verbose): + + def __init__(self, lock=None, verbose=None): + _Verbose.__init__(self, verbose) + if lock is None: + lock = RLock() + self.__lock = lock + # Export the lock's acquire() and release() methods + self.acquire = lock.acquire + self.release = lock.release + # If the lock defines _release_save() and/or _acquire_restore(), + # these override the default implementations (which just call + # release() and acquire() on the lock). Ditto for _is_owned(). + try: + self._release_save = lock._release_save + except AttributeError: + pass + try: + self._acquire_restore = lock._acquire_restore + except AttributeError: + pass + try: + self._is_owned = lock._is_owned + except AttributeError: + pass + self.__waiters = [] + + def __repr__(self): + return "" % (self.__lock, len(self.__waiters)) + + def _release_save(self): + self.__lock.release() # No state to save + + def _acquire_restore(self, x): + self.__lock.acquire() # Ignore saved state + + def _is_owned(self): + # Return True if lock is owned by currentThread. + # This method is called only if __lock doesn't have _is_owned(). + if self.__lock.acquire(0): + self.__lock.release() + return False + else: + return True + + def wait(self, timeout=None): + currentThread() # for side-effect + assert self._is_owned(), "wait() of un-acquire()d lock" + waiter = _allocate_lock() + waiter.acquire() + self.__waiters.append(waiter) + saved_state = self._release_save() + try: # restore state no matter what (e.g., KeyboardInterrupt) + if timeout is None: + waiter.acquire() + if __debug__: + self._note("%s.wait(): got it", self) + else: + # Balancing act: We can't afford a pure busy loop, so we + # have to sleep; but if we sleep the whole timeout time, + # we'll be unresponsive. The scheme here sleeps very + # little at first, longer as time goes on, but never longer + # than 20 times per second (or the timeout time remaining). + endtime = _time() + timeout + delay = 0.0005 # 500 us -> initial delay of 1 ms + while True: + gotit = waiter.acquire(0) + if gotit: + break + remaining = endtime - _time() + if remaining <= 0: + break + delay = min(delay * 2, remaining, .05) + _sleep(delay) + if not gotit: + if __debug__: + self._note("%s.wait(%s): timed out", self, timeout) + try: + self.__waiters.remove(waiter) + except ValueError: + pass + else: + if __debug__: + self._note("%s.wait(%s): got it", self, timeout) + finally: + self._acquire_restore(saved_state) + + def notify(self, n=1): + currentThread() # for side-effect + assert self._is_owned(), "notify() of un-acquire()d lock" + __waiters = self.__waiters + waiters = __waiters[:n] + if not waiters: + if __debug__: + self._note("%s.notify(): no waiters", self) + return + self._note("%s.notify(): notifying %d waiter%s", self, n, + n!=1 and "s" or "") + for waiter in waiters: + waiter.release() + try: + __waiters.remove(waiter) + except ValueError: + pass + + def notifyAll(self): + self.notify(len(self.__waiters)) + + +def Semaphore(*args, **kwargs): + return _Semaphore(*args, **kwargs) + +class _Semaphore(_Verbose): + + # After Tim Peters' semaphore class, but not quite the same (no maximum) + + def __init__(self, value=1, verbose=None): + assert value >= 0, "Semaphore initial value must be >= 0" + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__value = value + + def acquire(self, blocking=1): + rc = False + self.__cond.acquire() + while self.__value == 0: + if not blocking: + break + if __debug__: + self._note("%s.acquire(%s): blocked waiting, value=%s", + self, blocking, self.__value) + self.__cond.wait() + else: + self.__value = self.__value - 1 + if __debug__: + self._note("%s.acquire: success, value=%s", + self, self.__value) + rc = True + self.__cond.release() + return rc + + def release(self): + self.__cond.acquire() + self.__value = self.__value + 1 + if __debug__: + self._note("%s.release: success, value=%s", + self, self.__value) + self.__cond.notify() + self.__cond.release() + + +def BoundedSemaphore(*args, **kwargs): + return _BoundedSemaphore(*args, **kwargs) + +class _BoundedSemaphore(_Semaphore): + """Semaphore that checks that # releases is <= # acquires""" + def __init__(self, value=1, verbose=None): + _Semaphore.__init__(self, value, verbose) + self._initial_value = value + + def release(self): + if self._Semaphore__value >= self._initial_value: + raise ValueError, "Semaphore released too many times" + return _Semaphore.release(self) + + +def Event(*args, **kwargs): + return _Event(*args, **kwargs) + +class _Event(_Verbose): + + # After Tim Peters' event class (without is_posted()) + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__flag = False + + def isSet(self): + return self.__flag + + def set(self): + self.__cond.acquire() + try: + self.__flag = True + self.__cond.notifyAll() + finally: + self.__cond.release() + + def clear(self): + self.__cond.acquire() + try: + self.__flag = False + finally: + self.__cond.release() + + def wait(self, timeout=None): + self.__cond.acquire() + try: + if not self.__flag: + self.__cond.wait(timeout) + finally: + self.__cond.release() + +# Helper to generate new thread names +_counter = 0 +def _newname(template="Thread-%d"): + global _counter + _counter = _counter + 1 + return template % _counter + +# Active thread administration +_active_limbo_lock = _allocate_lock() +_active = {} +_limbo = {} + + +# Main class for threads + +class Thread(_Verbose): + + __initialized = False + + def __init__(self, group=None, target=None, name=None, + args=(), kwargs={}, verbose=None): + assert group is None, "group argument must be None for now" + _Verbose.__init__(self, verbose) + self.__target = target + self.__name = str(name or _newname()) + self.__args = args + self.__kwargs = kwargs + self.__daemonic = self._set_daemon() + self.__started = False + self.__stopped = False + self.__block = Condition(Lock()) + self.__initialized = True + + def _set_daemon(self): + # Overridden in _MainThread and _DummyThread + return currentThread().isDaemon() + + def __repr__(self): + assert self.__initialized, "Thread.__init__() was not called" + status = "initial" + if self.__started: + status = "started" + if self.__stopped: + status = "stopped" + if self.__daemonic: + status = status + " daemon" + return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) + + def start(self): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "thread already started" + if __debug__: + self._note("%s.start(): starting thread", self) + _active_limbo_lock.acquire() + _limbo[self] = self + _active_limbo_lock.release() + _start_new_thread(self.__bootstrap, ()) + self.__started = True + _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) + + def run(self): + if self.__target: + self.__target(*self.__args, **self.__kwargs) + + def __bootstrap(self): + try: + self.__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + del _limbo[self] + _active_limbo_lock.release() + if __debug__: + self._note("%s.__bootstrap(): thread started", self) + + if _trace_hook: + self._note("%s.__bootstrap(): registering trace hook", self) + _sys.settrace(_trace_hook) + if _profile_hook: + self._note("%s.__bootstrap(): registering profile hook", self) + _sys.setprofile(_profile_hook) + + try: + self.run() + except SystemExit: + if __debug__: + self._note("%s.__bootstrap(): raised SystemExit", self) + except: + if __debug__: + self._note("%s.__bootstrap(): unhandled exception", self) + s = _StringIO() + _print_exc(file=s) + _sys.stderr.write("Exception in thread %s:\n%s\n" % + (self.getName(), s.getvalue())) + else: + if __debug__: + self._note("%s.__bootstrap(): normal return", self) + finally: + self.__stop() + try: + self.__delete() + except: + pass + + def __stop(self): + self.__block.acquire() + self.__stopped = True + self.__block.notifyAll() + self.__block.release() + + def __delete(self): + _active_limbo_lock.acquire() + del _active[_get_ident()] + _active_limbo_lock.release() + + def join(self, timeout=None): + assert self.__initialized, "Thread.__init__() not called" + assert self.__started, "cannot join thread before it is started" + assert self is not currentThread(), "cannot join current thread" + if __debug__: + if not self.__stopped: + self._note("%s.join(): waiting until thread stops", self) + self.__block.acquire() + try: + if timeout is None: + while not self.__stopped: + self.__block.wait() + if __debug__: + self._note("%s.join(): thread stopped", self) + else: + deadline = _time() + timeout + while not self.__stopped: + delay = deadline - _time() + if delay <= 0: + if __debug__: + self._note("%s.join(): timed out", self) + break + self.__block.wait(delay) + else: + if __debug__: + self._note("%s.join(): thread stopped", self) + finally: + self.__block.release() + + def getName(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__name + + def setName(self, name): + assert self.__initialized, "Thread.__init__() not called" + self.__name = str(name) + + def isAlive(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__started and not self.__stopped + + def isDaemon(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__daemonic + + def setDaemon(self, daemonic): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "cannot set daemon status of active thread" + self.__daemonic = daemonic + +# The timer class was contributed by Itamar Shtull-Trauring + +def Timer(*args, **kwargs): + return _Timer(*args, **kwargs) + +class _Timer(Thread): + """Call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ + + def __init__(self, interval, function, args=[], kwargs={}): + Thread.__init__(self) + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = Event() + + def cancel(self): + """Stop the timer if it hasn't finished yet""" + self.finished.set() + + def run(self): + self.finished.wait(self.interval) + if not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + self.finished.set() + +# Special thread class to represent the main thread +# This is garbage collected through an exit handler + +class _MainThread(Thread): + + def __init__(self): + Thread.__init__(self, name="MainThread") + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + import atexit + atexit.register(self.__exitfunc) + + def _set_daemon(self): + return False + + def __exitfunc(self): + self._Thread__stop() + t = _pickSomeNonDaemonThread() + if t: + if __debug__: + self._note("%s: waiting for other threads", self) + while t: + t.join() + t = _pickSomeNonDaemonThread() + if __debug__: + self._note("%s: exiting", self) + self._Thread__delete() + +def _pickSomeNonDaemonThread(): + for t in enumerate(): + if not t.isDaemon() and t.isAlive(): + return t + return None + + +# Dummy thread class to represent threads not started here. +# These aren't garbage collected when they die, +# nor can they be waited for. +# Their purpose is to return *something* from currentThread(). +# They are marked as daemon threads so we won't wait for them +# when we exit (conform previous semantics). + +class _DummyThread(Thread): + + def __init__(self): + Thread.__init__(self, name=_newname("Dummy-%d")) + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + + def _set_daemon(self): + return True + + def join(self, timeout=None): + assert False, "cannot join a dummy thread" + + +# Global API functions + +def currentThread(): + try: + return _active[_get_ident()] + except KeyError: + ##print "currentThread(): no current thread for", _get_ident() + return _DummyThread() + +def activeCount(): + _active_limbo_lock.acquire() + count = len(_active) + len(_limbo) + _active_limbo_lock.release() + return count + +def enumerate(): + _active_limbo_lock.acquire() + active = _active.values() + _limbo.values() + _active_limbo_lock.release() + return active + +# Create the main thread object + +_MainThread() + + +# Self-test code + +def _test(): + + class BoundedQueue(_Verbose): + + def __init__(self, limit): + _Verbose.__init__(self) + self.mon = RLock() + self.rc = Condition(self.mon) + self.wc = Condition(self.mon) + self.limit = limit + self.queue = [] + + def put(self, item): + self.mon.acquire() + while len(self.queue) >= self.limit: + self._note("put(%s): queue full", item) + self.wc.wait() + self.queue.append(item) + self._note("put(%s): appended, length now %d", + item, len(self.queue)) + self.rc.notify() + self.mon.release() + + def get(self): + self.mon.acquire() + while not self.queue: + self._note("get(): queue empty") + self.rc.wait() + item = self.queue.pop(0) + self._note("get(): got %s, %d left", item, len(self.queue)) + self.wc.notify() + self.mon.release() + return item + + class ProducerThread(Thread): + + def __init__(self, queue, quota): + Thread.__init__(self, name="Producer") + self.queue = queue + self.quota = quota + + def run(self): + from random import random + counter = 0 + while counter < self.quota: + counter = counter + 1 + self.queue.put("%s.%d" % (self.getName(), counter)) + _sleep(random() * 0.00001) + + + class ConsumerThread(Thread): + + def __init__(self, queue, count): + Thread.__init__(self, name="Consumer") + self.queue = queue + self.count = count + + def run(self): + while self.count > 0: + item = self.queue.get() + print item + self.count = self.count - 1 + + NP = 3 + QL = 4 + NI = 5 + + Q = BoundedQueue(QL) + P = [] + for i in range(NP): + t = ProducerThread(Q, NI) + t.setName("Producer-%d" % (i+1)) + P.append(t) + C = ConsumerThread(Q, NI*NP) + for t in P: + t.start() + _sleep(0.000001) + C.start() + for t in P: + t.join() + C.join() + +if __name__ == '__main__': + _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py new file mode 100644 index 00000000..8539bfc0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py @@ -0,0 +1,793 @@ +"""Thread module emulating a subset of Java's threading model.""" + +# This started life as the threading.py module of Python 2.4 +# It's been patched to fix a problem with join, where a KeyboardInterrupt +# caused a lock to be left in the acquired state. + +import sys as _sys + +try: + import thread +except ImportError: + del _sys.modules[__name__] + raise + +from time import time as _time, sleep as _sleep +from traceback import format_exc as _format_exc +from collections import deque + +# Rename some stuff so "from threading import *" is safe +__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', + 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', + 'Timer', 'setprofile', 'settrace', 'local'] + +_start_new_thread = thread.start_new_thread +_allocate_lock = thread.allocate_lock +_get_ident = thread.get_ident +ThreadError = thread.error +del thread + + +# Debug support (adapted from ihooks.py). +# All the major classes here derive from _Verbose. We force that to +# be a new-style class so that all the major classes here are new-style. +# This helps debugging (type(instance) is more revealing for instances +# of new-style classes). + +_VERBOSE = False + +if __debug__: + + class _Verbose(object): + + def __init__(self, verbose=None): + if verbose is None: + verbose = _VERBOSE + self.__verbose = verbose + + def _note(self, format, *args): + if self.__verbose: + format = format % args + format = "%s: %s\n" % ( + currentThread().getName(), format) + _sys.stderr.write(format) + +else: + # Disable this when using "python -O" + class _Verbose(object): + def __init__(self, verbose=None): + pass + def _note(self, *args): + pass + +# Support for profile and trace hooks + +_profile_hook = None +_trace_hook = None + +def setprofile(func): + global _profile_hook + _profile_hook = func + +def settrace(func): + global _trace_hook + _trace_hook = func + +# Synchronization classes + +Lock = _allocate_lock + +def RLock(*args, **kwargs): + return _RLock(*args, **kwargs) + +class _RLock(_Verbose): + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__block = _allocate_lock() + self.__owner = None + self.__count = 0 + + def __repr__(self): + return "<%s(%s, %d)>" % ( + self.__class__.__name__, + self.__owner and self.__owner.getName(), + self.__count) + + def acquire(self, blocking=1): + me = currentThread() + if self.__owner is me: + self.__count = self.__count + 1 + if __debug__: + self._note("%s.acquire(%s): recursive success", self, blocking) + return 1 + rc = self.__block.acquire(blocking) + if rc: + self.__owner = me + self.__count = 1 + if __debug__: + self._note("%s.acquire(%s): initial succes", self, blocking) + else: + if __debug__: + self._note("%s.acquire(%s): failure", self, blocking) + return rc + + def release(self): + me = currentThread() + assert self.__owner is me, "release() of un-acquire()d lock" + self.__count = count = self.__count - 1 + if not count: + self.__owner = None + self.__block.release() + if __debug__: + self._note("%s.release(): final release", self) + else: + if __debug__: + self._note("%s.release(): non-final release", self) + + # Internal methods used by condition variables + + def _acquire_restore(self, (count, owner)): + self.__block.acquire() + self.__count = count + self.__owner = owner + if __debug__: + self._note("%s._acquire_restore()", self) + + def _release_save(self): + if __debug__: + self._note("%s._release_save()", self) + count = self.__count + self.__count = 0 + owner = self.__owner + self.__owner = None + self.__block.release() + return (count, owner) + + def _is_owned(self): + return self.__owner is currentThread() + + +def Condition(*args, **kwargs): + return _Condition(*args, **kwargs) + +class _Condition(_Verbose): + + def __init__(self, lock=None, verbose=None): + _Verbose.__init__(self, verbose) + if lock is None: + lock = RLock() + self.__lock = lock + # Export the lock's acquire() and release() methods + self.acquire = lock.acquire + self.release = lock.release + # If the lock defines _release_save() and/or _acquire_restore(), + # these override the default implementations (which just call + # release() and acquire() on the lock). Ditto for _is_owned(). + try: + self._release_save = lock._release_save + except AttributeError: + pass + try: + self._acquire_restore = lock._acquire_restore + except AttributeError: + pass + try: + self._is_owned = lock._is_owned + except AttributeError: + pass + self.__waiters = [] + + def __repr__(self): + return "" % (self.__lock, len(self.__waiters)) + + def _release_save(self): + self.__lock.release() # No state to save + + def _acquire_restore(self, x): + self.__lock.acquire() # Ignore saved state + + def _is_owned(self): + # Return True if lock is owned by currentThread. + # This method is called only if __lock doesn't have _is_owned(). + if self.__lock.acquire(0): + self.__lock.release() + return False + else: + return True + + def wait(self, timeout=None): + assert self._is_owned(), "wait() of un-acquire()d lock" + waiter = _allocate_lock() + waiter.acquire() + self.__waiters.append(waiter) + saved_state = self._release_save() + try: # restore state no matter what (e.g., KeyboardInterrupt) + if timeout is None: + waiter.acquire() + if __debug__: + self._note("%s.wait(): got it", self) + else: + # Balancing act: We can't afford a pure busy loop, so we + # have to sleep; but if we sleep the whole timeout time, + # we'll be unresponsive. The scheme here sleeps very + # little at first, longer as time goes on, but never longer + # than 20 times per second (or the timeout time remaining). + endtime = _time() + timeout + delay = 0.0005 # 500 us -> initial delay of 1 ms + while True: + gotit = waiter.acquire(0) + if gotit: + break + remaining = endtime - _time() + if remaining <= 0: + break + delay = min(delay * 2, remaining, .05) + _sleep(delay) + if not gotit: + if __debug__: + self._note("%s.wait(%s): timed out", self, timeout) + try: + self.__waiters.remove(waiter) + except ValueError: + pass + else: + if __debug__: + self._note("%s.wait(%s): got it", self, timeout) + finally: + self._acquire_restore(saved_state) + + def notify(self, n=1): + assert self._is_owned(), "notify() of un-acquire()d lock" + __waiters = self.__waiters + waiters = __waiters[:n] + if not waiters: + if __debug__: + self._note("%s.notify(): no waiters", self) + return + self._note("%s.notify(): notifying %d waiter%s", self, n, + n!=1 and "s" or "") + for waiter in waiters: + waiter.release() + try: + __waiters.remove(waiter) + except ValueError: + pass + + def notifyAll(self): + self.notify(len(self.__waiters)) + + +def Semaphore(*args, **kwargs): + return _Semaphore(*args, **kwargs) + +class _Semaphore(_Verbose): + + # After Tim Peters' semaphore class, but not quite the same (no maximum) + + def __init__(self, value=1, verbose=None): + assert value >= 0, "Semaphore initial value must be >= 0" + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__value = value + + def acquire(self, blocking=1): + rc = False + self.__cond.acquire() + while self.__value == 0: + if not blocking: + break + if __debug__: + self._note("%s.acquire(%s): blocked waiting, value=%s", + self, blocking, self.__value) + self.__cond.wait() + else: + self.__value = self.__value - 1 + if __debug__: + self._note("%s.acquire: success, value=%s", + self, self.__value) + rc = True + self.__cond.release() + return rc + + def release(self): + self.__cond.acquire() + self.__value = self.__value + 1 + if __debug__: + self._note("%s.release: success, value=%s", + self, self.__value) + self.__cond.notify() + self.__cond.release() + + +def BoundedSemaphore(*args, **kwargs): + return _BoundedSemaphore(*args, **kwargs) + +class _BoundedSemaphore(_Semaphore): + """Semaphore that checks that # releases is <= # acquires""" + def __init__(self, value=1, verbose=None): + _Semaphore.__init__(self, value, verbose) + self._initial_value = value + + def release(self): + if self._Semaphore__value >= self._initial_value: + raise ValueError, "Semaphore released too many times" + return _Semaphore.release(self) + + +def Event(*args, **kwargs): + return _Event(*args, **kwargs) + +class _Event(_Verbose): + + # After Tim Peters' event class (without is_posted()) + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__flag = False + + def isSet(self): + return self.__flag + + def set(self): + self.__cond.acquire() + try: + self.__flag = True + self.__cond.notifyAll() + finally: + self.__cond.release() + + def clear(self): + self.__cond.acquire() + try: + self.__flag = False + finally: + self.__cond.release() + + def wait(self, timeout=None): + self.__cond.acquire() + try: + if not self.__flag: + self.__cond.wait(timeout) + finally: + self.__cond.release() + +# Helper to generate new thread names +_counter = 0 +def _newname(template="Thread-%d"): + global _counter + _counter = _counter + 1 + return template % _counter + +# Active thread administration +_active_limbo_lock = _allocate_lock() +_active = {} +_limbo = {} + + +# Main class for threads + +class Thread(_Verbose): + + __initialized = False + # Need to store a reference to sys.exc_info for printing + # out exceptions when a thread tries to use a global var. during interp. + # shutdown and thus raises an exception about trying to perform some + # operation on/with a NoneType + __exc_info = _sys.exc_info + + def __init__(self, group=None, target=None, name=None, + args=(), kwargs={}, verbose=None): + assert group is None, "group argument must be None for now" + _Verbose.__init__(self, verbose) + self.__target = target + self.__name = str(name or _newname()) + self.__args = args + self.__kwargs = kwargs + self.__daemonic = self._set_daemon() + self.__started = False + self.__stopped = False + self.__block = Condition(Lock()) + self.__initialized = True + # sys.stderr is not stored in the class like + # sys.exc_info since it can be changed between instances + self.__stderr = _sys.stderr + + def _set_daemon(self): + # Overridden in _MainThread and _DummyThread + return currentThread().isDaemon() + + def __repr__(self): + assert self.__initialized, "Thread.__init__() was not called" + status = "initial" + if self.__started: + status = "started" + if self.__stopped: + status = "stopped" + if self.__daemonic: + status = status + " daemon" + return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) + + def start(self): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "thread already started" + if __debug__: + self._note("%s.start(): starting thread", self) + _active_limbo_lock.acquire() + _limbo[self] = self + _active_limbo_lock.release() + _start_new_thread(self.__bootstrap, ()) + self.__started = True + _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) + + def run(self): + if self.__target: + self.__target(*self.__args, **self.__kwargs) + + def __bootstrap(self): + try: + self.__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + del _limbo[self] + _active_limbo_lock.release() + if __debug__: + self._note("%s.__bootstrap(): thread started", self) + + if _trace_hook: + self._note("%s.__bootstrap(): registering trace hook", self) + _sys.settrace(_trace_hook) + if _profile_hook: + self._note("%s.__bootstrap(): registering profile hook", self) + _sys.setprofile(_profile_hook) + + try: + self.run() + except SystemExit: + if __debug__: + self._note("%s.__bootstrap(): raised SystemExit", self) + except: + if __debug__: + self._note("%s.__bootstrap(): unhandled exception", self) + # If sys.stderr is no more (most likely from interpreter + # shutdown) use self.__stderr. Otherwise still use sys (as in + # _sys) in case sys.stderr was redefined since the creation of + # self. + if _sys: + _sys.stderr.write("Exception in thread %s:\n%s\n" % + (self.getName(), _format_exc())) + else: + # Do the best job possible w/o a huge amt. of code to + # approximate a traceback (code ideas from + # Lib/traceback.py) + exc_type, exc_value, exc_tb = self.__exc_info() + try: + print>>self.__stderr, ( + "Exception in thread " + self.getName() + + " (most likely raised during interpreter shutdown):") + print>>self.__stderr, ( + "Traceback (most recent call last):") + while exc_tb: + print>>self.__stderr, ( + ' File "%s", line %s, in %s' % + (exc_tb.tb_frame.f_code.co_filename, + exc_tb.tb_lineno, + exc_tb.tb_frame.f_code.co_name)) + exc_tb = exc_tb.tb_next + print>>self.__stderr, ("%s: %s" % (exc_type, exc_value)) + # Make sure that exc_tb gets deleted since it is a memory + # hog; deleting everything else is just for thoroughness + finally: + del exc_type, exc_value, exc_tb + else: + if __debug__: + self._note("%s.__bootstrap(): normal return", self) + finally: + self.__stop() + try: + self.__delete() + except: + pass + + def __stop(self): + self.__block.acquire() + self.__stopped = True + self.__block.notifyAll() + self.__block.release() + + def __delete(self): + "Remove current thread from the dict of currently running threads." + + # Notes about running with dummy_thread: + # + # Must take care to not raise an exception if dummy_thread is being + # used (and thus this module is being used as an instance of + # dummy_threading). dummy_thread.get_ident() always returns -1 since + # there is only one thread if dummy_thread is being used. Thus + # len(_active) is always <= 1 here, and any Thread instance created + # overwrites the (if any) thread currently registered in _active. + # + # An instance of _MainThread is always created by 'threading'. This + # gets overwritten the instant an instance of Thread is created; both + # threads return -1 from dummy_thread.get_ident() and thus have the + # same key in the dict. So when the _MainThread instance created by + # 'threading' tries to clean itself up when atexit calls this method + # it gets a KeyError if another Thread instance was created. + # + # This all means that KeyError from trying to delete something from + # _active if dummy_threading is being used is a red herring. But + # since it isn't if dummy_threading is *not* being used then don't + # hide the exception. + + _active_limbo_lock.acquire() + try: + try: + del _active[_get_ident()] + except KeyError: + if 'dummy_threading' not in _sys.modules: + raise + finally: + _active_limbo_lock.release() + + def join(self, timeout=None): + assert self.__initialized, "Thread.__init__() not called" + assert self.__started, "cannot join thread before it is started" + assert self is not currentThread(), "cannot join current thread" + if __debug__: + if not self.__stopped: + self._note("%s.join(): waiting until thread stops", self) + self.__block.acquire() + try: + if timeout is None: + while not self.__stopped: + self.__block.wait() + if __debug__: + self._note("%s.join(): thread stopped", self) + else: + deadline = _time() + timeout + while not self.__stopped: + delay = deadline - _time() + if delay <= 0: + if __debug__: + self._note("%s.join(): timed out", self) + break + self.__block.wait(delay) + else: + if __debug__: + self._note("%s.join(): thread stopped", self) + finally: + self.__block.release() + + def getName(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__name + + def setName(self, name): + assert self.__initialized, "Thread.__init__() not called" + self.__name = str(name) + + def isAlive(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__started and not self.__stopped + + def isDaemon(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__daemonic + + def setDaemon(self, daemonic): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "cannot set daemon status of active thread" + self.__daemonic = daemonic + +# The timer class was contributed by Itamar Shtull-Trauring + +def Timer(*args, **kwargs): + return _Timer(*args, **kwargs) + +class _Timer(Thread): + """Call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ + + def __init__(self, interval, function, args=[], kwargs={}): + Thread.__init__(self) + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = Event() + + def cancel(self): + """Stop the timer if it hasn't finished yet""" + self.finished.set() + + def run(self): + self.finished.wait(self.interval) + if not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + self.finished.set() + +# Special thread class to represent the main thread +# This is garbage collected through an exit handler + +class _MainThread(Thread): + + def __init__(self): + Thread.__init__(self, name="MainThread") + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + import atexit + atexit.register(self.__exitfunc) + + def _set_daemon(self): + return False + + def __exitfunc(self): + self._Thread__stop() + t = _pickSomeNonDaemonThread() + if t: + if __debug__: + self._note("%s: waiting for other threads", self) + while t: + t.join() + t = _pickSomeNonDaemonThread() + if __debug__: + self._note("%s: exiting", self) + self._Thread__delete() + +def _pickSomeNonDaemonThread(): + for t in enumerate(): + if not t.isDaemon() and t.isAlive(): + return t + return None + + +# Dummy thread class to represent threads not started here. +# These aren't garbage collected when they die, +# nor can they be waited for. +# Their purpose is to return *something* from currentThread(). +# They are marked as daemon threads so we won't wait for them +# when we exit (conform previous semantics). + +class _DummyThread(Thread): + + def __init__(self): + Thread.__init__(self, name=_newname("Dummy-%d")) + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + + def _set_daemon(self): + return True + + def join(self, timeout=None): + assert False, "cannot join a dummy thread" + + +# Global API functions + +def currentThread(): + try: + return _active[_get_ident()] + except KeyError: + ##print "currentThread(): no current thread for", _get_ident() + return _DummyThread() + +def activeCount(): + _active_limbo_lock.acquire() + count = len(_active) + len(_limbo) + _active_limbo_lock.release() + return count + +def enumerate(): + _active_limbo_lock.acquire() + active = _active.values() + _limbo.values() + _active_limbo_lock.release() + return active + +# Create the main thread object + +_MainThread() + +# get thread-local implementation, either from the thread +# module, or from the python fallback + +try: + from thread import _local as local +except ImportError: + from _threading_local import local + + +# Self-test code + +def _test(): + + class BoundedQueue(_Verbose): + + def __init__(self, limit): + _Verbose.__init__(self) + self.mon = RLock() + self.rc = Condition(self.mon) + self.wc = Condition(self.mon) + self.limit = limit + self.queue = deque() + + def put(self, item): + self.mon.acquire() + while len(self.queue) >= self.limit: + self._note("put(%s): queue full", item) + self.wc.wait() + self.queue.append(item) + self._note("put(%s): appended, length now %d", + item, len(self.queue)) + self.rc.notify() + self.mon.release() + + def get(self): + self.mon.acquire() + while not self.queue: + self._note("get(): queue empty") + self.rc.wait() + item = self.queue.popleft() + self._note("get(): got %s, %d left", item, len(self.queue)) + self.wc.notify() + self.mon.release() + return item + + class ProducerThread(Thread): + + def __init__(self, queue, quota): + Thread.__init__(self, name="Producer") + self.queue = queue + self.quota = quota + + def run(self): + from random import random + counter = 0 + while counter < self.quota: + counter = counter + 1 + self.queue.put("%s.%d" % (self.getName(), counter)) + _sleep(random() * 0.00001) + + + class ConsumerThread(Thread): + + def __init__(self, queue, count): + Thread.__init__(self, name="Consumer") + self.queue = queue + self.count = count + + def run(self): + while self.count > 0: + item = self.queue.get() + print item + self.count = self.count - 1 + + NP = 3 + QL = 4 + NI = 5 + + Q = BoundedQueue(QL) + P = [] + for i in range(NP): + t = ProducerThread(Q, NI) + t.setName("Producer-%d" % (i+1)) + P.append(t) + C = ConsumerThread(Q, NI*NP) + for t in P: + t.start() + _sleep(0.000001) + C.start() + for t in P: + t.join() + C.join() + +if __name__ == '__main__': + _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block.py b/gnuradio-core/src/python/gnuradio/gr/hier_block.py new file mode 100644 index 00000000..d669d717 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/hier_block.py @@ -0,0 +1,132 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio_swig_python import io_signature +import weakref + +class hier_block_base(object): + """ + Abstract base class for hierarchical signal processing blocks. + """ + def __init__(self, fg): + """ + @param fg: The flow graph that contains this hierarchical block. + @type fg: gr.flow_graph + """ + self.fg = weakref.proxy(fg) + + def input_signature(self): + """ + @return input signature of hierarchical block. + @rtype gr.io_signature + """ + raise NotImplemented + + def output_signature(self): + """ + @return output signature of hierarchical block. + @rtype gr.io_signature + """ + raise NotImplemented + + def resolve_input_port(self, port_number): + """ + @param port_number: which input port number to resolve to an endpoint. + @type port_number: int + @return: sequence of endpoints + @rtype: sequence of endpoint + + Note that an input port can resolve to more than one endpoint. + """ + raise NotImplemented + + def resolve_output_port(self, port_number): + """ + @param port_number: which output port number to resolve to an endpoint. + @type port_number: int + @return: endpoint + @rtype: endpoint + + Output ports resolve to a single endpoint. + """ + raise NotImplemented + + +class hier_block(hier_block_base): + """ + Simple concrete class for building hierarchical blocks. + + This class assumes that there is at most a single block at the + head of the chain and a single block at the end of the chain. + Either head or tail may be None indicating a sink or source respectively. + + If you needs something more elaborate than this, derive a new class from + hier_block_base. + """ + def __init__(self, fg, head_block, tail_block): + """ + @param fg: The flow graph that contains this hierarchical block. + @type fg: flow_graph + @param head_block: the first block in the signal processing chain. + @type head_block: None or subclass of gr.block or gr.hier_block_base + @param tail_block: the last block in the signal processing chain. + @type tail_block: None or subclass of gr.block or gr.hier_block_base + """ + hier_block_base.__init__(self, fg) + # FIXME add type checks here for easier debugging of misuse + self.head = head_block + self.tail = tail_block + + def input_signature(self): + if self.head: + return self.head.input_signature() + else: + return io_signature(0,0,0) + + def output_signature(self): + if self.tail: + return self.tail.output_signature() + else: + return io_signature(0,0,0) + + def resolve_input_port(self, port_number): + return ((self.head, port_number),) + + def resolve_output_port(self, port_number): + return (self.tail, port_number) + + +class compose(hier_block): + """ + Compose one or more blocks (primitive or hierarchical) into a new hierarchical block. + """ + def __init__(self, fg, *blocks): + """ + @param fg: flow graph + @type fg: gr.flow_graph + @param *blocks: list of blocks + @type *blocks: list of blocks + """ + if len(blocks) < 1: + raise ValueError, ("compose requires at least one block; none provided.") + if len(blocks) > 1: + fg.connect(*blocks) + hier_block.__init__(self, fg, blocks[0], blocks[-1]) diff --git a/gnuradio-core/src/python/gnuradio/gr/prefs.py b/gnuradio-core/src/python/gnuradio/gr/prefs.py new file mode 100644 index 00000000..fa129127 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/prefs.py @@ -0,0 +1,129 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import gnuradio_swig_python as gsp +_prefs_base = gsp.gr_prefs + + +import ConfigParser +import os +import os.path +import sys + + +def _user_prefs_filename(): + return os.path.expanduser('~/.gnuradio/config.conf') + +def _sys_prefs_dirname(): + return os.path.join(gsp.prefix(), 'etc/gnuradio/conf.d') + +def _bool(x): + """ + Try to coerce obj to a True or False + """ + if isinstance(x, bool): + return x + if isinstance(x, (float, int)): + return bool(x) + raise TypeError, x + + +class _prefs(_prefs_base): + """ + Derive our 'real class' from the stubbed out base class that has support + for SWIG directors. This allows C++ code to magically and transparently + invoke the methods in this python class. + """ + def __init__(self): + _prefs_base.__init__(self) + self.cp = ConfigParser.RawConfigParser() + + def _sys_prefs_filenames(self): + dir = _sys_prefs_dirname() + try: + fnames = os.listdir(dir) + except (IOError, OSError): + return [] + fnames.sort() + return [os.path.join(dir, f) for f in fnames] + + + def _read_files(self): + filenames = self._sys_prefs_filenames() + filenames.append(_user_prefs_filename()) + #print "filenames: ", filenames + self.cp.read(filenames) + + def __getattr__(self, name): + return getattr(self.cp, name) + + # ---------------------------------------------------------------- + # These methods override the C++ virtual methods of the same name + # ---------------------------------------------------------------- + def has_section(self, section): + return self.cp.has_section(section) + + def has_option(self, section, option): + return self.cp.has_option(section, option) + + def get_string(self, section, option, default_val): + try: + return self.cp.get(section, option) + except: + return default_val + + def get_bool(self, section, option, default_val): + try: + return self.cp.getboolean(section, option) + except: + return default_val + + def get_long(self, section, option, default_val): + try: + return self.cp.getint(section, option) + except: + return default_val + + def get_double(self, section, option, default_val): + try: + return self.cp.getfloat(section, option) + except: + return default_val + # ---------------------------------------------------------------- + # End override of C++ virtual methods + # ---------------------------------------------------------------- + + +_prefs_db = _prefs() + +# if GR_DONT_LOAD_PREFS is set, don't load them. +# (make check uses this to avoid interactions.) +if os.getenv("GR_DONT_LOAD_PREFS", None) is None: + _prefs_db._read_files() + + +_prefs_base.set_singleton(_prefs_db) # tell C++ what instance to use + +def prefs(): + """ + Return the global preference data base + """ + return _prefs_db diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py b/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py new file mode 100755 index 00000000..6cb74e9f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ff (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_f (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_f () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_cc (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_c (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_c () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_add_const_ii (self): + src_data = (1, 2, 3, 4, 5) + expected_result = (6, 7, 8, 9, 10) + op = gr.add_const_ii (5) + self.help_ii ((src_data,), expected_result, op) + + def test_add_const_cc (self): + src_data = (1, 2, 3, 4, 5) + expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + op = gr.add_const_cc (5j) + self.help_cc ((src_data,), expected_result, op) + + def test_mult_const_ii (self): + src_data = (-1, 0, 1, 2, 3) + expected_result = (-5, 0, 5, 10, 15) + op = gr.multiply_const_ii (5) + self.help_ii ((src_data,), expected_result, op) + + def test_add_ii (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (9, -1, 7, 12, 7) + op = gr.add_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_mult_ii (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (8, -6, 12, 32, 10) + op = gr.multiply_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_sub_ii_1 (self): + src1_data = (1, 2, 3, 4, 5) + expected_result = (-1, -2, -3, -4, -5) + op = gr.sub_ii () + self.help_ii ((src1_data,), + expected_result, op) + + def test_sub_ii_2 (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (-7, 5, -1, -4, 3) + op = gr.sub_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_div_ff_1 (self): + src1_data = (1, 2, 4, -8) + expected_result = (1, 0.5, 0.25, -.125) + op = gr.divide_ff () + self.help_ff ((src1_data,), + expected_result, op) + + def test_div_ff_2 (self): + src1_data = ( 5, 9, -15, 1024) + src2_data = (10, 3, -5, 64) + expected_result = (0.5, 3, 3, 16) + op = gr.divide_ff () + self.help_ff ((src1_data, src2_data), + expected_result, op) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py b/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py new file mode 100755 index 00000000..11e69e37 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py @@ -0,0 +1,353 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_add_v_and_friends(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def help_ss(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_s(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_short, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_short, size) + dst = gr.vector_sink_s() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_ii(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_i(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_int, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_int, size) + dst = gr.vector_sink_i() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_ff(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_f(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_float, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_float, size) + dst = gr.vector_sink_f() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_cc(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_c(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_gr_complex, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_gr_complex, size) + dst = gr.vector_sink_c() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ss(self, src_data, exp_data, op): + src = gr.vector_source_s(src_data) + srcv = gr.stream_to_vector(gr.sizeof_short, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_short, len(src_data)) + dst = gr.vector_sink_s() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ii(self, src_data, exp_data, op): + src = gr.vector_source_i(src_data) + srcv = gr.stream_to_vector(gr.sizeof_int, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_int, len(src_data)) + dst = gr.vector_sink_i() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ff(self, src_data, exp_data, op): + src = gr.vector_source_f(src_data) + srcv = gr.stream_to_vector(gr.sizeof_float, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_float, len(src_data)) + dst = gr.vector_sink_f() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_cc(self, src_data, exp_data, op): + src = gr.vector_source_c(src_data) + srcv = gr.stream_to_vector(gr.sizeof_gr_complex, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_gr_complex, len(src_data)) + dst = gr.vector_sink_c() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + + def test_add_vss_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.add_vss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vss_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = gr.add_vss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vii_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.add_vii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vii_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = gr.add_vii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vff_one(self): + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = gr.add_vff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vff_five(self): + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (18.0, 21.0, 24.0, 27.0, 30.0) + op = gr.add_vff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vcc_one(self): + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (9.0+12j,) + op = gr.add_vcc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vcc_five(self): + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (33.0+36.0j, 39.0+42.0j, 45.0+48.0j, 51.0+54.0j, 57.0+60.0j) + op = gr.add_vcc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_const_vss_one(self): + src_data = (1,) + op = gr.add_const_vss((2,)) + exp_data = (3,) + self.help_const_ss(src_data, exp_data, op) + + def test_add_const_vss_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.add_const_vss((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ss(src_data, exp_data, op) + + def test_add_const_vii_one(self): + src_data = (1,) + op = gr.add_const_vii((2,)) + exp_data = (3,) + self.help_const_ii(src_data, exp_data, op) + + def test_add_const_vii_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.add_const_vii((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ii(src_data, exp_data, op) + + def test_add_const_vff_one(self): + src_data = (1.0,) + op = gr.add_const_vff((2.0,)) + exp_data = (3.0,) + self.help_const_ff(src_data, exp_data, op) + + def test_add_const_vff_five(self): + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = gr.add_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (7.0, 9.0, 11.0, 13.0, 15.0) + self.help_const_ff(src_data, exp_data, op) + + def test_add_const_vcc_one(self): + src_data = (1.0+2.0j,) + op = gr.add_const_vcc((2.0+3.0j,)) + exp_data = (3.0+5.0j,) + self.help_const_cc(src_data, exp_data, op) + + def test_add_const_vcc_five(self): + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = gr.add_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (12.0+14.0j, 16.0+18.0j, 20.0+22.0j, 24.0+26.0j, 28.0+30.0j) + self.help_const_cc(src_data, exp_data, op) + + + def test_multiply_vss_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.multiply_vss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vss_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = gr.multiply_vss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vii_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.multiply_vii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vii_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = gr.multiply_vii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vff_one(self): + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = gr.multiply_vff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vff_five(self): + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (66.0, 168.0, 312.0, 504.0, 750.0) + op = gr.multiply_vff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vcc_one(self): + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (-85+20j,) + op = gr.multiply_vcc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vcc_five(self): + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (-1021.0+428.0j, -2647.0+1754.0j, -4945.0+3704.0j, -8011.0+6374.0j, -11941.0+9860.0j) + op = gr.multiply_vcc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_const_vss_one(self): + src_data = (2,) + op = gr.multiply_const_vss((3,)) + exp_data = (6,) + self.help_const_ss(src_data, exp_data, op) + + def test_multiply_const_vss_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.multiply_const_vss((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ss(src_data, exp_data, op) + + def test_multiply_const_vii_one(self): + src_data = (2,) + op = gr.multiply_const_vii((3,)) + exp_data = (6,) + self.help_const_ii(src_data, exp_data, op) + + def test_multiply_const_vii_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.multiply_const_vii((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ii(src_data, exp_data, op) + + def test_multiply_const_vff_one(self): + src_data = (2.0,) + op = gr.multiply_const_vff((3.0,)) + exp_data = (6.0,) + self.help_const_ff(src_data, exp_data, op) + + def test_multiply_const_vff_five(self): + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = gr.multiply_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (6.0, 14.0, 24.0, 36.0, 50.0) + self.help_const_ff(src_data, exp_data, op) + + def test_multiply_const_vcc_one(self): + src_data = (1.0+2.0j,) + op = gr.multiply_const_vcc((2.0+3.0j,)) + exp_data = (-4.0+7.0j,) + self.help_const_cc(src_data, exp_data, op) + + def test_multiply_const_vcc_five(self): + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = gr.multiply_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (-13.0+34.0j, -17.0+94.0j, -21.0+170.0j, -25.0+262.0j, -29.0+370.0j) + self.help_const_cc(src_data, exp_data, op) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py new file mode 100755 index 00000000..0799c72e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + + +# ---------------------------------------------------------------- + + +class test_basic_flow_graph (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.basic_flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_create_delete (self): + pass + + def test_001a_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (gr.endpoint (src1, 0), gr.endpoint (dst1, 0)) + + def test_001b_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, gr.endpoint (dst1, 0)) + + def test_001c_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (gr.endpoint (src1, 0), dst1) + + def test_001d_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, dst1) + + def test_001e_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + + def test_002_dst_in_use (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + self.assertRaises (ValueError, + lambda : fg.connect ((src2, 0), + (dst1, 0))) + + def test_003_no_such_src_port (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + self.assertRaises (ValueError, + lambda : fg.connect ((src1, 1), + (dst1, 0))) + + def test_004_no_such_dst_port (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + self.assertRaises (ValueError, + lambda : fg.connect ((src1, 0), + (dst1, 1))) + + def test_005_one_src_two_dst (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + fg.connect ((src1, 0), (dst2, 0)) + + def test_006_check_item_sizes (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_char) + self.assertRaises (ValueError, + lambda : fg.connect ((src1, 0), + (dst1, 0))) + + def test_007_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + fg.connect ((src1, 0), (dst2, 0)) + fg.validate () + + def test_008_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 1)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 1), (dst2, 0)) + fg.validate () + + def test_009_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 2)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 1), (dst2, 0)) + self.assertRaises (ValueError, + lambda : fg.validate ()) + + + def test_010_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 1)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 2), (dst2, 0)) + self.assertRaises (ValueError, + lambda : fg.validate ()) + + + def test_011_disconnect (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 1)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 1), (dst2, 0)) + fg.validate () + fg.disconnect ((src1, 0), (nop1, 1)) + fg.validate () + self.assertRaises (ValueError, + lambda : fg.disconnect ((src1, 0), + (nop1, 1))) + + def test_012_connect (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (2, 3, 4, 5) + src1 = gr.vector_source_i (src_data) + op = gr.add_const_ii (2) + dst1 = gr.vector_sink_i () + fg.connect (src1, op) + fg.connect (op, dst1) + # print "edge_list:", fg.edge_list + fg.validate () + + def test_013_connect_varargs (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + self.assertRaises (ValueError, + lambda : fg.connect ()) + self.assertRaises (ValueError, + lambda : fg.connect (src1)) + + def test_014_connect_varargs (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, nop1, dst1) + fg.validate () + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py b/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py new file mode 100755 index 00000000..6b3e9aa9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + +class test_cma_equalizer_fir(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def transform(self, src_data): + SRC = gr.vector_source_c(src_data, False) + EQU = gr.cma_equalizer_cc(4, 1.0, .001) + DST = gr.vector_sink_c() + self.fg.connect(SRC, EQU, DST) + self.fg.run() + return DST.data() + + def test_001_identity(self): + # Constant modulus signal so no adjustments + src_data = (1+0j, 0+1j, -1+0j, 0-1j)*1000 + expected_data = src_data + result = self.transform(src_data) + self.assertComplexTuplesAlmostEqual(expected_data, result) + +if __name__ == "__main__": + gr_unittest.main() \ No newline at end of file diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py b/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py new file mode 100755 index 00000000..4bc19335 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_complex_ops (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_complex_to_float_1 (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, -1, 3, -3, -3) + src = gr.vector_source_c (src_data) + op = gr.complex_to_float () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_complex_to_float_2 (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result0 = (0, 1, -1, 3, -3, -3) + expected_result1 = (0, 0, 0, 4, -4, 4) + src = gr.vector_source_c (src_data) + op = gr.complex_to_float () + dst0 = gr.vector_sink_f () + dst1 = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect ((op, 0), dst0) + self.fg.connect ((op, 1), dst1) + self.fg.run () + actual_result = dst0.data () + self.assertFloatTuplesAlmostEqual (expected_result0, actual_result) + actual_result = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result1, actual_result) + + def test_complex_to_real (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, -1, 3, -3, -3) + src = gr.vector_source_c (src_data) + op = gr.complex_to_real () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_complex_to_imag (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 0, 0, 4, -4, 4) + src = gr.vector_source_c (src_data) + op = gr.complex_to_imag () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_mag (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, 1, 5, 5, 5) + src = gr.vector_source_c (src_data) + op = gr.complex_to_mag () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_arg (self): + pi = math.pi + expected_result = (0, pi/6, pi/4, pi/2, 3*pi/4, 7*pi/8, + -pi/6, -pi/4, -pi/2, -3*pi/4, -7*pi/8) + src_data = tuple ([math.cos (x) + math.sin (x) * 1j for x in expected_result]) + src = gr.vector_source_c (src_data) + op = gr.complex_to_arg () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 5) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py b/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py new file mode 100755 index 00000000..95641222 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_constellation_decoder_cb (self): + symbol_positions = [1 + 0j, 0 + 1j , -1 + 0j, 0 - 1j] + symbol_values_out = [0, 1, 2, 3] + expected_result = ( 0, 3, 2, 1, 0, 0, 3) + src_data = (0.5 + 0j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, 0.8 - 0j, 0.5 + 0j, 0.1 - 1.2j) + src = gr.vector_source_c (src_data) + op = gr.constellation_decoder_cb (symbol_positions, symbol_values_out) + dst = gr.vector_sink_b () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py b/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py new file mode 100755 index 00000000..89b4909e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +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_correlate_access_code(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def test_001(self): + pad = (0,) * 64 + # 0 0 0 1 0 0 0 1 + 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 = gr.correlate_access_code_bb("1011", 0) + dst = gr.vector_sink_b () + self.fg.connect (src, op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + + def test_002(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 = pad + code + (3, 0, 1, 1) + src = gr.vector_source_b (src_data) + op = gr.correlate_access_code_bb(access_code, 0) + dst = gr.vector_sink_b () + self.fg.connect (src, op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py new file mode 100755 index 00000000..44840709 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math +import random + +def make_random_int_tuple(L, min, max): + result = [] + for x in range(L): + result.append(random.randint(min, max)) + return tuple(result) + + +class test_encoder (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_diff_encdec_000(self): + random.seed(0) + modulus = 2 + src_data = make_random_int_tuple(1000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = gr.diff_encoder_bb(modulus) + dec = gr.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.fg.connect(src, enc, dec, dst) + self.fg.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + + def test_diff_encdec_001(self): + random.seed(0) + modulus = 4 + src_data = make_random_int_tuple(1000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = gr.diff_encoder_bb(modulus) + dec = gr.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.fg.connect(src, enc, dec, dst) + self.fg.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + + def test_diff_encdec_002(self): + random.seed(0) + modulus = 8 + src_data = make_random_int_tuple(40000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = gr.diff_encoder_bb(modulus) + dec = gr.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.fg.connect(src, enc, dec, dst) + self.fg.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.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py new file mode 100755 index 00000000..0b716020 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_complex_ops (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_diff_phasor_cc (self): + src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j) + expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j) + src = gr.vector_source_c (src_data) + op = gr.diff_phasor_cc () + dst = gr.vector_sink_c () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.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.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_feval.py b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py new file mode 100755 index 00000000..1de49369 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class my_add2_dd(gr.feval_dd): + def eval(self, x): + return x + 2 + +class my_add2_ll(gr.feval_ll): + def eval(self, x): + return x + 2 + +class my_add2_cc(gr.feval_cc): + def eval(self, x): + return x + (2 - 2j) + + +class test_feval(gr_unittest.TestCase): + + def test_dd_1(self): + f = my_add2_dd() + src_data = (0.0, 1.0, 2.0, 3.0, 4.0) + expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_dd_2(self): + f = my_add2_dd() + src_data = (0.0, 1.0, 2.0, 3.0, 4.0) + expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_dd_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + + def test_ll_1(self): + f = my_add2_ll() + src_data = (0, 1, 2, 3, 4) + expected_result = (2, 3, 4, 5, 6) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_ll_2(self): + f = my_add2_ll() + src_data = (0, 1, 2, 3, 4) + expected_result = (2, 3, 4, 5, 6) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_ll_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + + def test_cc_1(self): + f = my_add2_cc() + src_data = (0+1j, 2+3j, 4+5j, 6+7j) + expected_result = (2-1j, 4+1j, 6+3j, 8+5j) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_cc_2(self): + f = my_add2_cc() + src_data = (0+1j, 2+3j, 4+5j, 6+7j) + expected_result = (2-1j, 4+1j, 6+3j, 8+5j) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_cc_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py new file mode 100755 index 00000000..cb2e76b1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py @@ -0,0 +1,268 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import sys +import random + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.uniform(-1000,1000), + random.uniform(-1000,1000))) + return tuple(result) + +def make_random_float_tuple(L): + result = [] + for x in range(L): + result.append(float(int(random.uniform(-1000,1000)))) + return tuple(result) + + +def reference_filter_ccc(dec, taps, input): + """ + compute result using conventional fir filter + """ + fg = gr.flow_graph() + #src = gr.vector_source_c(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_c(input) + op = gr.fir_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + fg.connect(src, op, dst) + fg.run() + return dst.data() + +def reference_filter_fff(dec, taps, input): + """ + compute result using conventional fir filter + """ + fg = gr.flow_graph() + #src = gr.vector_source_f(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_f(input) + op = gr.fir_filter_fff(dec, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + return dst.data() + + +def print_complex(x): + for i in x: + i = complex(i) + sys.stdout.write("(%6.3f,%6.3fj), " % (i.real, i.imag)) + sys.stdout.write('\n') + + +class test_fft_filter(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def assert_fft_ok2(self, expected_result, result_data): + expected_result = expected_result[:len(result_data)] + self.assertComplexTuplesAlmostEqual2 (expected_result, result_data, + abs_eps=1e-9, rel_eps=4e-4) + + def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4): + expected_result = expected_result[:len(result_data)] + self.assertFloatTuplesAlmostEqual2 (expected_result, result_data, + abs_eps, rel_eps) + + #def test_ccc_000(self): + # self.assertRaises (RuntimeError, gr.fft_filter_ccc, 2, (1,)) + + def test_ccc_001(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_ccc_002(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_ccc_004(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(1, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + def test_ccc_005(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + # ---------------------------------------------------------------- + # test _fff version + # ---------------------------------------------------------------- + + def test_fff_001(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_fff_002(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def xtest_fff_003(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4096 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + #print "src_len =", src_len, " ntaps =", ntaps + try: + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=1.0) + except: + expected = open('expected', 'w') + for x in expected_result: + expected.write(`x` + '\n') + actual = open('actual', 'w') + for x in result_data: + actual.write(`x` + '\n') + raise + + def xtest_fff_004(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0) + + def xtest_fff_005(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(dec, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py b/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py new file mode 100755 index 00000000..191552ca --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class qa_filter_delay_fc (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001_filter_delay_one_input (self): + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + fg = self.fg + + sampling_freq = 100 + + ntaps = 51 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c () + + # calculate taps + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + fg.connect (src1, head) + fg.connect (head, hd) + fg.connect (hd,dst2) + + fg.run () + + # get output + result_data = dst2.data () + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_002_filter_delay_two_inputs (self): + + # giving the same signal to both the inputs should fetch the same results + # as above + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + fg = self.fg + + sampling_freq = 100 + ntaps = 51 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c () + + + # calculate taps + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + fg.connect (src1, head) + fg.connect (head, (hd,0)) + fg.connect (head, (hd,1)) + fg.connect (hd,dst2) + fg.run () + + # get output + result_data = dst2.data () + + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_003_filter_delay_two_inputs (self): + + # give two different inputs + + # expected result + expected_result = ( -0.0020331963896751404j, + -0.0016448829555884004j, + -0.0032375147566199303j, + -0.0014826074475422502j, + -0.0033034090884029865j, + -0.00051144487224519253j, + -0.0043686260469257832j, + -0.0010198024101555347j, + -0.0082517862319946289j, + -0.003456643782556057j, + -0.014193611219525337j, + -0.005875137634575367j, + -0.020293503999710083j, + -0.0067503536120057106j, + -0.026798896491527557j, + -0.0073488112539052963j, + -0.037041611969470978j, + -0.010557252913713455j, + -0.055669989436864853j, + -0.018332764506340027j, + -0.089904911816120148j, + -0.033361352980136871j, + -0.16902604699134827j, + -0.074318811297416687j, + -0.58429563045501709j, + (7.2191945754696007e-09 -0.35892376303672791j), + (0.58778399229049683 +0.63660913705825806j), + (0.95105588436126709 +0.87681591510772705j), + (0.95105588436126709 +0.98705857992172241j), + (0.5877838134765625 +0.55447429418563843j), + (5.8516356205018383e-09 +0.026006083935499191j), + (-0.5877840518951416 -0.60616838932037354j), + (-0.95105588436126709 -0.9311758279800415j), + (-0.95105588436126709 -0.96169203519821167j), + (-0.5877838134765625 -0.57292771339416504j), + (-8.7774534307527574e-09 -0.0073488391935825348j), + (0.58778399229049683 +0.59720659255981445j), + (0.95105588436126709 +0.94438445568084717j), + (0.95105588436126709 +0.95582199096679688j), + (0.5877838134765625 +0.58196049928665161j), + (1.4629089051254596e-08 +0.0026587247848510742j), + (-0.5877840518951416 -0.59129220247268677j), + (-0.95105588436126709 -0.94841635227203369j), + (-0.95105588436126709 -0.95215457677841187j), + (-0.5877838134765625 -0.58535969257354736j), + (-1.7554906861505515e-08 -0.00051158666610717773j), + (0.58778399229049683 +0.58867418766021729j), + (0.95105582475662231 +0.94965213537216187j), + (0.95105588436126709 +0.95050644874572754j), + (0.5877838134765625 +0.58619076013565063j), + (2.3406542482007353e-08 +1.1920928955078125e-07j), + (-0.5877840518951416 -0.58783555030822754j), + (-0.95105588436126709 -0.95113480091094971j), + (-0.95105588436126709 -0.95113474130630493j), + (-0.5877838134765625 -0.58783555030822754j), + (-2.6332360292258272e-08 -8.1956386566162109e-08j), + (0.58778399229049683 +0.58783555030822754j), + (0.95105582475662231 +0.95113474130630493j), + (0.95105588436126709 +0.95113474130630493j), + (0.5877838134765625 +0.58783560991287231j), + (3.218399768911695e-08 +1.1920928955078125e-07j)) + + fg = self.fg + + sampling_freq = 100 + ntaps = 51 + + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE,sampling_freq * 0.10, 1.0) + src2 = gr.sig_source_f (sampling_freq, gr.GR_COS_WAVE,sampling_freq * 0.10, 1.0) + + head1 = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + head2 = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + dst2 = gr.vector_sink_c () + + fg.connect (src1, head1) + fg.connect (src2, head2) + + fg.connect (head1, (hd,0)) + fg.connect (head2, (hd,1)) + fg.connect (hd, dst2) + + fg.run () + + # get output + result_data = dst2.data () + + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py new file mode 100755 index 00000000..455cc135 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py @@ -0,0 +1,356 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import qa_basic_flow_graph + + +def all_counts (): + return (gr.block_ncurrently_allocated (), + gr.block_detail_ncurrently_allocated (), + gr.buffer_ncurrently_allocated (), + gr.buffer_reader_ncurrently_allocated ()) + + +class wrap_add(gr.hier_block): + def __init__(self, fg, a): + add = gr.add_const_ii (a) + gr.hier_block.__init__ (self, fg, add, add) + +class mult_add(gr.hier_block): + def __init__(self, fg, m, a): + mult = gr.multiply_const_ii (m) + add = gr.add_const_ii (a) + fg.connect (mult, add) + gr.hier_block.__init__ (self, fg, mult, add) + + +class test_flow_graph (qa_basic_flow_graph.test_basic_flow_graph): + + def setUp (self): + ''' override qa_basic_flow_graph setUp in order to use our class''' + self.fg = gr.flow_graph () + + def tearDown (self): + qa_basic_flow_graph.test_basic_flow_graph.tearDown (self) + + + # we inherit all their tests, so we can be sure we don't break + # any of the underlying code + + + def leak_check (self, fct): + begin = all_counts () + fct () + # tear down early so we can check for leaks + self.tearDown () + end = all_counts () + self.assertEqual (begin, end) + + def test_100_tsort_null (self): + self.assertEqual ([], self.fg.topological_sort (self.fg.all_blocks ())) + + def test_101_tsort_two (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + fg.validate () + self.assertEqual ([src1, dst1], fg.topological_sort (fg.all_blocks ())) + + def test_102_tsort_three_a (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, nop1) + fg.connect (nop1, dst1) + fg.validate () + self.assertEqual ([src1, nop1, dst1], fg.topological_sort (fg.all_blocks ())) + + def test_103_tsort_three_b (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (nop1, dst1) + fg.connect (src1, nop1) + fg.validate () + self.assertEqual ([src1, nop1, dst1], fg.topological_sort (fg.all_blocks ())) + + def test_104_trivial_dag_check (self): + fg = self.fg + nop1 = gr.nop (gr.sizeof_int) + fg.connect (nop1, nop1) + fg.validate () + self.assertRaises (gr.NotDAG, + lambda : fg.topological_sort (fg.all_blocks ())) + + def test_105 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + + fg.connect (src1, nop1) + fg.connect (src2, nop2) + fg.connect (nop1, (nop3, 0)) + fg.connect (nop2, (nop3, 1)) + fg.connect (nop3, dst1) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, src1, nop1, nop3, dst1], ts) + + + def test_106 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + + fg.connect (nop3, dst1) + fg.connect (nop2, (nop3, 1)) + fg.connect (nop1, (nop3, 0)) + fg.connect (src2, nop2) + fg.connect (src1, nop1) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, src1, nop1, nop3, dst1], ts) + + def test_107 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + + fg.connect (src1, nop1) + fg.connect (nop1, dst1) + fg.connect (src2, nop2) + fg.connect (nop2, dst2) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, dst2, src1, nop1, dst1], ts) + + def test_108 (self): + self.leak_check (self.body_108) + + def body_108 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + + fg.connect (nop2, dst2) + fg.connect (src1, nop1) + fg.connect (src2, nop2) + fg.connect (nop1, dst1) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, dst2, src1, nop1, dst1], ts) + self.assertEqual ((6,0,0,0), all_counts ()) + + def test_109__setup_connections (self): + self.leak_check (self.body_109) + + def body_109 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, dst1) + fg._setup_connections () + self.assertEqual ((2,2,1,1), all_counts ()) + + def test_110_scheduler (self): + self.leak_check (self.body_110) + + def body_110 (self): + fg = self.fg + src_data = (0, 1, 2, 3) + src1 = gr.vector_source_i (src_data) + dst1 = gr.vector_sink_i () + fg.connect ((src1, 0), (dst1, 0)) + fg.run () + dst_data = dst1.data () + self.assertEqual (src_data, dst_data) + + def test_111_scheduler (self): + self.leak_check (self.body_111) + + def body_111 (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (2, 3, 4, 5) + src1 = gr.vector_source_i (src_data) + op = gr.add_const_ii (2) + dst1 = gr.vector_sink_i () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_111v_scheduler (self): + self.leak_check (self.body_111v) + + def body_111v (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (2, 3, 4, 5) + src1 = gr.vector_source_i (src_data) + op = gr.add_const_ii (2) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_112 (self): + fg = self.fg + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + fg.connect ((nop1, 0), (nop2, 0)) + fg.connect ((nop1, 1), (nop3, 0)) + fg._setup_connections () + self.assertEqual (2, nop1.detail().noutputs()) + + def test_113 (self): + fg = self.fg + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + fg.connect ((nop1, 0), (nop2, 0)) + fg.connect ((nop1, 0), (nop3, 0)) + fg._setup_connections () + self.assertEqual (1, nop1.detail().noutputs()) + + def test_200_partition (self): + self.leak_check (self.body_200) + + def body_200 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (nop1, dst1) + fg.connect (src1, nop1) + fg.validate () + p = fg.partition_graph (fg.all_blocks ()) + self.assertEqual ([[src1, nop1, dst1]], p) + self.assertEqual ((3,0,0,0), all_counts ()) + + def test_201_partition (self): + self.leak_check (self.body_201) + + def body_201 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + + fg.connect (nop2, dst2) + fg.connect (src1, nop1) + fg.connect (src2, nop2) + fg.connect (nop1, dst1) + fg.validate () + p = fg.partition_graph (fg.all_blocks ()) + self.assertEqual ([[src2, nop2, dst2], [src1, nop1, dst1]], p) + self.assertEqual ((6,0,0,0), all_counts ()) + + def test_300_hier (self): + self.leak_check (self.body_300_hier) + + def body_300_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (10, 11, 12, 13) + src1 = gr.vector_source_i (src_data) + op = wrap_add (fg, 10) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_301_hier (self): + self.leak_check (self.body_301_hier) + + def body_301_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (5, 8, 11, 14) + src1 = gr.vector_source_i (src_data) + op = mult_add (fg, 3, 5) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_302_hier (self): + self.leak_check (self.body_302_hier) + + def body_302_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (10, 11, 12, 13) + src1 = gr.vector_source_i (src_data) + op = gr.compose (fg, gr.add_const_ii (10)) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_303_hier (self): + self.leak_check (self.body_303_hier) + + def body_303_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (35, 38, 41, 44) + src1 = gr.vector_source_i (src_data) + op = gr.compose (fg, gr.add_const_ii (10), mult_add (fg, 3, 5)) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py b/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py new file mode 100755 index 00000000..cfa34830 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +def sincos(x): + return math.cos(x) + math.sin(x) * 1j + + +class test_frequency_modulator (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_fm_001 (self): + pi = math.pi + sensitivity = pi/4 + src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0) + running_sum = (pi/16, 3*pi/16, pi/4, 3*pi/16, pi/16, 0) + expected_result = tuple ([sincos (x) for x in running_sum]) + src = gr.vector_source_f (src_data) + op = gr.frequency_modulator_fc (sensitivity) + dst = gr.vector_sink_c () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py new file mode 100755 index 00000000..d61ddb1a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +def sincos(x): + return math.cos(x) + math.sin(x) * 1j + +class test_bytes_to_syms (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_bytes_to_syms_001 (self): + src_data = (0x01, 0x80, 0x03) + expected_result = (-1, -1, -1, -1, -1, -1, -1, +1, + +1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, +1, +1) + src = gr.vector_source_b (src_data) + op = gr.bytes_to_syms () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + def test_simple_framer (self): + src_data = (0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff) + + expected_result = ( + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x00, 0x00, 0x11, 0x22, 0x33, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x01, 0x44, 0x55, 0x66, 0x77, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x02, 0x88, 0x99, 0xaa, 0xbb, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x03, 0xcc, 0xdd, 0xee, 0xff, 0x55) + + src = gr.vector_source_b (src_data) + op = gr.simple_framer (4) + dst = gr.vector_sink_b () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py b/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py new file mode 100755 index 00000000..da9d65f6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +from math import pi, cos + +class test_goertzel(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = 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 = gr.goertzel_fc(rate, rate, freq) + dst = gr.vector_sink_c() + self.fg.connect(src, dft, dst) + self.fg.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=5) + + 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=5) + +if __name__ == '__main__': + gr_unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_head.py b/gnuradio-core/src/python/gnuradio/gr/qa_head.py new file mode 100755 index 00000000..a6fcd7f9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_head.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_head (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = (1, 2, 3, 4) + src1 = gr.vector_source_i (src_data) + op = gr.head (gr.sizeof_int, 4) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op) + self.fg.connect (op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py b/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py new file mode 100755 index 00000000..a8f39dd6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_sig_source (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_hilbert (self): + fg = self.fg + ntaps = 51 + sampling_freq = 100 + + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + hilb = gr.hilbert_fc (ntaps) + dst1 = gr.vector_sink_c () + fg.connect (src1, head) + fg.connect (head, hilb) + fg.connect (hilb, dst1) + fg.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_iir.py b/gnuradio-core/src/python/gnuradio/gr/qa_iir.py new file mode 100755 index 00000000..a1f2aa07 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_iir.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_iir (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_iir_direct_001 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = () + fbtaps = () + expected_result = (0, 0, 0, 0, 0, 0, 0, 0) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_002 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2,) + fbtaps = (0,) + expected_result = (2, 4, 6, 8, 10, 12, 14, 16) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_003 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, 0) + expected_result = (2, 15, 28, 41, 54, 67, 80, 93) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_004 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, -1) + expected_result = (2, 13, 15, 26, 28, 39, 41, 52) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_005 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_006 (self): + fftaps = (2, 11, 0) + fbtaps = (0, -1) + self.assertRaises ((RuntimeError, ValueError), gr.iir_filter_ffd, fftaps, fbtaps) + + def test_iir_direct_007 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + fftaps = (2, 1) + fbtaps = (0, -1) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + op.set_taps (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_008 (self): + fftaps = (2, 1) + fbtaps = (0, -1) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps = (2, 11) + fbtaps = (0, -1, 3) + self.assertRaises ((RuntimeError, ValueError), op.set_taps, fftaps, fbtaps) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py b/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py new file mode 100755 index 00000000..003d12e6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_interleave (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_int_001 (self): + lenx = 64 + src0 = gr.vector_source_f (range (0, lenx, 4)) + src1 = gr.vector_source_f (range (1, lenx, 4)) + src2 = gr.vector_source_f (range (2, lenx, 4)) + src3 = gr.vector_source_f (range (3, lenx, 4)) + op = gr.interleave (gr.sizeof_float) + dst = gr.vector_sink_f () + + self.fg.connect (src0, (op, 0)) + self.fg.connect (src1, (op, 1)) + self.fg.connect (src2, (op, 2)) + self.fg.connect (src3, (op, 3)) + self.fg.connect (op, dst) + self.fg.run () + expected_result = tuple (range (lenx)) + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_deint_001 (self): + lenx = 64 + src = gr.vector_source_f (range (lenx)) + op = gr.deinterleave (gr.sizeof_float) + dst0 = gr.vector_sink_f () + dst1 = gr.vector_sink_f () + dst2 = gr.vector_sink_f () + dst3 = gr.vector_sink_f () + + self.fg.connect (src, op) + self.fg.connect ((op, 0), dst0) + self.fg.connect ((op, 1), dst1) + self.fg.connect ((op, 2), dst2) + self.fg.connect ((op, 3), dst3) + self.fg.run () + + expected_result0 = tuple (range (0, lenx, 4)) + expected_result1 = tuple (range (1, lenx, 4)) + expected_result2 = tuple (range (2, lenx, 4)) + expected_result3 = tuple (range (3, lenx, 4)) + + self.assertFloatTuplesAlmostEqual (expected_result0, dst0.data ()) + self.assertFloatTuplesAlmostEqual (expected_result1, dst1.data ()) + self.assertFloatTuplesAlmostEqual (expected_result2, dst2.data ()) + self.assertFloatTuplesAlmostEqual (expected_result3, dst3.data ()) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py new file mode 100755 index 00000000..4119e3e2 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_interp_fir_filter (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_fff (self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170) + expected_result = tuple ([float (x) for x in xr]) + + src = gr.vector_source_f (src_data) + op = gr.interp_fir_filter_fff (interpolation, taps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + L = min(len(result_data), len(expected_result)) + self.assertEqual (expected_result[0:L], result_data[0:L]) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py new file mode 100755 index 00000000..f5dee152 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math +import random + + +class test_kludge_copy(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + self.rng = random.Random() + self.rng.seed(0) + + def tearDown(self): + self.fg = None + self.rng = None + + def make_random_int_tuple(self, L): + result = [] + for x in range(L): + result.append(self.rng.randint(int(-1e9), int(+1e9))) + return tuple(result) + + + def test_001(self): + # 1 input stream; 1 output stream + src0_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + self.fg.connect(src0, op, dst0) + self.fg.run() + dst0_data = dst0.data() + self.assertEqual(src0_data, dst0_data) + + def test_002(self): + # 2 input streams; 2 output streams + src0_data = self.make_random_int_tuple(16000) + src1_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + src1 = gr.vector_source_i(src1_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + dst1 = gr.vector_sink_i() + self.fg.connect(src0, (op, 0), dst0) + self.fg.connect(src1, (op, 1), dst1) + self.fg.run() + dst0_data = dst0.data() + dst1_data = dst1.data() + self.assertEqual(src0_data, dst0_data) + self.assertEqual(src1_data, dst1_data) + + def test_003(self): + # number of input streams != number of output streams + src0_data = self.make_random_int_tuple(16000) + src1_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + src1 = gr.vector_source_i(src1_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + dst1 = gr.vector_sink_i() + self.fg.connect(src0, (op, 0), dst0) + self.fg.connect(src1, (op, 1)) + self.assertRaises(ValueError, self.fg.run) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py new file mode 100755 index 00000000..b2086772 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_blks_import(self): + # make sure that this somewhat magic import works + from gnuradio import blks + + def test_gru_import(self): + # make sure that this somewhat magic import works + from gnuradio import gru + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_message.py b/gnuradio-core/src/python/gnuradio/gr/qa_message.py new file mode 100755 index 00000000..d5d51114 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_message.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import qa_basic_flow_graph + + +def all_counts (): + return (gr.block_ncurrently_allocated (), + gr.block_detail_ncurrently_allocated (), + gr.buffer_ncurrently_allocated (), + gr.buffer_reader_ncurrently_allocated (), + gr.message_ncurrently_allocated ()) + + +class test_message (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph() + self.msgq = gr.msg_queue () + + def tearDown (self): + self.fg = None + self.msgq = None + + def leak_check (self, fct): + begin = all_counts () + fct () + # tear down early so we can check for leaks + self.tearDown () + end = all_counts () + self.assertEqual (begin, end) + + def test_100 (self): + msg = gr.message (0, 1.5, 2.3) + self.assertEquals (0, msg.type()) + self.assertAlmostEqual (1.5, msg.arg1()) + self.assertAlmostEqual (2.3, msg.arg2()) + self.assertEquals (0, msg.length()) + + def test_101 (self): + s = 'This is a test' + msg = gr.message_from_string(s) + self.assertEquals(s, msg.to_string()) + + def test_200 (self): + self.leak_check (self.body_200) + + def body_200 (self): + self.msgq.insert_tail (gr.message (0)) + self.assertEquals (1, self.msgq.count()) + self.msgq.insert_tail (gr.message (1)) + self.assertEquals (2, self.msgq.count()) + msg0 = self.msgq.delete_head () + self.assertEquals (0, msg0.type()) + msg1 = self.msgq.delete_head () + self.assertEquals (1, msg1.type()) + self.assertEquals (0, self.msgq.count()) + + def test_201 (self): + self.leak_check (self.body_201) + + def body_201 (self): + self.msgq.insert_tail (gr.message (0)) + self.assertEquals (1, self.msgq.count()) + self.msgq.insert_tail (gr.message (1)) + self.assertEquals (2, self.msgq.count()) + + def test_202 (self): + self.leak_check (self.body_202) + + def body_202 (self): + # global msg + msg = gr.message (666) + + def test_300(self): + input_data = (0,1,2,3,4,5,6,7,8,9) + src = gr.vector_source_b(input_data) + dst = gr.vector_sink_b() + self.fg.connect(src, dst) + self.fg.run() + self.assertEquals(input_data, dst.data()) + + def test_301(self): + src = gr.message_source(gr.sizeof_char) + dst = gr.vector_sink_b() + self.fg.connect(src, dst) + src.msgq().insert_tail(gr.message_from_string('01234')) + src.msgq().insert_tail(gr.message_from_string('5')) + src.msgq().insert_tail(gr.message_from_string('')) + src.msgq().insert_tail(gr.message_from_string('6789')) + src.msgq().insert_tail(gr.message(1)) # send EOF + self.fg.run() + self.assertEquals(tuple(map(ord, '0123456789')), dst.data()) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_mute.py b/gnuradio-core/src/python/gnuradio/gr/qa_mute.py new file mode 100755 index 00000000..863c308a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_mute.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ff (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_f (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_f () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_cc (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_c (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_c () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_unmute_ii(self): + src_data = (1, 2, 3, 4, 5) + expected_result = (1, 2, 3, 4, 5) + op = gr.mute_ii (False) + self.help_ii ((src_data,), expected_result, op) + + def test_mute_ii(self): + src_data = (1, 2, 3, 4, 5) + expected_result = (0, 0, 0, 0, 0) + op = gr.mute_ii (True) + self.help_ii ((src_data,), expected_result, op) + + def test_unmute_cc (self): + src_data = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + op = gr.mute_cc (False) + self.help_cc ((src_data,), expected_result, op) + + def test_unmute_cc (self): + src_data = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + expected_result = (0+0j, 0+0j, 0+0j, 0+0j, 0+0j) + op = gr.mute_cc (True) + self.help_cc ((src_data,), expected_result, op) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py new file mode 100755 index 00000000..f056d110 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_single_pole_iir(gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001(self): + src_data = (-10, 0, 10, 100, 1000, 10000, 100000) + expected_result = (-180, -180, 10, 20, 30, 40, 50) + src = gr.vector_source_f(src_data) + op = gr.nlog10_ff(10) + dst = gr.vector_sink_f() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py b/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py new file mode 100755 index 00000000..d5472c8d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import random + +class test_packing(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def test_001(self): + """ + Test stream_to_streams. + """ + src_data = (0x80,) + expected_results = (1,0,0,0,0,0,0,0) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + """ + Test stream_to_streams. + """ + src_data = (0x80,) + expected_results = (0,0,0,0,0,0,0, 1) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + """ + Test stream_to_streams. + """ + src_data = (0x11,) + expected_results = (4, 2) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(3, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_004(self): + """ + Test stream_to_streams. + """ + src_data = (0x11,) + expected_results = (0, 4) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(3, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_005(self): + """ + Test stream_to_streams. + """ + src_data = (1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0) + expected_results = (0x82,0x5a) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_006(self): + """ + Test stream_to_streams. + """ + src_data = (0,1,0,0,0,0,0,1,0,1,0,1,1,0,1,0) + expected_results = (0x82,0x5a) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + + def test_007(self): + """ + Test stream_to_streams. + """ + src_data = (4, 2, 0,0,0) + expected_results = (0x11,) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(3, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_008(self): + """ + Test stream_to_streams. + """ + src_data = (0, 4, 2,0,0) + expected_results = (0x11,) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(3, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_009(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(202): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(3, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_bb(3, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + + dst = gr.vector_sink_b() + self.fg.connect(op2, dst) + + self.fg.run() + + self.assertEqual(expected_results[0:201], dst.data()) + + def test_010(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(56): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(7, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_bb(7, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_b() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results[0:201], dst.data()) + + def test_011(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(56): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(7, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_bb(7, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_b() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results[0:201], dst.data()) + + + # tests on shorts + + def test_100a(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(1, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ss(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_100b(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(1, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ss(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_101a(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(8, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ss(8, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_101b(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(8, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ss(8, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + # tests on ints + + def test_200a(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(1, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ii(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_200b(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(1, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ii(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_201a(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(8, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ii(8, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_201b(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(8, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ii(8, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py b/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py new file mode 100755 index 00000000..dca18c8e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +if 0: + import os + print "pid =", os.getpid() + raw_input("Attach, then press Enter to continue") + + +def calc_expected_result(src_data, n): + assert (len(src_data) % n) == 0 + result = [list() for x in range(n)] + #print "len(result) =", len(result) + for i in xrange(len(src_data)): + (result[i % n]).append(src_data[i]) + return [tuple(x) for x in result] + + +class test_pipe_fittings(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def test_001(self): + """ + Test stream_to_streams. + """ + n = 8 + src_len = n * 8 + src_data = range(src_len) + + expected_results = calc_expected_result(src_data, n) + #print "expected results: ", expected_results + src = gr.vector_source_i(src_data) + op = gr.stream_to_streams(gr.sizeof_int, n) + self.fg.connect(src, op) + + dsts = [] + for i in range(n): + dst = gr.vector_sink_i() + self.fg.connect((op, i), (dst, 0)) + dsts.append(dst) + + self.fg.run() + + for d in range(n): + self.assertEqual(expected_results[d], dsts[d].data()) + + def test_002(self): + """ + Test streams_to_stream (using stream_to_streams). + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_streams(gr.sizeof_int, n) + op2 = gr.streams_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.fg.connect(src, op1) + for i in range(n): + self.fg.connect((op1, i), (op2, i)) + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + """ + Test streams_to_vector (using stream_to_streams & vector_to_stream). + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_streams(gr.sizeof_int, n) + op2 = gr.streams_to_vector(gr.sizeof_int, n) + op3 = gr.vector_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.fg.connect(src, op1) + for i in range(n): + self.fg.connect((op1, i), (op2, i)) + self.fg.connect(op2, op3, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_004(self): + """ + Test vector_to_streams. + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_vector(gr.sizeof_int, n) + op2 = gr.vector_to_streams(gr.sizeof_int, n) + op3 = gr.streams_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.fg.connect(src, op1, op2) + for i in range(n): + self.fg.connect((op2, i), (op3, i)) + self.fg.connect(op3, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py b/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py new file mode 100755 index 00000000..2505482d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blks +import math +import random +import sys + +#import os +#print os.getpid() +#raw_input('Attach with gdb, then press Enter: ') + + +def random_floats(n): + r = [] + for x in xrange(n): + r.append(float(random.randint(-32768, 32768))) + return tuple(r) + + +def reference_dec_filter(src_data, decim, taps): + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + result_data = dst.data() + fg = None + return result_data + +def reference_interp_filter(src_data, interp, taps): + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.interp_fir_filter_fff(interp, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + result_data = dst.data() + fg = None + return result_data + +def reference_interp_dec_filter(src_data, interp, decim, taps): + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + up = gr.interp_fir_filter_fff(interp, (1,)) + dn = gr.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + fg.connect(src, up, dn, dst) + fg.run() + result_data = dst.data() + fg = None + return result_data + + +class test_rational_resampler (gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + # + # test the gr.rational_resampler_base primitives... + # + + def test_000_1_to_1(self): + taps = (-4, 5) + src_data = (234, -4, 23, -56, 45, 98, -23, -7) + xr = (-936, 1186, -112, 339, -460, -167, 582) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, 1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_001_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170,1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002_interp(self): + taps = random_floats(31) + #src_data = random_floats(10000) # FIXME the 10k case fails! + src_data = random_floats(1000) + interpolation = 3 + + expected_result = reference_interp_filter(src_data, interpolation, taps) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % + (L2 - L1, len(taps), interpolation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first 3 answers + self.assertEqual(expected_result[3:L], result_data[3:L]) + + def test_003_interp(self): + taps = random_floats(31) + src_data = random_floats(10000) + decimation = 3 + + expected_result = reference_dec_filter(src_data, decimation, taps) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, decimation, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % + (L2 - L1, len(taps), decimation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_004_decim_random_vals(self): + MAX_TAPS = 9 + MAX_DECIM = 7 + OUTPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for decim in xrange(1, MAX_DECIM+1): + for ilen in xrange(ntaps + decim, ntaps + OUTPUT_LEN*decim): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_dec_filter(src_data, decim, taps) + + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, decim, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + fg = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % (L2 - L1, ntaps, decim, ilen)) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_005_interp_random_vals(self): + MAX_TAPS = 9 + MAX_INTERP = 7 + INPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for interp in xrange(1, MAX_INTERP+1): + for ilen in xrange(ntaps, ntaps + INPUT_LEN): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_interp_filter(src_data, interp, taps) + + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interp, 1, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + fg = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + #if True or abs(L1-L2) > 1: + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % (L2 - L1, ntaps, interp, ilen)) + #sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + # (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first ntaps+1 answers + self.assertEqual(expected_result[ntaps+1:L], result_data[ntaps+1:L]) + + + def test_006_interp_decim(self): + taps = (0,1,0,0) + src_data = range(10000) + interp = 3 + decimation = 2 + + expected_result = reference_interp_dec_filter(src_data, interp, decimation, taps) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interp, decimation, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % + (L2 - L1, len(taps), decimation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[1:L], result_data[1:L]) + + # + # test the blks.rational_resampler_??? primitives... + # + + def test_101_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170,1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = blks.rational_resampler_fff(self.fg, interpolation, 1, taps=taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main() + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py new file mode 100755 index 00000000..39866ac4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_sig_source (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_const_f (self): + fg = self.fg + expected_result = (1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5) + src1 = gr.sig_source_f (1e6, gr.GR_CONST_WAVE, 0, 1.5) + op = gr.head (gr.sizeof_float, 10) + dst1 = gr.vector_sink_f () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_const_i (self): + fg = self.fg + expected_result = (1, 1, 1, 1) + src1 = gr.sig_source_i (1e6, gr.GR_CONST_WAVE, 0, 1) + op = gr.head (gr.sizeof_int, 4) + dst1 = gr.vector_sink_i () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_sine_f (self): + fg = self.fg + sqrt2 = math.sqrt(2) / 2 + expected_result = (0, sqrt2, 1, sqrt2, 0, -sqrt2, -1, -sqrt2, 0) + src1 = gr.sig_source_f (8, gr.GR_SIN_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_cosine_f (self): + fg = self.fg + sqrt2 = math.sqrt(2) / 2 + expected_result = (1, sqrt2, 0, -sqrt2, -1, -sqrt2, 0, sqrt2, 1) + src1 = gr.sig_source_f (8, gr.GR_COS_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py new file mode 100755 index 00000000..5898188f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_single_pole_iir(gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = src_data + src = gr.vector_source_f(src_data) + op = gr.single_pole_iir_filter_ff (1.0) + dst = gr.vector_sink_f() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 359.375, 689.453125, 1103.271484, 1590.36255) + src = gr.vector_source_f(src_data) + op = gr.single_pole_iir_filter_ff (0.125) + dst = gr.vector_sink_f() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 3) + + def test_003(self): + block_size = 2 + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 250, 484.375, 718.75, 1048.828125) + src = gr.vector_source_f(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_float, block_size) + op = gr.single_pole_iir_filter_ff (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_float, block_size) + dst = gr.vector_sink_f() + self.fg.connect (src, s2p, op, p2s, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 3) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py new file mode 100755 index 00000000..a7889d17 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest + +class test_single_pole_iir_cc(gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001(self): + src_data = (0+0j, 1000+1000j, 2000+2000j, 3000+3000j, 4000+4000j, 5000+5000j) + expected_result = src_data + src = gr.vector_source_c(src_data) + op = gr.single_pole_iir_filter_cc (1.0) + dst = gr.vector_sink_c() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(359.375,-359.375), complex(689.453125,-689.453125), complex(1103.271484,-1103.271484), complex(1590.36255,-1590.36255)) + src = gr.vector_source_c(src_data) + op = gr.single_pole_iir_filter_cc (0.125) + dst = gr.vector_sink_c() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 3) + + def test_003(self): + block_size = 2 + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(250,-250), complex(484.375,-484.375), complex(718.75,-718.75), complex(1048.828125,-1048.828125)) + src = gr.vector_source_c(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, block_size) + op = gr.single_pole_iir_filter_cc (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_gr_complex, block_size) + dst = gr.vector_sink_c() + self.fg.connect (src, s2p, op, p2s, dst) + self.fg.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 3) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py new file mode 100755 index 00000000..59f838a4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import random + +class test_unpack(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def test_001(self): + src_data = (1,0,1,1,0,1,1,0) + expected_results = (1,0,1,1,0,1,1,0) + src = gr.vector_source_b(src_data,False) + op = gr.unpack_k_bits_bb(1) + dst = gr.vector_sink_b() + self.fg.connect(src, op, dst) + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + src_data = ( 2, 3, 0, 1) + expected_results = (1,0,1,1,0,0,0,1) + src = gr.vector_source_b(src_data,False) + op = gr.unpack_k_bits_bb(2) + dst = gr.vector_sink_b() + self.fg.connect(src, op, dst) + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/run_tests.in b/gnuradio-core/src/python/gnuradio/gr/run_tests.in new file mode 100755 index 00000000..87d0afda --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/run_tests.in @@ -0,0 +1,33 @@ +#!/bin/sh + +swigbld=@abs_top_builddir@/gnuradio-core/src/lib/swig +swigsrc=@abs_top_srcdir@/gnuradio-core/src/lib/swig +py=@abs_top_srcdir@/gnuradio-core/src/python + +PYTHONPATH="$swigbld:$swigbld/.libs:$swigsrc:$py" +export PYTHONPATH + +# for OS/X +DYLD_LIBRARY_PATH="@abs_top_builddir@/gnuradio-core/src/lib/.libs" +export DYLD_LIBRARY_PATH + +# Don't load user or system prefs +GR_DONT_LOAD_PREFS=1 +export GR_DONT_LOAD_PREFS + +ok=yes +for file in @srcdir@/qa_*.py +do + echo $file + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gnuradio-core/src/python/gnuradio/gr/scheduler.py b/gnuradio-core/src/python/gnuradio/gr/scheduler.py new file mode 100644 index 00000000..919d07f0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/scheduler.py @@ -0,0 +1,70 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio.gr.exceptions import * +from gnuradio_swig_python import single_threaded_scheduler, sts_pyrun +import gr_threading as _threading +#import threading as _threading + +class scheduler_thread(_threading.Thread): + def __init__(self, sts): + _threading.Thread.__init__(self) + self.sts = sts + def run(self): + # Invoke the single threaded scheduler's run method + # + # Note that we're in a new thread, and that sts_pyrun + # releases the global interpreter lock. This has the + # effect of evaluating the graph in parallel to the + # main line control code. + sts_pyrun(self.sts) + self.sts = None + +class scheduler(object): + def __init__(self, fg): + graphs = fg.partition_graph(fg.blocks) + # print "@@@ # graphs = %d" % (len(graphs)) + + self.state = [] + + for g in graphs: + list_of_blocks = [x.block() for x in g] + sts = single_threaded_scheduler(list_of_blocks) + thread = scheduler_thread(sts) + thread.setDaemon(1) + self.state.append((sts, thread)) + + def start(self): + for (sts, thread) in self.state: + thread.start() + + def stop(self): + for (sts, thread) in self.state: + sts.stop() + self.wait() + + def wait(self): + for (sts, thread) in self.state: + timeout = 0.100 + while True: + thread.join(timeout) + if not thread.isAlive(): + break diff --git a/gnuradio-core/src/python/gnuradio/gr_unittest.py b/gnuradio-core/src/python/gnuradio/gr_unittest.py new file mode 100755 index 00000000..a74a0615 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr_unittest.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import unittest +import sys + +class TestCase(unittest.TestCase): + """A subclass of unittest.TestCase that adds additional assertions + + Adds new methods assertComplexAlmostEqual, + assertComplexTuplesAlmostEqual and assertFloatTuplesAlmostEqual + """ + + def assertComplexAlmostEqual (self, first, second, places=7, msg=None): + """Fail if the two complex objects are unequal as determined by their + difference rounded to the given number of decimal places + (default 7) and comparing to zero. + + Note that decimal places (from zero) is usually not the same + as significant digits (measured from the most signficant digit). + """ + if round(second.real-first.real, places) != 0: + raise self.failureException, \ + (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + if round(second.imag-first.imag, places) != 0: + raise self.failureException, \ + (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + + def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): + """ + Fail if the two complex objects are unequal as determined by... + """ + if abs(ref - x) < abs_eps: + return + + if abs(ref) > abs_eps: + if abs(ref-x)/abs(ref) > rel_eps: + raise self.failureException, \ + (msg or '%s != %s rel_error = %s rel_limit = %s' % ( + `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + else: + raise self.failureException, \ + (msg or '%s != %s rel_error = %s rel_limit = %s' % ( + `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + + + + def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None): + self.assertEqual (len(a), len(b)) + for i in xrange (len(a)): + self.assertComplexAlmostEqual (a[i], b[i], places, msg) + + def assertComplexTuplesAlmostEqual2 (self, ref, x, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual (len(ref), len(x)) + for i in xrange (len(ref)): + try: + self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) + except self.failureException, e: + #sys.stderr.write("index = %d " % (i,)) + #sys.stderr.write("%s\n" % (e,)) + raise + + def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None): + self.assertEqual (len(a), len(b)) + for i in xrange (len(a)): + self.assertAlmostEqual (a[i], b[i], places, msg) + + + def assertFloatTuplesAlmostEqual2 (self, ref, x, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual (len(ref), len(x)) + for i in xrange (len(ref)): + try: + self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) + except self.failureException, e: + #sys.stderr.write("index = %d " % (i,)) + #sys.stderr.write("%s\n" % (e,)) + raise + + +TestResult = unittest.TestResult +TestSuite = unittest.TestSuite +FunctionTestCase = unittest.FunctionTestCase +TestLoader = unittest.TestLoader +TextTestRunner = unittest.TextTestRunner +TestProgram = unittest.TestProgram +main = TestProgram + +############################################################################## +# Executing this module from the command line +############################################################################## + +if __name__ == "__main__": + main(module=None) diff --git a/gnuradio-core/src/python/gnuradio/gru/Makefile.am b/gnuradio-core/src/python/gnuradio/gru/Makefile.am new file mode 100644 index 00000000..44b52b6c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gru/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# EXTRA_DIST = run_tests.in +# TESTS = run_tests + +grblkspythondir = $(grpythondir)/gru + +grblkspython_PYTHON = \ + __init__.py + + +noinst_PYTHON = + +CLEANFILES = *.pyc *.pyo diff --git a/gnuradio-core/src/python/gnuradio/gru/__init__.py b/gnuradio-core/src/python/gnuradio/gru/__init__.py new file mode 100644 index 00000000..272c7a5f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gru/__init__.py @@ -0,0 +1,37 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import glob +import os.path + +# Semi-hideous kludge to import everything in the gruimpl directory +# into the gnuradio.gru namespace. This keeps us from having to remember +# to manually update this file. + +for p in __path__: + filenames = glob.glob (os.path.join (p, "..", "gruimpl", "*.py")) + for f in filenames: + f = os.path.basename(f).lower() + f = f[:-3] + if f == '__init__': + continue + # print f + exec "from gnuradio.gruimpl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am new file mode 100644 index 00000000..06eb7a1f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am @@ -0,0 +1,40 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +grupythondir = $(grpythondir)/gruimpl + +grupython_PYTHON = \ + __init__.py \ + crc.py \ + freqz.py \ + gnuplot_freqz.py \ + hexint.py \ + listmisc.py \ + mathmisc.py \ + lmx2306.py \ + os_read_exactly.py \ + sdr_1000.py \ + seq_with_cursor.py \ + socket_stuff.py + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/crc.py b/gnuradio-core/src/python/gnuradio/gruimpl/crc.py new file mode 100644 index 00000000..6a97c81b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/crc.py @@ -0,0 +1,36 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from hexint import * +import struct + +def gen_and_append_crc32(s): + crc = gr.crc32(s) + return s + struct.pack(">I", hexint(crc)) + +def check_crc32(s): + msg = s[:-4] + #print "msg = '%s'" % (msg,) + actual = gr.crc32(msg) + (expected,) = struct.unpack(">I", s[-4:]) + # print "actual =", hex(actual), "expected =", hex(expected) + return (actual == expected, msg) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py new file mode 100644 index 00000000..21704944 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# This code lifted from various parts of www.scipy.org -eb 2005-01-24 + +# Copyright (c) 2001, 2002 Enthought, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# a. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# b. 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. +# c. Neither the name of the Enthought 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 REGENTS 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. +# + +__all__ = ['freqz'] + +import Numeric +from Numeric import * +Num=Numeric + +def atleast_1d(*arys): + """ Force a sequence of arrays to each be at least 1D. + + Description: + Force an array to be at least 1D. If an array is 0D, the + array is converted to a single row of values. Otherwise, + the array is unaltered. + Arguments: + *arys -- arrays to be converted to 1 or more dimensional array. + Returns: + input array converted to at least 1D array. + """ + res = [] + for ary in arys: + ary = asarray(ary) + if len(ary.shape) == 0: + result = Numeric.array([ary[0]]) + else: + result = ary + res.append(result) + if len(res) == 1: + return res[0] + else: + return res + + +def polyval(p,x): + """Evaluate the polynomial p at x. If x is a polynomial then composition. + + Description: + + If p is of length N, this function returns the value: + p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1] + + x can be a sequence and p(x) will be returned for all elements of x. + or x can be another polynomial and the composite polynomial p(x) will be + returned. + """ + p = asarray(p) + if isinstance(x,poly1d): + y = 0 + else: + x = asarray(x) + y = Numeric.zeros(x.shape,x.typecode()) + for i in range(len(p)): + y = x * y + p[i] + return y + +class poly1d: + """A one-dimensional polynomial class. + + p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3 + + p(0.5) evaluates the polynomial at the location + p.r is a list of roots + p.c is the coefficient array [1,2,3] + p.order is the polynomial order (after leading zeros in p.c are removed) + p[k] is the coefficient on the kth power of x (backwards from + sequencing the coefficient array. + + polynomials can be added, substracted, multplied and divided (returns + quotient and remainder). + asarray(p) will also give the coefficient array, so polynomials can + be used in all functions that accept arrays. + """ + def __init__(self, c_or_r, r=0): + if isinstance(c_or_r,poly1d): + for key in c_or_r.__dict__.keys(): + self.__dict__[key] = c_or_r.__dict__[key] + return + if r: + c_or_r = poly(c_or_r) + c_or_r = atleast_1d(c_or_r) + if len(c_or_r.shape) > 1: + raise ValueError, "Polynomial must be 1d only." + c_or_r = trim_zeros(c_or_r, trim='f') + if len(c_or_r) == 0: + c_or_r = Numeric.array([0]) + self.__dict__['coeffs'] = c_or_r + self.__dict__['order'] = len(c_or_r) - 1 + + def __array__(self,t=None): + if t: + return asarray(self.coeffs,t) + else: + return asarray(self.coeffs) + + def __coerce__(self,other): + return None + + def __repr__(self): + vals = repr(self.coeffs) + vals = vals[6:-1] + return "poly1d(%s)" % vals + + def __len__(self): + return self.order + + def __str__(self): + N = self.order + thestr = "0" + for k in range(len(self.coeffs)): + coefstr ='%.4g' % abs(self.coeffs[k]) + if coefstr[-4:] == '0000': + coefstr = coefstr[:-5] + power = (N-k) + if power == 0: + if coefstr != '0': + newstr = '%s' % (coefstr,) + else: + if k == 0: + newstr = '0' + else: + newstr = '' + elif power == 1: + if coefstr == '0': + newstr = '' + elif coefstr == '1': + newstr = 'x' + else: + newstr = '%s x' % (coefstr,) + else: + if coefstr == '0': + newstr = '' + elif coefstr == '1': + newstr = 'x**%d' % (power,) + else: + newstr = '%s x**%d' % (coefstr, power) + + if k > 0: + if newstr != '': + if self.coeffs[k] < 0: + thestr = "%s - %s" % (thestr, newstr) + else: + thestr = "%s + %s" % (thestr, newstr) + elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0): + thestr = "-%s" % (newstr,) + else: + thestr = newstr + return _raise_power(thestr) + + + def __call__(self, val): + return polyval(self.coeffs, val) + + def __mul__(self, other): + if isscalar(other): + return poly1d(self.coeffs * other) + else: + other = poly1d(other) + return poly1d(polymul(self.coeffs, other.coeffs)) + + def __rmul__(self, other): + if isscalar(other): + return poly1d(other * self.coeffs) + else: + other = poly1d(other) + return poly1d(polymul(self.coeffs, other.coeffs)) + + def __add__(self, other): + other = poly1d(other) + return poly1d(polyadd(self.coeffs, other.coeffs)) + + def __radd__(self, other): + other = poly1d(other) + return poly1d(polyadd(self.coeffs, other.coeffs)) + + def __pow__(self, val): + if not isscalar(val) or int(val) != val or val < 0: + raise ValueError, "Power to non-negative integers only." + res = [1] + for k in range(val): + res = polymul(self.coeffs, res) + return poly1d(res) + + def __sub__(self, other): + other = poly1d(other) + return poly1d(polysub(self.coeffs, other.coeffs)) + + def __rsub__(self, other): + other = poly1d(other) + return poly1d(polysub(other.coeffs, self.coeffs)) + + def __div__(self, other): + if isscalar(other): + return poly1d(self.coeffs/other) + else: + other = poly1d(other) + return map(poly1d,polydiv(self.coeffs, other.coeffs)) + + def __rdiv__(self, other): + if isscalar(other): + return poly1d(other/self.coeffs) + else: + other = poly1d(other) + return map(poly1d,polydiv(other.coeffs, self.coeffs)) + + def __setattr__(self, key, val): + raise ValueError, "Attributes cannot be changed this way." + + def __getattr__(self, key): + if key in ['r','roots']: + return roots(self.coeffs) + elif key in ['c','coef','coefficients']: + return self.coeffs + elif key in ['o']: + return self.order + else: + return self.__dict__[key] + + def __getitem__(self, val): + ind = self.order - val + if val > self.order: + return 0 + if val < 0: + return 0 + return self.coeffs[ind] + + def __setitem__(self, key, val): + ind = self.order - key + if key < 0: + raise ValueError, "Does not support negative powers." + if key > self.order: + zr = Numeric.zeros(key-self.order,self.coeffs.typecode()) + self.__dict__['coeffs'] = Numeric.concatenate((zr,self.coeffs)) + self.__dict__['order'] = key + ind = 0 + self.__dict__['coeffs'][ind] = val + return + + def integ(self, m=1, k=0): + return poly1d(polyint(self.coeffs,m=m,k=k)) + + def deriv(self, m=1): + return poly1d(polyder(self.coeffs,m=m)) + +def freqz(b, a, worN=None, whole=0, plot=None): + """Compute frequency response of a digital filter. + + Description: + + Given the numerator (b) and denominator (a) of a digital filter compute + its frequency response. + + jw -jw -jmw + jw B(e) b[0] + b[1]e + .... + b[m]e + H(e) = ---- = ------------------------------------ + jw -jw -jnw + A(e) a[0] + a[2]e + .... + a[n]e + + Inputs: + + b, a --- the numerator and denominator of a linear filter. + worN --- If None, then compute at 512 frequencies around the unit circle. + If a single integer, the compute at that many frequencies. + Otherwise, compute the response at frequencies given in worN + whole -- Normally, frequencies are computed from 0 to pi (upper-half of + unit-circle. If whole is non-zero compute frequencies from 0 + to 2*pi. + + Outputs: (h,w) + + h -- The frequency response. + w -- The frequencies at which h was computed. + """ + b, a = map(atleast_1d, (b,a)) + if whole: + lastpoint = 2*pi + else: + lastpoint = pi + if worN is None: + N = 512 + w = Num.arange(0,lastpoint,lastpoint/N) + elif isinstance(worN, types.IntType): + N = worN + w = Num.arange(0,lastpoint,lastpoint/N) + else: + w = worN + w = atleast_1d(w) + zm1 = exp(-1j*w) + h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1) + # if not plot is None: + # plot(w, h) + return h, w diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py new file mode 100755 index 00000000..5a117605 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +__all__ = ['gnuplot_freqz'] + +import tempfile +import os +import math +import Numeric + +from gnuradio import gr +from gnuradio.gruimpl.freqz import freqz + + +def gnuplot_freqz (hw, Fs=None, logfreq=False): + + """hw is a tuple of the form (h, w) where h is sequence of complex + freq responses, and w is a sequence of corresponding frequency + points. Plot the frequency response using gnuplot. If Fs is + provide, use it as the sampling frequency, else use 2*pi. + + Returns a handle to the gnuplot graph. When the handle is reclaimed + the graph is torn down.""" + + data_file = tempfile.NamedTemporaryFile () + cmd_file = os.popen ('gnuplot', 'w') + + h, w = hw + ampl = 20 * Numeric.log10 (Numeric.absolute (h) + 1e-9) + phase = map (lambda x: math.atan2 (x.imag, x.real), h) + + if Fs: + w *= (Fs/(2*math.pi)) + + for freq, a, ph in zip (w, ampl, phase): + data_file.write ("%g\t%g\t%g\n" % (freq, a, ph)) + + data_file.flush () + + cmd_file.write ("set grid\n") + if logfreq: + cmd_file.write ("set logscale x\n") + else: + cmd_file.write ("unset logscale x\n") + cmd_file.write ("plot '%s' using 1:2 with lines\n" % (data_file.name,)) + cmd_file.flush () + + return (cmd_file, data_file) + + +def test_plot (): + sample_rate = 2.0e6 + taps = gr.firdes.low_pass (1.0, # gain + sample_rate, # sampling rate + 200e3, # low pass cutoff freq + 100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + # print len (taps) + return gnuplot_freqz (freqz (taps, 1), sample_rate) + +if __name__ == '__main__': + handle = test_plot () + raw_input ('Press Enter to continue: ') diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py new file mode 100644 index 00000000..1220755c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py @@ -0,0 +1,32 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def hexint(mask): + """ + Convert unsigned masks into signed ints. + + This allows us to use hex constants like 0xf0f0f0f2 when talking to + our hardware and not get screwed by them getting treated as python + longs. + """ + if mask >= 2**31: + return int(mask-2**32) + return mask diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py new file mode 100644 index 00000000..857e417f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py @@ -0,0 +1,29 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def list_reverse(x): + """ + Return a copy of x that is reverse order. + """ + r = list(x) + r.reverse() + return r + diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py new file mode 100755 index 00000000..b46c896f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +'''Control National LMX2306 based frequency synthesizer''' + +from gnuradio import gr +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +# bottom two bits of 21 bit word select which register to program + +R_REG = 0x0 +AB_REG = 0x1 +F_REG = 0x2 + +F_counter_reset = (1 << 2) +F_phase_detector_polarity = (1 << 7) + +F_LD_tri_state = (0 << 4) +F_LD_R_divider_output = (4 << 4) +F_LD_N_divider_output = (2 << 4) +F_LD_serial_data_output = (6 << 4) +F_LD_digital_lock_detect = (1 << 4) +F_LD_open_drain = (5 << 4) +F_LD_high = (3 << 4) +F_LD_low = (7 << 4) + +# F_default = F_LD_digital_lock_detect | F_phase_detector_polarity +F_default = F_LD_open_drain | F_phase_detector_polarity + +# +# 4 control pins: +# CE always high +# LE load enable. When LE goes high, data stored in the shift register +# is loaded into one of the three registers +# CLK data is clocked in on the rising edge +# DATA single data bit. Entered MSB first + +DB_CLK = (1 << 0) +DB_DATA = (1 << 1) +DB_LE = (1 << 2) +DB_CE = (1 << 3) + +class lmx2306 (object): + '''Control the National LMX2306 PLL''' + __slots__ = ['pp', 'shadow', 'fosc', 'r', 'step_size', 'verbose'] + def __init__ (self, fosc, step_size, which_pp = 0): + '''FOSC is the frequency of the reference oscillator, + STEP_SIZE is the step between valid frequencies, + WHICH_PP specifies which parallel port to use + ''' + self.pp = gr.make_ppio (which_pp) + self.shadow = DB_CE + self.pp.lock () + self.pp.write_data (self.shadow) + self.pp.unlock () + self.verbose = False + self._set_fosc (fosc) + self._set_step (step_size) + + + def program (self, r, a, b): + if self.verbose: + print "lmx2306: r = %d a = %d b = %d" % (r, a, b) + self.pp.lock () + self._write_word (F_REG | F_default | F_counter_reset) + self._write_word (R_REG | ((r & 0x3fff) << 2)) + self._write_word (AB_REG | ((a & 0x1f) << 2) | ((b & 0x1fff) << 7)) + self._write_word (F_REG | F_default) + self.pp.unlock () + + def set_freq (self, freq): + '''Set the PLL frequency to FREQ + + Return the actual freq value set. It will be rounded down to a + multiple of step_size + ''' + divisor = int (freq / self.step_size) + actual = divisor * self.step_size + (a, b) = self._compute_ab (divisor) + self.program (self.r, a, b) + return actual + + # ---------------------------------------------------------------- + + def _set_fosc (self, ref_oscillator_freq): + self.fosc = ref_oscillator_freq + + def _set_step (self, step_size): + r = int (self.fosc / step_size) + if r * step_size != self.fosc: + raise ValueError, "step_size is not a factor of self.fosc" + if r < 3 or r > 16383: + raise ValueError, "r is out of range" + self.r = r + self.step_size = step_size + + def _compute_ab (self, divisor): + b = divisor / 8 + a = divisor - (b * 8) + if b < 3 or b > 8191 or a > b: + raise ValueError, "Invalid divisor" + return (a, b) + + def _write_word (self, w): + for i in range(21): + if w & (1 << 20): + self._set_DATA_1 () + else: + self._set_DATA_0 () + w = (w << 1) & 0x0ffffff + self._set_CLK_1 () + self._set_CLK_0 () + self._set_LE_1 () + self._set_LE_0 () + + def _set_LE_0 (self): + self.shadow = self.shadow & ~DB_LE + self.pp.write_data (self.shadow) + + def _set_LE_1 (self): + self.shadow = self.shadow | DB_LE + self.pp.write_data (self.shadow) + + def _set_CLK_0 (self): + self.shadow = self.shadow & ~DB_CLK + self.pp.write_data (self.shadow) + + def _set_CLK_1 (self): + self.shadow = self.shadow | DB_CLK + self.pp.write_data (self.shadow) + + def _set_DATA_0 (self): + self.shadow = self.shadow & ~DB_DATA + self.pp.write_data (self.shadow) + + def _set_DATA_1 (self): + self.shadow = self.shadow | DB_DATA + self.pp.write_data (self.shadow) + +if __name__ == '__main__': + parser = OptionParser (option_class=eng_option) + parser.add_option ("-o", "--fosc", type="eng_float", default=32e6, + help="set reference oscillator freq to FREQ", metavar="FREQ") + parser.add_option ("-s", "--step-size", type="eng_float", default=10e3, + help="set the frequency step size to STEP_SIZE") + parser.add_option ("-f", "--freq", type="eng_float", default=430e6, + help="set VCO frequency to FREQ") + parser.add_option ("-v", "--verbose", action="store_true", default=False) + (options, args) = parser.parse_args () + + if options.verbose: + print "fosc = %s step = %s fvco = %s" % ( + eng_notation.num_to_str (options.fosc), + eng_notation.num_to_str (options.step_size), + eng_notation.num_to_str (options.freq)) + + lmx = lmx2306 (options.fosc, options.step_size) + lmx.verbose = options.verbose + + actual = lmx.set_freq (options.freq) + + if options.verbose: + print "fvco_actual = %s delta = %s" % ( + eng_notation.num_to_str (actual), + eng_notation.num_to_str (options.freq - actual)) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py new file mode 100644 index 00000000..13e6de80 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py @@ -0,0 +1,33 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math + +def gcd(a,b): + while b: + a,b = b, a % b + return a + +def lcm(a,b): + return a * b / gcd(a, b) + +def log2(x): + return math.log(x)/math.log(2) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py new file mode 100644 index 00000000..afdfb514 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py @@ -0,0 +1,36 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import os + +def os_read_exactly(file_descriptor, nbytes): + """ + Replacement for os.read that blocks until it reads exactly nbytes. + + """ + s = '' + while nbytes > 0: + sbuf = os.read(file_descriptor, nbytes) + if not(sbuf): + return '' + nbytes -= len(sbuf) + s = s + sbuf + return s diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py b/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py new file mode 100644 index 00000000..5de23b72 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py @@ -0,0 +1,84 @@ +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr + +class sdr_1000 (gr.sdr_1000_base): + "Control the DDS on the SDR-1000" + def __init__(self, pport = 0): + gr.sdr_1000_base.__init__(self, pport) + self.write_latch (3, 0x00, 0xC0) # Reset low, WRS/ low + self.write_reg (0x20, 0x40) + + def write_reg(self, addr, data): + self.write_latch (3, addr & 0x3f, 0x3f) + self.write_latch (2, data, 0xff) + self.write_latch (3, 0x40, 0x40) + self.write_latch (3, 0x00, 0x40) + + def set_freq(self, freq): + self.set_band (freq) + ftw = freq / 200e6; + for i in xrange(6): + word = int(ftw * 256) + ftw = ftw*256 - word + # print (('%d [%02x]') % (i, word)) + self.write_reg (4+i, word) + + def set_band (self, freq): + if freq <= 2.25e6: + band = 0 + elif freq <= 5.5e6: + band = 1 + elif freq <= 11e6: + band = 3 # due to wiring mistake on board + elif freq <= 22e6: + band = 2 # due to wiring mistake on board + elif freq <= 37.5e6: + band = 4 + else: + band = 5 + + self.write_latch (1, 1 << band, 0x3f) + + def set_bit (self, reg, bit, state): + val = 0x00 + if state: val = 1< 0), "Out of range 1..7" + self.set_bit(0, pin-1, on) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py new file mode 100644 index 00000000..5616dea9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py @@ -0,0 +1,77 @@ +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# misc utilities + +import types +import exceptions + +class seq_with_cursor (object): + __slots__ = [ 'items', 'index' ] + + def __init__ (self, items, initial_index = None, initial_value = None): + assert len (items) > 0, "seq_with_cursor: len (items) == 0" + self.items = items + self.set_index (initial_index) + if initial_value is not None: + self.set_index_by_value(initial_value) + + def set_index (self, initial_index): + if initial_index is None: + self.index = len (self.items) / 2 + elif initial_index >= 0 and initial_index < len (self.items): + self.index = initial_index + else: + raise exceptions.ValueError + + def set_index_by_value(self, v): + """ + Set index to the smallest value such that items[index] >= v. + If there is no such item, set index to the maximum value. + """ + self.set_index(0) # side effect! + cv = self.current() + more = True + while cv < v and more: + cv, more = self.next() # side effect! + + def next (self): + new_index = self.index + 1 + if new_index < len (self.items): + self.index = new_index + return self.items[new_index], True + else: + return self.items[self.index], False + + def prev (self): + new_index = self.index - 1 + if new_index >= 0: + self.index = new_index + return self.items[new_index], True + else: + return self.items[self.index], False + + def current (self): + return self.items[self.index] + + def get_seq (self): + return self.items[:] # copy of items + diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py new file mode 100644 index 00000000..05be0d43 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py @@ -0,0 +1,56 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# random socket related stuff + +import socket +import os +import sys + +def tcp_connect_or_die(sock_addr): + """ + @param sock_addr: (host, port) to connect to + @type sock_addr: tuple + @returns: socket or exits + """ + s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect(sock_addr) + except socket.error, err: + sys.stderr.write('Failed to connect to %s: %s\n' % + (sock_addr, os.strerror (err.args[0]),)) + sys.exit(1) + return s + +def udp_connect_or_die(sock_addr): + """ + @param sock_addr: (host, port) to connect to + @type sock_addr: tuple + @returns: socket or exits + """ + s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect(sock_addr) + except socket.error, err: + sys.stderr.write('Failed to connect to %s: %s\n' % + (sock_addr, os.strerror (err.args[0]),)) + sys.exit(1) + return s diff --git a/gnuradio-core/src/python/gnuradio/optfir.py b/gnuradio-core/src/python/gnuradio/optfir.py new file mode 100644 index 00000000..eb3f321b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/optfir.py @@ -0,0 +1,242 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +''' +Routines for designing optimal FIR filters. + +For a great intro to how all this stuff works, see section 6.6 of +"Digital Signal Processing: A Practical Approach", Emmanuael C. Ifeachor +and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X. +''' + +import math +from gnuradio import gr + +remez = gr.remez + +# ---------------------------------------------------------------- + +def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, + nextra_taps=0): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (gain, 0) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [passband_dev, stopband_dev], Fs) + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +# FIXME high_passs is broken... +def high_pass (Fs, freq1, freq2, stopband_atten_db, passband_ripple_db, + nextra_taps=0): + """FIXME: broken""" + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (0, 1) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [stopband_dev, passband_dev], Fs) + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +# ---------------------------------------------------------------- + +def stopband_atten_to_dev (atten_db): + """Convert a stopband attenuation in dB to an absolute value""" + return 10**(-atten_db/20) + +def passband_ripple_to_dev (ripple_db): + """Convert passband ripple spec expressed in dB to an absolute value""" + return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + +# ---------------------------------------------------------------- + +def remezord (fcuts, mags, devs, fsamp = 2): + ''' + FIR order estimator (lowpass, highpass, bandpass, mulitiband). + + (n, fo, ao, w) = remezord (f, a, dev) + (n, fo, ao, w) = remezord (f, a, dev, fs) + + (n, fo, ao, w) = remezord (f, a, dev) finds the approximate order, + normalized frequency band edges, frequency band amplitudes, and + weights that meet input specifications f, a, and dev, to use with + the remez command. + + * f is a sequence of frequency band edges (between 0 and Fs/2, where + Fs is the sampling frequency), and a is a sequence specifying the + desired amplitude on the bands defined by f. The length of f is + twice the length of a, minus 2. The desired function is + piecewise constant. + + * dev is a sequence the same size as a that specifies the maximum + allowable deviation or ripples between the frequency response + and the desired amplitude of the output filter, for each band. + + Use remez with the resulting order n, frequency sequence fo, + amplitude response sequence ao, and weights w to design the filter b + which approximately meets the specifications given by remezord + input parameters f, a, and dev: + + b = remez (n, fo, ao, w) + + (n, fo, ao, w) = remezord (f, a, dev, Fs) specifies a sampling frequency Fs. + + Fs defaults to 2 Hz, implying a Nyquist frequency of 1 Hz. You can + therefore specify band edges scaled to a particular applications + sampling frequency. + + In some cases remezord underestimates the order n. If the filter + does not meet the specifications, try a higher order such as n+1 + or n+2. + ''' + # get local copies + fcuts = fcuts[:] + mags = mags[:] + devs = devs[:] + + for i in range (len (fcuts)): + fcuts[i] = float (fcuts[i]) / fsamp + + nf = len (fcuts) + nm = len (mags) + nd = len (devs) + nbands = nm + + if nm != nd: + raise ValueError, "Length of mags and devs must be equal" + + if nf != 2 * (nbands - 1): + raise ValueError, "Length of f must be 2 * len (mags) - 2" + + for i in range (len (mags)): + if mags[i] != 0: # if not stopband, get relative deviation + devs[i] = devs[i] / mags[i] + + # separate the passband and stopband edges + f1 = fcuts[0::2] + f2 = fcuts[1::2] + + n = 0 + min_delta = 2 + for i in range (len (f1)): + if f2[i] - f1[i] < min_delta: + n = i + min_delta = f2[i] - f1[i] + + if nbands == 2: + # lowpass or highpass case (use formula) + l = lporder (f1[n], f2[n], devs[0], devs[1]) + else: + # bandpass or multipass case + # try different lowpasses and take the worst one that + # goes through the BP specs + l = 0 + for i in range (1, nbands-1): + l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1]) + l2 = lporder (f1[i], f2[i], devs[i], devs[i+1]) + l = max (l, l1, l2) + + n = int (math.ceil (l)) - 1 # need order, not length for remez + + # cook up remez compatible result + ff = [0] + fcuts + [1] + for i in range (1, len (ff) - 1): + ff[i] *= 2 + + aa = [] + for a in mags: + aa = aa + [a, a] + + max_dev = max (devs) + wts = [1] * len(devs) + for i in range (len (wts)): + wts[i] = max_dev / devs[i] + + return (n, ff, aa, wts) + +# ---------------------------------------------------------------- + +def lporder (freq1, freq2, delta_p, delta_s): + ''' + FIR lowpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + Note, this works for high pass filters too (freq1 > freq2), but + doesnt work well if the transition is near f == 0 or f == fs/2 + + From Herrmann et al (1973), Practical design rules for optimum + finite impulse response filters. Bell System Technical J., 52, 769-99 + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 5.309e-3 + a2 = 7.114e-2 + a3 = -4.761e-1 + a4 = -2.66e-3 + a5 = -5.941e-1 + a6 = -4.278e-1 + + b1 = 11.01217 + b2 = 0.5124401 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6) + ff = b1 + b2 * (ddp - dds) + n = dinf / df - ff * df + 1 + return n + + +def bporder (freq1, freq2, delta_p, delta_s): + ''' + FIR bandpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + From Mintzer and Liu (1979) + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 0.01201 + a2 = 0.09664 + a3 = -0.51325 + a4 = 0.00203 + a5 = -0.57054 + a6 = -0.44314 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + cinf = dds * (t1 + t2 + a3) + t3 + t4 + a6 + ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9 + n = cinf / df + ginf * df + 1 + return n + diff --git a/gnuradio-core/src/python/gnuradio/packet_utils.py b/gnuradio-core/src/python/gnuradio/packet_utils.py new file mode 100644 index 00000000..d7235540 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/packet_utils.py @@ -0,0 +1,433 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import struct +import Numeric +from gnuradio import gru + + +def conv_packed_binary_string_to_1_0_string(s): + """ + '\xAF' --> '10101111' + """ + r = [] + for ch in s: + x = ord(ch) + for i in range(7,-1,-1): + t = (x >> i) & 0x1 + r.append(t) + + return ''.join(map(lambda x: chr(x + ord('0')), r)) + +def conv_1_0_string_to_packed_binary_string(s): + """ + '10101111' -> ('\xAF', False) + + Basically the inverse of conv_packed_binary_string_to_1_0_string, + but also returns a flag indicating if we had to pad with leading zeros + to get to a multiple of 8. + """ + if not is_1_0_string(s): + raise ValueError, "Input must be a string containing only 0's and 1's" + + # pad to multiple of 8 + padded = False + rem = len(s) % 8 + if rem != 0: + npad = 8 - rem + s = '0' * npad + s + padded = True + + assert len(s) % 8 == 0 + + r = [] + i = 0 + while i < len(s): + t = 0 + for j in range(8): + t = (t << 1) | (ord(s[i + j]) - ord('0')) + r.append(chr(t)) + i += 8 + return (''.join(r), padded) + + +default_access_code = \ + conv_packed_binary_string_to_1_0_string('\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC') + + +def is_1_0_string(s): + if not isinstance(s, str): + return False + for ch in s: + if not ch in ('0', '1'): + return False + return True + +def string_to_hex_list(s): + return map(lambda x: hex(ord(x)), s) + + +def whiten(s): + sa = Numeric.fromstring(s, Numeric.UnsignedInt8) + z = sa ^ random_mask_vec8[0:len(sa)] + return z.tostring() + +def dewhiten(s): + return whiten(s) # self inverse + + +def make_header(payload_len): + return struct.pack('!HH', payload_len, payload_len) + +def make_packet(payload, spb, bits_per_baud, access_code=default_access_code, pad_for_usrp=True): + """ + Build a packet, given access code and payload. + + @param payload: packet payload, len [0, 4096] + @param spb: samples per baud (needed for padding calculation) + @type spb: int + @param bits_per_baud: (needed for padding calculation) + @type bits_per_baud: int + @param access_code: string of ascii 0's and 1's + + Packet will have access code at the beginning, followed by length, payload + and finally CRC-32. + """ + if not is_1_0_string(access_code): + raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,) + + (packed_access_code, padded) = conv_1_0_string_to_packed_binary_string(access_code) + + payload_with_crc = gru.gen_and_append_crc32(payload) + #print "outbound crc =", string_to_hex_list(payload_with_crc[-4:]) + + L = len(payload_with_crc) + MAXLEN = len(random_mask_tuple) + if L > MAXLEN: + raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,) + + pkt = ''.join((packed_access_code, make_header(L), whiten(payload_with_crc), '\x55')) + if pad_for_usrp: + pkt = pkt + (_npadding_bytes(len(pkt), spb, bits_per_baud) * '\x55') + + #print "make_packet: len(pkt) =", len(pkt) + return pkt + +def _npadding_bytes(pkt_byte_len, spb, bits_per_baud): + """ + Generate sufficient padding such that each packet ultimately ends + up being a multiple of 512 bytes when sent across the USB. We + send 4-byte samples across the USB (16-bit I and 16-bit Q), thus + we want to pad so that after modulation the resulting packet + is a multiple of 128 samples. + + @param ptk_byte_len: len in bytes of packet, not including padding. + @param spb: samples per baud == samples per bit (1 bit / baud with GMSK) + @type spb: int + + @returns number of bytes of padding to append. + """ + modulus = 128 + byte_modulus = gru.lcm(modulus/8, spb) * bits_per_baud / spb + r = pkt_byte_len % byte_modulus + if r == 0: + return 0 + return byte_modulus - r + + +def unmake_packet(whitened_payload_with_crc): + """ + Return (ok, payload) + + @param whitened_payload_with_crc: string + """ + payload_with_crc = dewhiten(whitened_payload_with_crc) + ok, payload = gru.check_crc32(payload_with_crc) + + if 0: + print "payload_with_crc =", string_to_hex_list(payload_with_crc) + print "ok = %r, len(payload) = %d" % (ok, len(payload)) + print "payload =", string_to_hex_list(payload) + + return ok, payload + + +# FYI, this PN code is the output of a 15-bit LFSR +random_mask_tuple = ( + 255, 63, 0, 16, 0, 12, 0, 5, 192, 3, 16, 1, 204, 0, 85, 192, + 63, 16, 16, 12, 12, 5, 197, 195, 19, 17, 205, 204, 85, 149, 255, 47, + 0, 28, 0, 9, 192, 6, 208, 2, 220, 1, 153, 192, 106, 208, 47, 28, + 28, 9, 201, 198, 214, 210, 222, 221, 152, 89, 170, 186, 255, 51, 0, 21, + 192, 15, 16, 4, 12, 3, 69, 193, 243, 16, 69, 204, 51, 21, 213, 207, + 31, 20, 8, 15, 70, 132, 50, 227, 85, 137, 255, 38, 192, 26, 208, 11, + 28, 7, 73, 194, 182, 209, 182, 220, 118, 217, 230, 218, 202, 219, 23, 27, + 78, 139, 116, 103, 103, 106, 170, 175, 63, 60, 16, 17, 204, 12, 85, 197, + 255, 19, 0, 13, 192, 5, 144, 3, 44, 1, 221, 192, 89, 144, 58, 236, + 19, 13, 205, 197, 149, 147, 47, 45, 220, 29, 153, 201, 170, 214, 255, 30, + 192, 8, 80, 6, 188, 2, 241, 193, 132, 80, 99, 124, 41, 225, 222, 200, + 88, 86, 186, 190, 243, 48, 69, 212, 51, 31, 85, 200, 63, 22, 144, 14, + 236, 4, 77, 195, 117, 145, 231, 44, 74, 157, 247, 41, 134, 158, 226, 232, + 73, 142, 182, 228, 118, 203, 102, 215, 106, 222, 175, 24, 124, 10, 161, 199, + 56, 82, 146, 189, 173, 177, 189, 180, 113, 183, 100, 118, 171, 102, 255, 106, + 192, 47, 16, 28, 12, 9, 197, 198, 211, 18, 221, 205, 153, 149, 170, 239, + 63, 12, 16, 5, 204, 3, 21, 193, 207, 16, 84, 12, 63, 69, 208, 51, + 28, 21, 201, 207, 22, 212, 14, 223, 68, 88, 51, 122, 149, 227, 47, 9, + 220, 6, 217, 194, 218, 209, 155, 28, 107, 73, 239, 118, 204, 38, 213, 218, + 223, 27, 24, 11, 74, 135, 119, 34, 166, 153, 186, 234, 243, 15, 5, 196, + 3, 19, 65, 205, 240, 85, 132, 63, 35, 80, 25, 252, 10, 193, 199, 16, + 82, 140, 61, 165, 209, 187, 28, 115, 73, 229, 246, 203, 6, 215, 66, 222, + 177, 152, 116, 106, 167, 111, 58, 172, 19, 61, 205, 209, 149, 156, 111, 41, + 236, 30, 205, 200, 85, 150, 191, 46, 240, 28, 68, 9, 243, 70, 197, 242, + 211, 5, 157, 195, 41, 145, 222, 236, 88, 77, 250, 181, 131, 55, 33, 214, + 152, 94, 234, 184, 79, 50, 180, 21, 183, 79, 54, 180, 22, 247, 78, 198, + 180, 82, 247, 125, 134, 161, 162, 248, 121, 130, 162, 225, 185, 136, 114, 230, + 165, 138, 251, 39, 3, 90, 129, 251, 32, 67, 88, 49, 250, 148, 67, 47, + 113, 220, 36, 89, 219, 122, 219, 99, 27, 105, 203, 110, 215, 108, 94, 173, + 248, 125, 130, 161, 161, 184, 120, 114, 162, 165, 185, 187, 50, 243, 85, 133, + 255, 35, 0, 25, 192, 10, 208, 7, 28, 2, 137, 193, 166, 208, 122, 220, + 35, 25, 217, 202, 218, 215, 27, 30, 139, 72, 103, 118, 170, 166, 255, 58, + 192, 19, 16, 13, 204, 5, 149, 195, 47, 17, 220, 12, 89, 197, 250, 211, + 3, 29, 193, 201, 144, 86, 236, 62, 205, 208, 85, 156, 63, 41, 208, 30, + 220, 8, 89, 198, 186, 210, 243, 29, 133, 201, 163, 22, 249, 206, 194, 212, + 81, 159, 124, 104, 33, 238, 152, 76, 106, 181, 239, 55, 12, 22, 133, 206, + 227, 20, 73, 207, 118, 212, 38, 223, 90, 216, 59, 26, 147, 75, 45, 247, + 93, 134, 185, 162, 242, 249, 133, 130, 227, 33, 137, 216, 102, 218, 170, 219, + 63, 27, 80, 11, 124, 7, 97, 194, 168, 81, 190, 188, 112, 113, 228, 36, + 75, 91, 119, 123, 102, 163, 106, 249, 239, 2, 204, 1, 149, 192, 111, 16, + 44, 12, 29, 197, 201, 147, 22, 237, 206, 205, 148, 85, 175, 127, 60, 32, + 17, 216, 12, 90, 133, 251, 35, 3, 89, 193, 250, 208, 67, 28, 49, 201, + 212, 86, 223, 126, 216, 32, 90, 152, 59, 42, 147, 95, 45, 248, 29, 130, + 137, 161, 166, 248, 122, 194, 163, 17, 185, 204, 114, 213, 229, 159, 11, 40, + 7, 94, 130, 184, 97, 178, 168, 117, 190, 167, 48, 122, 148, 35, 47, 89, + 220, 58, 217, 211, 26, 221, 203, 25, 151, 74, 238, 183, 12, 118, 133, 230, + 227, 10, 201, 199, 22, 210, 142, 221, 164, 89, 187, 122, 243, 99, 5, 233, + 195, 14, 209, 196, 92, 83, 121, 253, 226, 193, 137, 144, 102, 236, 42, 205, + 223, 21, 152, 15, 42, 132, 31, 35, 72, 25, 246, 138, 198, 231, 18, 202, + 141, 151, 37, 174, 155, 60, 107, 81, 239, 124, 76, 33, 245, 216, 71, 26, + 178, 139, 53, 167, 87, 58, 190, 147, 48, 109, 212, 45, 159, 93, 168, 57, + 190, 146, 240, 109, 132, 45, 163, 93, 185, 249, 178, 194, 245, 145, 135, 44, + 98, 157, 233, 169, 142, 254, 228, 64, 75, 112, 55, 100, 22, 171, 78, 255, + 116, 64, 39, 112, 26, 164, 11, 59, 71, 83, 114, 189, 229, 177, 139, 52, + 103, 87, 106, 190, 175, 48, 124, 20, 33, 207, 88, 84, 58, 191, 83, 48, + 61, 212, 17, 159, 76, 104, 53, 238, 151, 12, 110, 133, 236, 99, 13, 233, + 197, 142, 211, 36, 93, 219, 121, 155, 98, 235, 105, 143, 110, 228, 44, 75, + 93, 247, 121, 134, 162, 226, 249, 137, 130, 230, 225, 138, 200, 103, 22, 170, + 142, 255, 36, 64, 27, 112, 11, 100, 7, 107, 66, 175, 113, 188, 36, 113, + 219, 100, 91, 107, 123, 111, 99, 108, 41, 237, 222, 205, 152, 85, 170, 191, + 63, 48, 16, 20, 12, 15, 69, 196, 51, 19, 85, 205, 255, 21, 128, 15, + 32, 4, 24, 3, 74, 129, 247, 32, 70, 152, 50, 234, 149, 143, 47, 36, + 28, 27, 73, 203, 118, 215, 102, 222, 170, 216, 127, 26, 160, 11, 56, 7, + 82, 130, 189, 161, 177, 184, 116, 114, 167, 101, 186, 171, 51, 63, 85, 208, + 63, 28, 16, 9, 204, 6, 213, 194, 223, 17, 152, 12, 106, 133, 239, 35, + 12, 25, 197, 202, 211, 23, 29, 206, 137, 148, 102, 239, 106, 204, 47, 21, + 220, 15, 25, 196, 10, 211, 71, 29, 242, 137, 133, 166, 227, 58, 201, 211, + 22, 221, 206, 217, 148, 90, 239, 123, 12, 35, 69, 217, 243, 26, 197, 203, + 19, 23, 77, 206, 181, 148, 119, 47, 102, 156, 42, 233, 223, 14, 216, 4, + 90, 131, 123, 33, 227, 88, 73, 250, 182, 195, 54, 209, 214, 220, 94, 217, + 248, 90, 194, 187, 17, 179, 76, 117, 245, 231, 7, 10, 130, 135, 33, 162, + 152, 121, 170, 162, 255, 57, 128, 18, 224, 13, 136, 5, 166, 131, 58, 225, + 211, 8, 93, 198, 185, 146, 242, 237, 133, 141, 163, 37, 185, 219, 50, 219, + 85, 155, 127, 43, 96, 31, 104, 8, 46, 134, 156, 98, 233, 233, 142, 206, + 228, 84, 75, 127, 119, 96, 38, 168, 26, 254, 139, 0, 103, 64, 42, 176, + 31, 52, 8, 23, 70, 142, 178, 228, 117, 139, 103, 39, 106, 154, 175, 43, + 60, 31, 81, 200, 60, 86, 145, 254, 236, 64, 77, 240, 53, 132, 23, 35, + 78, 153, 244, 106, 199, 111, 18, 172, 13, 189, 197, 177, 147, 52, 109, 215, + 109, 158, 173, 168, 125, 190, 161, 176, 120, 116, 34, 167, 89, 186, 186, 243, + 51, 5, 213, 195, 31, 17, 200, 12, 86, 133, 254, 227, 0, 73, 192, 54, + 208, 22, 220, 14, 217, 196, 90, 211, 123, 29, 227, 73, 137, 246, 230, 198, + 202, 210, 215, 29, 158, 137, 168, 102, 254, 170, 192, 127, 16, 32, 12, 24, + 5, 202, 131, 23, 33, 206, 152, 84, 106, 191, 111, 48, 44, 20, 29, 207, + 73, 148, 54, 239, 86, 204, 62, 213, 208, 95, 28, 56, 9, 210, 134, 221, + 162, 217, 185, 154, 242, 235, 5, 143, 67, 36, 49, 219, 84, 91, 127, 123, + 96, 35, 104, 25, 238, 138, 204, 103, 21, 234, 143, 15, 36, 4, 27, 67, + 75, 113, 247, 100, 70, 171, 114, 255, 101, 128, 43, 32, 31, 88, 8, 58, + 134, 147, 34, 237, 217, 141, 154, 229, 171, 11, 63, 71, 80, 50, 188, 21, + 177, 207, 52, 84, 23, 127, 78, 160, 52, 120, 23, 98, 142, 169, 164, 126, + 251, 96, 67, 104, 49, 238, 148, 76, 111, 117, 236, 39, 13, 218, 133, 155, + 35, 43, 89, 223, 122, 216, 35, 26, 153, 203, 42, 215, 95, 30, 184, 8, + 114, 134, 165, 162, 251, 57, 131, 82, 225, 253, 136, 65, 166, 176, 122, 244, + 35, 7, 89, 194, 186, 209, 179, 28, 117, 201, 231, 22, 202, 142, 215, 36, + 94, 155, 120, 107, 98, 175, 105, 188, 46, 241, 220, 68, 89, 243, 122, 197, + 227, 19, 9, 205, 198, 213, 146, 223, 45, 152, 29, 170, 137, 191, 38, 240, + 26, 196, 11, 19, 71, 77, 242, 181, 133, 183, 35, 54, 153, 214, 234, 222, + 207, 24, 84, 10, 191, 71, 48, 50, 148, 21, 175, 79, 60, 52, 17, 215, + 76, 94, 181, 248, 119, 2, 166, 129, 186, 224, 115, 8, 37, 198, 155, 18, + 235, 77, 143, 117, 164, 39, 59, 90, 147, 123, 45, 227, 93, 137, 249, 166, + 194, 250, 209, 131, 28, 97, 201, 232, 86, 206, 190, 212, 112, 95, 100, 56, + 43, 82, 159, 125, 168, 33, 190, 152, 112, 106, 164, 47, 59, 92, 19, 121, + 205, 226, 213, 137, 159, 38, 232, 26, 206, 139, 20, 103, 79, 106, 180, 47, + 55, 92, 22, 185, 206, 242, 212, 69, 159, 115, 40, 37, 222, 155, 24, 107, + 74, 175, 119, 60, 38, 145, 218, 236, 91, 13, 251, 69, 131, 115, 33, 229, + 216, 75, 26, 183, 75, 54, 183, 86, 246, 190, 198, 240, 82, 196, 61, 147, + 81, 173, 252, 125, 129, 225, 160, 72, 120, 54, 162, 150, 249, 174, 194, 252, + 81, 129, 252, 96, 65, 232, 48, 78, 148, 52, 111, 87, 108, 62, 173, 208, + 125, 156, 33, 169, 216, 126, 218, 160, 91, 56, 59, 82, 147, 125, 173, 225, + 189, 136, 113, 166, 164, 122, 251, 99, 3, 105, 193, 238, 208, 76, 92, 53, + 249, 215, 2, 222, 129, 152, 96, 106, 168, 47, 62, 156, 16, 105, 204, 46, + 213, 220, 95, 25, 248, 10, 194, 135, 17, 162, 140, 121, 165, 226, 251, 9, + 131, 70, 225, 242, 200, 69, 150, 179, 46, 245, 220, 71, 25, 242, 138, 197, + 167, 19, 58, 141, 211, 37, 157, 219, 41, 155, 94, 235, 120, 79, 98, 180, + 41, 183, 94, 246, 184, 70, 242, 178, 197, 181, 147, 55, 45, 214, 157, 158, + 233, 168, 78, 254, 180, 64, 119, 112, 38, 164, 26, 251, 75, 3, 119, 65, + 230, 176, 74, 244, 55, 7, 86, 130, 190, 225, 176, 72, 116, 54, 167, 86, + 250, 190, 195, 48, 81, 212, 60, 95, 81, 248, 60, 66, 145, 241, 172, 68, + 125, 243, 97, 133, 232, 99, 14, 169, 196, 126, 211, 96, 93, 232, 57, 142, + 146, 228, 109, 139, 109, 167, 109, 186, 173, 179, 61, 181, 209, 183, 28, 118, + 137, 230, 230, 202, 202, 215, 23, 30, 142, 136, 100, 102, 171, 106, 255, 111, + 0, 44, 0, 29, 192, 9, 144, 6, 236, 2, 205, 193, 149, 144, 111, 44, + 44, 29, 221, 201, 153, 150, 234, 238, 207, 12, 84, 5, 255, 67, 0, 49, + 192, 20, 80, 15, 124, 4, 33, 195, 88, 81, 250, 188, 67, 49, 241, 212, + 68, 95, 115, 120, 37, 226, 155, 9, 171, 70, 255, 114, 192, 37, 144, 27, + 44, 11, 93, 199, 121, 146, 162, 237, 185, 141, 178, 229, 181, 139, 55, 39, + 86, 154, 190, 235, 48, 79, 84, 52, 63, 87, 80, 62, 188, 16, 113, 204, + 36, 85, 219, 127, 27, 96, 11, 104, 7, 110, 130, 172, 97, 189, 232, 113, + 142, 164, 100, 123, 107, 99, 111, 105, 236, 46, 205, 220, 85, 153, 255, 42, + 192, 31, 16, 8, 12, 6, 133, 194, 227, 17, 137, 204, 102, 213, 234, 223, + 15, 24, 4, 10, 131, 71, 33, 242, 152, 69, 170, 179, 63, 53, 208, 23, + 28, 14, 137, 196, 102, 211, 106, 221, 239, 25, 140, 10, 229, 199, 11, 18, + 135, 77, 162, 181, 185, 183, 50, 246, 149, 134, 239, 34, 204, 25, 149, 202, + 239, 23, 12, 14, 133, 196, 99, 19, 105, 205, 238, 213, 140, 95, 37, 248, + 27, 2, 139, 65, 167, 112, 122, 164, 35, 59, 89, 211, 122, 221, 227, 25, + 137, 202, 230, 215, 10, 222, 135, 24, 98, 138, 169, 167, 62, 250, 144, 67, + 44, 49, 221, 212, 89, 159, 122, 232, 35, 14, 153, 196, 106, 211, 111, 29, + 236, 9, 141, 198, 229, 146, 203, 45, 151, 93, 174, 185, 188, 114, 241, 229, + 132, 75, 35, 119, 89, 230, 186, 202, 243, 23, 5, 206, 131, 20, 97, 207, + 104, 84, 46, 191, 92, 112, 57, 228, 18, 203, 77, 151, 117, 174, 167, 60, + 122, 145, 227, 44, 73, 221, 246, 217, 134, 218, 226, 219, 9, 155, 70, 235, + 114, 207, 101, 148, 43, 47, 95, 92, 56, 57, 210, 146, 221, 173, 153, 189, + 170, 241, 191, 4, 112, 3, 100, 1, 235, 64, 79, 112, 52, 36, 23, 91, + 78, 187, 116, 115, 103, 101, 234, 171, 15, 63, 68, 16, 51, 76, 21, 245, + 207, 7, 20, 2, 143, 65, 164, 48, 123, 84, 35, 127, 89, 224, 58, 200, + 19, 22, 141, 206, 229, 148, 75, 47, 119, 92, 38, 185, 218, 242, 219, 5, + 155, 67, 43, 113, 223, 100, 88, 43, 122, 159, 99, 40, 41, 222, 158, 216, + 104, 90, 174, 187, 60, 115, 81, 229, 252, 75, 1, 247, 64, 70, 176, 50, + 244, 21, 135, 79, 34, 180, 25, 183, 74, 246, 183, 6, 246, 130, 198, 225, + 146, 200, 109, 150, 173, 174, 253, 188, 65, 177, 240, 116, 68, 39, 115, 90, + 165, 251, 59, 3, 83, 65, 253, 240, 65, 132, 48, 99, 84, 41, 255, 94, + 192, 56, 80, 18, 188, 13, 177, 197, 180, 83, 55, 125, 214, 161, 158, 248, + 104, 66, 174, 177, 188, 116, 113, 231, 100, 74, 171, 119, 63, 102, 144, 42, + 236, 31, 13, 200, 5, 150, 131, 46, 225, 220, 72, 89, 246, 186, 198, 243, + 18, 197, 205, 147, 21, 173, 207, 61, 148, 17, 175, 76, 124, 53, 225, 215, + 8, 94, 134, 184, 98, 242, 169, 133, 190, 227, 48, 73, 212, 54, 223, 86, + 216, 62, 218, 144, 91, 44, 59, 93, 211, 121, 157, 226, 233, 137, 142, 230, + 228, 74, 203, 119, 23, 102, 142, 170, 228, 127, 11, 96, 7, 104, 2, 174, + 129, 188, 96, 113, 232, 36, 78, 155, 116, 107, 103, 111, 106, 172, 47, 61, + 220, 17, 153, 204, 106, 213, 239, 31, 12, 8, 5, 198, 131, 18, 225, 205, + 136, 85, 166, 191, 58, 240, 19, 4, 13, 195, 69, 145, 243, 44, 69, 221, + 243, 25, 133, 202, 227, 23, 9, 206, 134, 212, 98, 223, 105, 152, 46, 234, + 156, 79, 41, 244, 30, 199, 72, 82, 182, 189, 182, 241, 182, 196, 118, 211, + 102, 221, 234, 217, 143, 26, 228, 11, 11, 71, 71, 114, 178, 165, 181, 187, + 55, 51, 86, 149, 254, 239, 0, 76, 0, 53, 192, 23, 16, 14, 140, 4, + 101, 195, 107, 17, 239, 76, 76, 53, 245, 215, 7, 30, 130, 136, 97, 166, + 168, 122, 254, 163, 0, 121, 192, 34, 208, 25, 156, 10, 233, 199, 14, 210, + 132, 93, 163, 121, 185, 226, 242, 201, 133, 150, 227, 46, 201, 220, 86, 217, + 254, 218, 192, 91, 16, 59, 76, 19, 117, 205, 231, 21, 138, 143, 39, 36, + 26, 155, 75, 43, 119, 95, 102, 184, 42, 242, 159, 5, 168, 3, 62, 129, + 208, 96, 92, 40, 57, 222, 146, 216, 109, 154, 173, 171, 61, 191, 81, 176, + 60, 116, 17, 231, 76, 74, 181, 247, 55, 6, 150, 130, 238, 225, 140, 72, + 101, 246, 171, 6, 255, 66, 192, 49, 144, 20, 108, 15, 109, 196, 45, 147, + 93, 173, 249, 189, 130, 241, 161, 132, 120, 99, 98, 169, 233, 190, 206, 240, + 84, 68, 63, 115, 80, 37, 252, 27, 1, 203, 64, 87, 112, 62, 164, 16, + 123, 76, 35, 117, 217, 231, 26, 202, 139, 23, 39, 78, 154, 180, 107, 55, + 111, 86, 172, 62, 253, 208, 65, 156, 48, 105, 212, 46, 223, 92, 88, 57, + 250, 146, 195, 45, 145, 221, 172, 89, 189, 250, 241, 131, 4, 97, 195, 104, + 81, 238, 188, 76, 113, 245, 228, 71, 11, 114, 135, 101, 162, 171, 57, 191, + 82, 240, 61, 132, 17, 163, 76, 121, 245, 226, 199, 9, 146, 134, 237, 162, + 205, 185, 149, 178, 239, 53, 140, 23, 37, 206, 155, 20, 107, 79, 111, 116, + 44, 39, 93, 218, 185, 155, 50, 235, 85, 143, 127, 36, 32, 27, 88, 11, + 122, 135, 99, 34, 169, 217, 190, 218, 240, 91, 4, 59, 67, 83, 113, 253, + 228, 65, 139, 112, 103, 100, 42, 171, 95, 63, 120, 16, 34, 140, 25, 165, + 202, 251, 23, 3, 78, 129, 244, 96, 71, 104, 50, 174, 149, 188, 111, 49, + 236, 20, 77, 207, 117, 148, 39, 47, 90, 156, 59, 41, 211, 94, 221, 248, + 89, 130, 186, 225, 179, 8, 117, 198, 167, 18, 250, 141, 131, 37, 161, 219, + 56, 91, 82, 187, 125, 179, 97, 181, 232, 119, 14, 166, 132, 122, 227, 99, + 9, 233, 198, 206, 210, 212, 93, 159, 121, 168, 34, 254, 153, 128, 106, 224, + 47, 8, 28, 6, 137, 194, 230, 209, 138, 220, 103, 25, 234, 138, 207, 39, + 20, 26, 143, 75, 36, 55, 91, 86, 187, 126, 243, 96, 69, 232, 51, 14, + 149, 196, 111, 19, 108, 13, 237, 197, 141, 147, 37, 173, 219, 61, 155, 81, + 171, 124, 127, 97, 224, 40, 72, 30, 182, 136, 118, 230, 166, 202, 250, 215, + 3, 30, 129, 200, 96, 86, 168, 62, 254, 144, 64, 108, 48, 45, 212, 29, + 159, 73, 168, 54, 254, 150, 192, 110, 208, 44, 92, 29, 249, 201, 130, 214, + 225, 158, 200, 104, 86, 174, 190, 252, 112, 65, 228, 48, 75, 84, 55, 127, + 86, 160, 62, 248, 16, 66, 140, 49, 165, 212, 123, 31, 99, 72, 41, 246, + 158, 198, 232, 82, 206, 189, 148, 113, 175, 100, 124, 43, 97, 223, 104, 88, + 46, 186, 156, 115, 41, 229, 222, 203, 24, 87, 74, 190, 183, 48, 118, 148, + 38, 239, 90, 204, 59, 21, 211, 79, 29, 244, 9, 135, 70, 226, 178, 201, + 181, 150, 247, 46, 198, 156, 82, 233, 253, 142, 193, 164, 80, 123, 124, 35, + 97, 217, 232, 90, 206, 187, 20, 115, 79, 101, 244, 43, 7, 95, 66, 184, + 49, 178, 148, 117, 175, 103, 60, 42, 145, 223, 44, 88, 29, 250, 137, 131, + 38, 225, 218, 200, 91, 22, 187, 78, 243, 116, 69, 231, 115, 10, 165, 199, + 59, 18, 147, 77, 173, 245, 189, 135, 49, 162, 148, 121, 175, 98, 252, 41, + 129, 222, 224, 88, 72, 58, 182, 147, 54, 237, 214, 205, 158, 213, 168, 95, + 62, 184, 16, 114, 140, 37, 165, 219, 59, 27, 83, 75, 125, 247, 97, 134, + 168, 98, 254, 169, 128, 126, 224, 32, 72, 24, 54, 138, 150, 231, 46, 202, + 156, 87, 41, 254, 158, 192, 104, 80, 46, 188, 28, 113, 201, 228, 86, 203, + 126, 215, 96, 94, 168, 56, 126, 146, 160, 109, 184, 45, 178, 157, 181, 169, + 183, 62, 246, 144, 70, 236, 50, 205, 213, 149, 159, 47, 40, 28, 30, 137, + 200, 102, 214, 170, 222, 255, 24, 64, 10, 176, 7, 52, 2, 151, 65, 174, + 176, 124, 116, 33, 231, 88, 74, 186, 183, 51, 54, 149, 214, 239, 30, 204, + 8, 85, 198, 191, 18, 240, 13, 132, 5, 163, 67, 57, 241, 210, 196, 93, + 147, 121, 173, 226, 253, 137, 129, 166, 224, 122, 200, 35, 22, 153, 206, 234, + 212, 79, 31, 116, 8, 39, 70, 154, 178, 235, 53, 143, 87, 36, 62, 155, + 80, 107, 124, 47, 97, 220, 40, 89, 222, 186, 216, 115, 26, 165, 203, 59, + 23, 83, 78, 189, 244, 113, 135, 100, 98, 171, 105, 191, 110, 240, 44, 68, + 29, 243, 73, 133, 246, 227, 6, 201, 194, 214, 209, 158, 220, 104, 89, 238, + 186, 204, 115, 21, 229, 207, 11, 20, 7, 79, 66, 180, 49, 183, 84, 118, + 191, 102, 240, 42, 196, 31, 19, 72, 13, 246, 133, 134, 227, 34, 201, 217, + 150, 218, 238, 219, 12, 91, 69, 251, 115, 3, 101, 193, 235, 16, 79, 76, + 52, 53, 215, 87, 30, 190, 136, 112, 102, 164, 42, 251, 95, 3, 120, 1, + 226, 128, 73, 160, 54, 248, 22, 194, 142, 209, 164, 92, 123, 121, 227, 98, + 201, 233, 150, 206, 238, 212, 76, 95, 117, 248, 39, 2, 154, 129, 171, 32, + 127, 88, 32, 58, 152, 19, 42, 141, 223, 37, 152, 27, 42, 139, 95, 39, + 120, 26, 162, 139, 57, 167, 82, 250, 189, 131, 49, 161, 212, 120, 95, 98, + 184, 41, 178, 158, 245, 168, 71, 62, 178, 144, 117, 172, 39, 61, 218, 145, + 155, 44, 107, 93, 239, 121, 140, 34, 229, 217, 139, 26, 231, 75, 10, 183, + 71, 54, 178, 150, 245, 174, 199, 60, 82, 145, 253, 172, 65, 189, 240, 113, + 132, 36, 99, 91, 105, 251, 110, 195, 108, 81, 237, 252, 77, 129, 245, 160, + 71, 56, 50, 146, 149, 173, 175, 61, 188, 17, 177, 204, 116, 85, 231, 127, + 10, 160, 7, 56, 2, 146, 129, 173, 160, 125, 184, 33, 178, 152, 117, 170, + 167, 63, 58, 144, 19, 44, 13, 221, 197, 153, 147, 42, 237, 223, 13, 152, + 5, 170, 131, 63, 33, 208, 24, 92, 10, 185, 199, 50, 210, 149, 157, 175, + 41, 188, 30, 241, 200, 68, 86, 179, 126, 245, 224, 71, 8, 50, 134, 149, + 162, 239, 57, 140, 18, 229, 205, 139, 21, 167, 79, 58, 180, 19, 55, 77, + 214, 181, 158, 247, 40, 70, 158, 178, 232, 117, 142, 167, 36, 122, 155, 99, + 43, 105, 223, 110, 216, 44, 90, 157, 251, 41, 131, 94, 225, 248, 72, 66, + 182, 177, 182, 244, 118, 199, 102, 210, 170, 221, 191, 25, 176, 10, 244, 7, + 7, 66, 130, 177, 161, 180, 120, 119, 98, 166, 169, 186, 254, 243, 0, 69, + 192, 51, 16, 21, 204, 15, 21, 196, 15, 19, 68, 13, 243, 69, 133, 243, + 35, 5, 217, 195, 26, 209, 203, 28, 87, 73, 254, 182, 192, 118, 208, 38, + 220, 26, 217, 203, 26, 215, 75, 30, 183, 72, 118, 182, 166, 246, 250, 198, + 195, 18, 209, 205, 156, 85, 169, 255, 62, 192, 16, 80, 12, 60, 5, 209, + 195, 28, 81, 201, 252, 86, 193, 254, 208, 64, 92, 48, 57, 212, 18, 223, + 77, 152, 53, 170, 151, 63, 46, 144, 28, 108, 9, 237, 198, 205, 146, 213, + 173, 159, 61, 168, 17, 190, 140, 112, 101, 228, 43, 11, 95, 71, 120, 50, + 162, 149, 185, 175, 50, 252, 21, 129, 207, 32, 84, 24, 63, 74, 144, 55, + 44, 22, 157, 206, 233, 148, 78, 239, 116, 76, 39, 117, 218, 167, 27, 58, + 139, 83, 39, 125, 218, 161, 155, 56, 107, 82, 175, 125, 188, 33, 177, 216, + 116, 90, 167, 123, 58, 163, 83, 57, 253, 210, 193, 157, 144, 105, 172, 46, + 253, 220, 65, 153, 240, 106, 196, 47, 19, 92, 13, 249, 197, 130, 211, 33, + 157, 216, 105, 154, 174, 235, 60, 79, 81, 244, 60, 71, 81, 242, 188, 69, + 177, 243, 52, 69, 215, 115, 30, 165, 200, 123, 22, 163, 78, 249, 244, 66, + 199, 113, 146, 164, 109, 187, 109, 179, 109, 181, 237, 183, 13, 182, 133, 182, + 227, 54, 201, 214, 214, 222, 222, 216, 88, 90, 186, 187, 51, 51, 255, 63 ) + +random_mask_vec8 = Numeric.array(random_mask_tuple, Numeric.UnsignedInt8) + diff --git a/gnuradio-core/src/python/gnuradio/window.py b/gnuradio-core/src/python/gnuradio/window.py new file mode 100644 index 00000000..391b83c3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/window.py @@ -0,0 +1,190 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +''' +Routines for designing window functions. +''' + +import math +from gnuradio import gr + +def izero(x): + izeroepsilon = 1e-21 + halfx = x/2.0 + accum = u = n = 1 + while 1: + temp = halfx/n + n += 1 + temp *= temp + u *= temp + accum += u + if u >= IzeroEPSILON*sum: + break + return accum + +def midm1(fft_size): + return (fft_size - 1)/2 + +def midp1(fft_size): + return (fft_size+1)/2 + +def freq(fft_size): + return 2.0*math.pi/fft_size + +def rate(fft_size): + return 1.0/(fft_size >> 1) + +def expn(fft_size): + math.log(2.0)/(midn(fft_size) + 1.0) + +def hamming(fft_size): + window = [] + for index in xrange(fft_size): + window.append(0.54 - 0.46 * math.cos (2 * math.pi / fft_size * index)) # Hamming window + return window + +def hanning(fft_size): + window = [] + for index in xrange(fft_size): + window.append(0.5 - 0.5 * math.cos (2 * math.pi / fft_size * index)) # von Hann window + return window + +def welch(fft_size): + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = (1.0 - math.sqrt((index - midm1(fft_size)) / midp1(fft_size))) + j -= 1 + return window + +def parzen(fft_size): + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = (1.0 - math.abs((index - midm1(fft_size)) / midp1(fft_size))) + j -= 1 + return window + +def bartlett(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = angle + angle += freq + j -= 1 + return window + +def blackman2(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.34401 + (cx * (-.49755 + (cx * .15844)))) + angle += freq + j -= 1 + return window + +def blackman3(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.21747 + (cx * (-.45325 + (cx * (.28256 - (cx * .04672)))))) + angle += freq + j -= 1 + return window + +def blackman4(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.084037 + (cx * (-.29145 + (cx * (.375696 + (cx * (-.20762 + (cx * .041194)))))))) + angle += freq + j -= 1 + return window + +def exponential(fft_size): + expsum = 1.0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[i] = (expsum - 1.0) + expsum *= expn(fft_size) + j -= 1 + return window + +def riemann(fft_size): + sr1 = freq(fft_size) + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)): + if index == midn(fft_size): + window[index] = window[j] = 1.0 + else: + cx = sr1*midn(fft_size) - index + window[index] = window[j] = math.sin(cx)/cx + j -= 1 + return window + +def blackmanharris(fft_size): + a0 = 0.35875 + a1 = 0.48829 + a2 = 0.14128 + a3 = 0.01168 + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = a0 + window[index] -= a1*math.cos(2.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] += a2*math.cos(4.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] -= a3*math.cos(6.0*math.pi*(index+0.5)/(fft_size - 1)) + return window + +def nuttall(fft_size): + a0 = 0.3635819 + a1 = 0.4891775 + a2 = 0.1365995 + a3 = 0.0106411 + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = a0 + window[index] -= a1*math.cos(2.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] += a2*math.cos(4.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] -= a3*math.cos(6.0*math.pi*(index+0.5)/(fft_size - 1)) + return window + +def kaiser(fft_size,beta): + ibeta = 1.0/izero(beta) + inm1 = 1.0/(fft_size) + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = izero(beta*math.sqrt(1.0 - (index * inm1)*(index * inm1))) * ibeta + return window + + diff --git a/gnuradio-core/src/tests/Makefile.am b/gnuradio-core/src/tests/Makefile.am new file mode 100644 index 00000000..1dd3dd06 --- /dev/null +++ b/gnuradio-core/src/tests/Makefile.am @@ -0,0 +1,96 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +# list of programs run by "make check" and "make distcheck" + +TESTS = test_all + + +# test_atsc + +#Test program to test setting up buffers using gr_test which can be run manually +EXTRA_DIST = \ + test_buffers.py + +noinst_PROGRAMS = \ + benchmark_dotprod \ + benchmark_dotprod_fsf \ + benchmark_dotprod_fcc \ + benchmark_dotprod_scc \ + benchmark_dotprod_ccc \ + benchmark_dotprod_ccf \ + benchmark_nco \ + benchmark_vco \ + test_runtime \ + test_general \ + test_all \ + test_filter \ + test_vmcircbuf + + +LIBGNURADIO = $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core.la +LIBGNURADIOQA = $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core-qa.la $(LIBGNURADIO) + +benchmark_dotprod_SOURCES = benchmark_dotprod.cc +benchmark_dotprod_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_fsf_SOURCES = benchmark_dotprod_fsf.cc +benchmark_dotprod_fsf_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_ccf_SOURCES = benchmark_dotprod_ccf.cc +benchmark_dotprod_ccf_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_fcc_SOURCES = benchmark_dotprod_fcc.cc +benchmark_dotprod_fcc_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_scc_SOURCES = benchmark_dotprod_scc.cc +benchmark_dotprod_scc_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_ccc_SOURCES = benchmark_dotprod_ccc.cc +benchmark_dotprod_ccc_LDADD = $(LIBGNURADIO) + +benchmark_nco_SOURCES = benchmark_nco.cc +benchmark_nco_LDADD = $(LIBGNURADIO) + +benchmark_vco_SOURCES = benchmark_vco.cc +benchmark_vco_LDADD = $(LIBGNURADIO) + +test_runtime_SOURCES = test_runtime.cc +test_runtime_LDADD = $(LIBGNURADIOQA) + +test_general_SOURCES = test_general.cc +test_general_LDADD = $(LIBGNURADIOQA) + +test_filter_SOURCES = test_filter.cc +test_filter_LDADD = $(LIBGNURADIOQA) + +# test_atsc_SOURCES = test_atsc.cc +#test_atsc_LDADD = $(LIBGNURADIOQA) + +test_vmcircbuf_SOURCES = test_vmcircbuf.cc +test_vmcircbuf_LDADD = $(LIBGNURADIOQA) + +test_all_SOURCES = test_all.cc +test_all_LDADD = $(LIBGNURADIOQA) diff --git a/gnuradio-core/src/tests/benchmark_dotprod.cc b/gnuradio-core/src/tests/benchmark_dotprod.cc new file mode 100644 index 00000000..8986f725 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fff* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_fff filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + float result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end -clock_start; +#endif + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_fff_info (&info); // get all known FFF implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc b/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc new file mode 100644 index 00000000..afc24e07 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc @@ -0,0 +1,149 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_ccc* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_ccc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + gr_complex input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter ((gr_complex*)&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_ccc_info (&info); // get all known CCC implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc b/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc new file mode 100644 index 00000000..866f7f61 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_ccf* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_ccf filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + gr_complex input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_ccf_info (&info); // get all known CCF implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc b/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc new file mode 100644 index 00000000..af54707b --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fcc* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_fcc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_fcc_info (&info); // get all known FCC implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc b/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc new file mode 100644 index 00000000..7317e839 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fsf* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_fsf filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + short result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_fsf_info (&info); // get all known FFF implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_scc.cc b/gnuradio-core/src/tests/benchmark_dotprod_scc.cc new file mode 100644 index 00000000..d67fad55 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_scc.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_scc* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_scc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + short input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end -clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_scc_info (&info); // get all known SCC implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_nco.cc b/gnuradio-core/src/tests/benchmark_nco.cc new file mode 100644 index 00000000..fb0fe687 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_nco.cc @@ -0,0 +1,219 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include + +#define ITERATIONS 20000000 +#define BLOCK_SIZE (10 * 1000) // fits in cache + +#define FREQ 5003.123 + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (void test (float *x, float *y), const char *implementation_name) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + float output[2*BLOCK_SIZE]; + float *x = &output[0], *y = &output[BLOCK_SIZE]; + + // touch memory + memset(output, 0, 2*BLOCK_SIZE*sizeof(float)); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + test (x, y); + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + printf ("%18s: cpu: %6.3f steps/sec: %10.3e\n", + implementation_name, total, ITERATIONS / total); +} + +// ---------------------------------------------------------------- +// Don't compare the _vec with other functions since memory store's +// are involved. + +void basic_sincos_vec (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + for (int j = 0; j < BLOCK_SIZE; j++){ + nco.sincos (&x[2*j+1], &x[2*j]); + nco.step (); + } + } +} + +void native_sincos_vec (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + nco.sincos ((gr_complex*)x, BLOCK_SIZE); + } +} + +void fxpt_sincos_vec (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + nco.sincos ((gr_complex*)x, BLOCK_SIZE); + } +} + +// ---------------------------------------------------------------- + +void native_sincos (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + nco.sincos (x, y); + nco.step (); + } +} + +void fxpt_sincos (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + nco.sincos (x, y); + nco.step (); + } +} + +// ---------------------------------------------------------------- + +void native_sin (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + *x = nco.sin (); + nco.step (); + } +} + +void fxpt_sin (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + *x = nco.sin (); + nco.step (); + } +} + +// ---------------------------------------------------------------- + +void nop_fct (float *x, float *y) +{ +} + +void nop_loop (float *x, float *y) +{ + for (int i = 0; i < ITERATIONS; i++){ + nop_fct (x, y); + } +} + +int +main (int argc, char **argv) +{ + benchmark (nop_loop, "nop loop"); + benchmark (native_sin, "native sine"); + benchmark (fxpt_sin, "fxpt sine"); + benchmark (native_sincos, "native sin/cos"); + benchmark (fxpt_sincos, "fxpt sin/cos"); + benchmark (basic_sincos_vec, "basic sin/cos vec"); + benchmark (native_sincos_vec, "native sin/cos vec"); + benchmark (fxpt_sincos_vec, "fxpt sin/cos vec"); +} diff --git a/gnuradio-core/src/tests/benchmark_vco.cc b/gnuradio-core/src/tests/benchmark_vco.cc new file mode 100644 index 00000000..1b290dfa --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_vco.cc @@ -0,0 +1,166 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include + +#define ITERATIONS 5000000 +#define BLOCK_SIZE (10 * 1000) // fits in cache + +#define FREQ 5003.123 +#define K 4.9999999 +#define AMPLITUDE 2.444444444 + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (void test (float *x, const float *y), const char *implementation_name) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + float output[BLOCK_SIZE]; + float input[BLOCK_SIZE]; + + // touch memory + memset(output, 0, BLOCK_SIZE*sizeof(float)); + for (int i = 0; i 2 * M_PI) + phase -= 2 * M_PI; + + while (phase < -2 * M_PI) + phase += 2 * M_PI; + } + } +} + +void native_vco (float *output, const float *input) +{ + gr_vco vco; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE); + } + } + +void fxpt_vco (float *output, const float *input) +{ + gr_fxpt_vco vco; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE); + } +} + +// ---------------------------------------------------------------- + +void nop_fct (float *x, const float *y) +{ +} + +void nop_loop (float *x, const float *y) +{ + for (int i = 0; i < ITERATIONS; i++){ + nop_fct (x, y); + } +} + +int +main (int argc, char **argv) +{ + benchmark (nop_loop, "nop loop"); + benchmark (basic_vco, "basic vco"); + benchmark (native_vco, "native vco"); + benchmark (fxpt_vco, "fxpt vco"); +} diff --git a/gnuradio-core/src/tests/nco_results b/gnuradio-core/src/tests/nco_results new file mode 100644 index 00000000..5bdf5dd1 --- /dev/null +++ b/gnuradio-core/src/tests/nco_results @@ -0,0 +1,48 @@ +================================================================ +These are on a 1.4 GHz Pentium M using g++ 3.4.1 +================================================================ + +Default compiler options -O2 + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.900 steps/sec: 1.111e+07 + fxpt sine: cpu: 0.281 steps/sec: 3.559e+07 + native sin/cos: cpu: 1.138 steps/sec: 8.789e+06 + fxpt sin/cos: cpu: 0.550 steps/sec: 1.818e+07 + +-O2 -march=pentium-m -fomit-frame-pointer + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.903 steps/sec: 1.108e+07 + fxpt sine: cpu: 0.271 steps/sec: 3.691e+07 + native sin/cos: cpu: 1.092 steps/sec: 9.159e+06 + fxpt sin/cos: cpu: 0.542 steps/sec: 1.845e+07 + +Inlined fxpt::sin & cos +-O2 -march=pentium-m -fomit-frame-pointer + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.904 steps/sec: 1.106e+07 + fxpt sine: cpu: 0.187 steps/sec: 5.348e+07 + native sin/cos: cpu: 1.091 steps/sec: 9.167e+06 + fxpt sin/cos: cpu: 0.373 steps/sec: 2.681e+07 + +================================================================ +These are on a 1.5 GHz Athon MP 1800+ +================================================================ + +Default compiler options: -O2 + + nop loop: cpu: 0.013 steps/sec: 7.693e+08 + native sine: cpu: 0.733 steps/sec: 1.364e+07 + fxpt sine: cpu: 0.210 steps/sec: 4.763e+07 + native sin/cos: cpu: 1.183 steps/sec: 8.454e+06 + fxpt sin/cos: cpu: 0.420 steps/sec: 2.381e+07 + +-O2 -fomit-frame-pointer -march=athlon-mp + + nop loop: cpu: 0.013 steps/sec: 7.693e+08 + native sine: cpu: 0.679 steps/sec: 1.473e+07 + fxpt sine: cpu: 0.200 steps/sec: 5.001e+07 + native sin/cos: cpu: 1.147 steps/sec: 8.720e+06 + fxpt sin/cos: cpu: 0.444 steps/sec: 2.253e+07 diff --git a/gnuradio-core/src/tests/test_all.cc b/gnuradio-core/src/tests/test_all.cc new file mode 100644 index 00000000..b5e1b461 --- /dev/null +++ b/gnuradio-core/src/tests/test_all.cc @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include +#include +#include +// #include + +// FIXME add atsc back in. + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_runtime::suite ()); + runner.addTest (qa_general::suite ()); + runner.addTest (qa_filter::suite ()); + // runner.addTest (qa_atsc::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_atsc.cc b/gnuradio-core/src/tests/test_atsc.cc new file mode 100644 index 00000000..cca96d55 --- /dev/null +++ b/gnuradio-core/src/tests/test_atsc.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_atsc::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_buffers.py b/gnuradio-core/src/tests/test_buffers.py new file mode 100755 index 00000000..b3211329 --- /dev/null +++ b/gnuradio-core/src/tests/test_buffers.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import time +import sys + +# Test script to test setting up the buffers using gr_test +# For very large buffers it will fail when you hit the circbuf memory limit. +# On linux this limit is shmmax, it will fail when it tries to create a buffer > shmmax. +# With a 2.6 or later kernel you can set the shmmax limit manually in a root console +#show current shmmax limit +#$ cat /proc/sys/kernel/shmmax +#33554432 + +#set shmmax limit manually to 300MB +#echo 300000000 >/proc/sys/kernel/shmmax + +#show new shmmax limit +#$ cat /proc/sys/kernel/shmmax +#300000000 + +class my_graph(gr.flow_graph): + + def __init__(self, seconds,history,output_multiple): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl) + + nsamples=int(sample_rate * seconds) #1 seconds + # gr.test (const std::string &name=std::string("gr_test"), + # int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + # int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + # unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + # bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + name="gr_test" + min_inputs=1 + max_inputs=1 + sizeof_input_item=gr.sizeof_float + min_outputs=1 + max_outputs=1 + sizeof_output_item=gr.sizeof_float + #history=1 # problems start at 8150 + #output_multiple=1 #problems start at 8000 in combination with large history + relative_rate=1.0 + fixed_rate=True + consume_type=gr.CONSUME_NOUTPUT_ITEMS + produce_type=gr.PRODUCE_NOUTPUT_ITEMS + test = gr.test(name, min_inputs,max_inputs,sizeof_input_item, + min_outputs,max_outputs,sizeof_output_item, + history,output_multiple,relative_rate, + fixed_rate, consume_type,produce_type) + #test = gr.test("gr_test",1,1,gr.sizeof_float, + # 1,1,gr.sizeof_float, + # 1,1,1.0, + # True, gr.CONSUME_NOUTPUT_ITEMS,gr.PRODUCE_NOUTPUT_ITEMS) + #unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + #bool fixed_rate=false + dst = audio.sink (sample_rate, options.audio_output) + head= gr.head(gr.sizeof_float, nsamples) + + self.connect (src0,test,head,(dst, 0)) + + +if __name__ == '__main__': + + seconds=5.0 + output_multiple=1 + for history in (1,1000,8000,8100,8150,8175,8190,8191,8192,8193,8194,8195,9000,10000,100000,1000000,10000000): #,100000000): + sys.stdout.flush() + sys.stderr.flush() + print 'Test with history=', history, 'output_multiple=',output_multiple + sys.stdout.flush() + sys.stderr.flush() + succeed=True + starttime=time.time() + try: + my_graph(seconds,history,output_multiple).run() + except KeyboardInterrupt: + pass + except: + print "\nAn exception has terminated the graph." + exception=True + succeed=False + sys.stdout.flush() + sys.stderr.flush() + if succeed: + print '' + endtime=time.time() + duration=endtime - starttime + if (duration < 0.5*seconds) and (succeed): + print "A problem has terminated the graph." + succeed=False + if (duration > 1.5*seconds) and (succeed): + print "Something slowed the graph down considerably." + succeed=False + + print 'The test result was:' , succeed + print 'Test duration' , duration + print '' diff --git a/gnuradio-core/src/tests/test_filter.cc b/gnuradio-core/src/tests/test_filter.cc new file mode 100644 index 00000000..1b2c57be --- /dev/null +++ b/gnuradio-core/src/tests/test_filter.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_filter::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_general.cc b/gnuradio-core/src/tests/test_general.cc new file mode 100644 index 00000000..9f93b9d7 --- /dev/null +++ b/gnuradio-core/src/tests/test_general.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_general::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_runtime.cc b/gnuradio-core/src/tests/test_runtime.cc new file mode 100644 index 00000000..72290a9b --- /dev/null +++ b/gnuradio-core/src/tests/test_runtime.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_runtime::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_vmcircbuf.cc b/gnuradio-core/src/tests/test_vmcircbuf.cc new file mode 100644 index 00000000..e00b1706 --- /dev/null +++ b/gnuradio-core/src/tests/test_vmcircbuf.cc @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + int verbose = 1; // summary + + if (argc > 1) + verbose = 2; // extra chatty + + bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose); + + if (ok){ + fprintf (stdout, "test_vmcircbuf: OK. We've got at least one workable solution\n"); + return 0; + } + else { + fprintf (stdout, "test_vmcircbuf: NOT OK. We don't have a workable solution\n"); + return 1; + } +} diff --git a/gnuradio-core/src/utils/Makefile.am b/gnuradio-core/src/utils/Makefile.am new file mode 100644 index 00000000..ee0bd437 --- /dev/null +++ b/gnuradio-core/src/utils/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + db_width.m \ + filter_tools.m \ + plot_freq_response.m \ + plot_freq_response_db.m \ + plot_freq_response_phase.m \ + plotfft.m \ + plotfftavgk.m \ + plotfftavgk_db.m \ + plotfftk.m \ + plotfftk_db.m \ + put_markers.m \ + read_char_binary.m \ + read_complex_binary.m \ + read_float_binary.m \ + read_int_binary.m \ + read_short_binary.m \ + single_pole_iir.m \ + write_float_binary.m \ + write_short_binary.m diff --git a/gnuradio-core/src/utils/cool.m b/gnuradio-core/src/utils/cool.m new file mode 100644 index 00000000..eff194d8 --- /dev/null +++ b/gnuradio-core/src/utils/cool.m @@ -0,0 +1,50 @@ +%% Copyright (C) 1999,2000 Kai Habel +%% +%% 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 2 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, write to the Free Software +%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +%% -*- texinfo -*- +%% @deftypefn {Function File} {} cool (@var{n}) +%% Create color colormap. +%% (cyan to magenta) +%% The argument @var{n} should be a scalar. If it +%% is omitted, the length of the current colormap or 64 is assumed. +%% @end deftypefn +%% @seealso{colormap} + +%% Author: Kai Habel + +function map = cool (number) + + if (nargin == 0) + number = rows (colormap); + elseif (nargin == 1) + if (! is_scalar (number)) + error ("cool: argument must be a scalar"); + end + else + usage ("cool (number)"); + end + + if (number == 1) + map = [0, 1, 1]; + elseif (number > 1) + r = (0:number - 1)' ./ (number - 1); + g = 1 - r; + b = ones (number, 1); + map = [r, g, b]; + else + map = []; + end + diff --git a/gnuradio-core/src/utils/db_width.m b/gnuradio-core/src/utils/db_width.m new file mode 100644 index 00000000..c12dfd1c --- /dev/null +++ b/gnuradio-core/src/utils/db_width.m @@ -0,0 +1,35 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. + +%% find the N-dB width of the given filter +%% E.g., to find the 3-dB width, use width = db_width (taps, -3.0) +%% the result is normalized to nyquist == 1 + +function width = db_width (taps, db) + [H,w] = freqz (taps, 1, 4096); + Habs = abs(H); + max_H = max(Habs); + min_H = min(Habs); + threshold = max_H * 10^(db/20); + if (min_H > threshold) + error ("The %g dB point is never reached", db); + end + above = Habs >= threshold; + width = sum(above) / length (above); diff --git a/gnuradio-core/src/utils/filter_tools.m b/gnuradio-core/src/utils/filter_tools.m new file mode 100644 index 00000000..78a50b7d --- /dev/null +++ b/gnuradio-core/src/utils/filter_tools.m @@ -0,0 +1,42 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +%% equivalent to the C++ code in VrComplexFIRfilter::buildFilterComplex + +1; + +%% hamming window, nothing fancy + +function taps = build_filter_complex_lp (gain, ntaps) + + taps = gain * (0.54 - 0.46 * cos (2 * pi * (0:ntaps-1)' / (ntaps-1))); + +end + +%% old_taps describes a low pass filter, convert it to bandpass +%% centered at center_freq. center_freq is normalized to Fs (sampling freq) + +function new_taps = freq_shift_filter (old_taps, center_freq) + + ntaps = length(old_taps); + + new_taps = exp (j*2*pi*center_freq*(0:ntaps-1)') .* old_taps; + +end diff --git a/gnuradio-core/src/utils/is_complex.m b/gnuradio-core/src/utils/is_complex.m new file mode 100644 index 00000000..a17b8ad4 --- /dev/null +++ b/gnuradio-core/src/utils/is_complex.m @@ -0,0 +1,24 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function p = is_complex (x) + p = any (imag (x) != 0); +endfunction; diff --git a/gnuradio-core/src/utils/lp_to_bp.m b/gnuradio-core/src/utils/lp_to_bp.m new file mode 100644 index 00000000..8718baed --- /dev/null +++ b/gnuradio-core/src/utils/lp_to_bp.m @@ -0,0 +1,27 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +## transform low pass coefficients into bandpass coefficients + +function bp_taps = lp_to_bp (lp_taps, center_freq, sampling_freq) + arg = 2 * pi * center_freq / sampling_freq; + bp_taps = lp_taps .* exp (j*arg*(0:length(lp_taps)-1)'); +endfunction diff --git a/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm b/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm new file mode 100644 index 00000000..598f79d8 --- /dev/null +++ b/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm @@ -0,0 +1,68 @@ +;; Estimate the total work (ntaps * sampling rate) for two cascaded +;; decimating low pass filters. +;; +;; The basic assumption is that the number of taps required in any +;; section is inversely proportional to the normalized transition width +;; for that section. +;; +;; FS is the input sampling frequency +;; F1 is the cutoff frequency +;; F2 is the far edge of the transition band +;; DEC1 is the decimation factor for the first filter +;; DEC2 is the decimation factor for the 2nd filter +;; +;; The total decimation factor is DEC1 * DEC2. Therefore, +;; the output rate of the filter is FS / (DEC1 * DEC2) + +(require 'common-list-functions) +(require 'factor) + + + +(define (work2 fs f1 f2 dec1 dec2) + (+ (work1 fs f1 (/ fs (* 2 dec1)) dec1) + (work1 (/ fs dec1) f1 f2 dec2))) + + +;; work for a single section + +(define (work1 fs f1 f2 dec) + (/ (* fs (/ fs (- f2 f1))) dec)) + + +;; return the max integer dec such that fs/(2*dec) >= f2 + +(define (max-dec fs f2) + (inexact->exact (floor (/ fs (* 2 f2))))) + + +;; `adjoin' returns the adjoint of the element OBJ and the list LST. +;; That is, if OBJ is in LST, `adjoin' returns LST, otherwise, it returns +;; `(cons OBJ LST)'. + +(define (adjoin-equal obj lst) + (if (member obj lst) lst (cons obj lst))) + + +;;; not quite right + +(define (permute lst) + (let ((result '())) + (define (aux set head) + (if (null? set) + (set! result (cons head result)) + (for-each (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set))) + (aux lst '()) + result)) + +;; `extract-nth' returns the Nth element of LST consed on to the +;; list resulting from splicing out the Nth element of LST. +;; Indexing is 0 based. + +(define (extract-nth n lst) + lst) + + \ No newline at end of file diff --git a/gnuradio-core/src/utils/permute.scm b/gnuradio-core/src/utils/permute.scm new file mode 100644 index 00000000..23ddfc99 --- /dev/null +++ b/gnuradio-core/src/utils/permute.scm @@ -0,0 +1,27 @@ +(require 'common-list-functions) + + +(define (permute lst) + (define (aux set head) + (cond ((null? set) head) + (else + (map (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set)))) + (aux lst '())) + +(define (permute-2 lst) + (let ((result '())) + (define (aux set head) + (if (null? set) + (set! result (cons head result)) + (for-each (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set))) + (aux lst '()) + result)) + + + diff --git a/gnuradio-core/src/utils/plot_cic_decimator_response.m b/gnuradio-core/src/utils/plot_cic_decimator_response.m new file mode 100644 index 00000000..e26883c5 --- /dev/null +++ b/gnuradio-core/src/utils/plot_cic_decimator_response.m @@ -0,0 +1,45 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_cic_decimator_response (R, N, M) + ## R = decimation rate + ## N = number of stages (4) + ## M = 1 + gain = (R*M)^N + npoints = 1024; + w = 0:1/npoints:1-1/npoints; + w = w * 1 * pi; + ## w = w * R; + length(w); + num = sin (w*R*M/2); + length (num); + ## H = sin (w*R*M/2) ./ sin (w/2) + denom = sin(w/2); + length (denom); + H = (num ./ denom) .^ N; + H(1) = gain; + H = H ./ gain; + plot (R*w/(2*pi), 10 * log10 (H)); + ## plot (R*w/(2*pi), H); +endfunction + + + \ No newline at end of file diff --git a/gnuradio-core/src/utils/plot_freq_response.m b/gnuradio-core/src/utils/plot_freq_response.m new file mode 100644 index 00000000..bf186fae --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response.m @@ -0,0 +1,36 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_freq_response (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + plot (w/(2*pi), abs(H)); + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Magnitude (linear)'); +endfunction diff --git a/gnuradio-core/src/utils/plot_freq_response_db.m b/gnuradio-core/src/utils/plot_freq_response_db.m new file mode 100644 index 00000000..d6ebce39 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response_db.m @@ -0,0 +1,39 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_freq_response_db (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Magnitude Squared (dB)'); + abs = abs(H); +# plot (w/(2*pi), 20 * log10 (abs/max(abs))); + plot (w/(2*pi), 20 * log10 (abs)); +endfunction diff --git a/gnuradio-core/src/utils/plot_freq_response_phase.m b/gnuradio-core/src/utils/plot_freq_response_phase.m new file mode 100644 index 00000000..f30ff7d3 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response_phase.m @@ -0,0 +1,38 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_freq_response_db (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Phase (radians)'); + abs = abs(H); + plot (w/(2*pi), atan2(imag(H), real(H))) +endfunction diff --git a/gnuradio-core/src/utils/plotfft.m b/gnuradio-core/src/utils/plotfft.m new file mode 100644 index 00000000..5af149a1 --- /dev/null +++ b/gnuradio-core/src/utils/plotfft.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfft (data, sample_rate) + + if (nargin == 1) + sample_rate = 1.0; + endif; + + if ((m = nargchk (1,2,nargin))) + usage (m); + endif; + + len = length(data); + s = fft (data.*kaiser(len, 5)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, abs(fftshift(s))); + +endfunction diff --git a/gnuradio-core/src/utils/plotfftavgk.m b/gnuradio-core/src/utils/plotfftavgk.m new file mode 100644 index 00000000..3e19f40c --- /dev/null +++ b/gnuradio-core/src/utils/plotfftavgk.m @@ -0,0 +1,61 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftavgk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + ## len = 1024; + len = 8192; + ##window = ones (len, 1); + window = kaiser (len, 5); + + s = zeros (len,1); + + count = min (100, floor (length (all_data)/len)); + + for i = 0:count-1; + data = all_data((k+i)*len + 1 : (k+i+1)*len); + s = s + abs (fft (data.*window)); + endfor; + + s = s ./ count; + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + ## y = 20 * log10(fftshift(s)); + y = (fftshift(s)); + plot (x, y); + + i = find (y == max(y)) + x(i) + y(i) + +endfunction diff --git a/gnuradio-core/src/utils/plotfftavgk_db.m b/gnuradio-core/src/utils/plotfftavgk_db.m new file mode 100644 index 00000000..6dbb0f50 --- /dev/null +++ b/gnuradio-core/src/utils/plotfftavgk_db.m @@ -0,0 +1,73 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftavgk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + ## len = 8192; + ##window = ones (len, 1); + #window = kaiser (len, 5); + window = hanning (len); + + s = zeros (len,1); + + count = min (100, floor (length (all_data)/len)); + + for i = 0:count-1; + data = all_data((k+i)*len + 1 : (k+i+1)*len); + s = s + abs (fft (data.*window)); + endfor; + + s = s ./ count; + + incr = sample_rate/len; + + if is_complex (all_data); + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + y = 20 * log10(fftshift(s)); + plot (x, y); + else + min_x = 0 + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + y = 20 * log10(s(1:len/2)); + plot (x, y); + + endif; + + + i = find (y == max(y)) + x(i) + y(i) + +endfunction diff --git a/gnuradio-core/src/utils/plotfftk.m b/gnuradio-core/src/utils/plotfftk.m new file mode 100644 index 00000000..bf93ea5d --- /dev/null +++ b/gnuradio-core/src/utils/plotfftk.m @@ -0,0 +1,41 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftk (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + data = all_data(k*len + 1 : (k+1)*len); + s = fft (data.*kaiser(len, 5)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, abs(fftshift(s))); + +endfunction diff --git a/gnuradio-core/src/utils/plotfftk_db.m b/gnuradio-core/src/utils/plotfftk_db.m new file mode 100644 index 00000000..498c22fc --- /dev/null +++ b/gnuradio-core/src/utils/plotfftk_db.m @@ -0,0 +1,43 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + data = all_data(k*len + 1 : (k+1)*len); + ## s = fft (data.*kaiser(len, 5)); + ## s = fft (data.*hamming(len)); + s = fft (data.*hanning(len)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, 20 * log10(abs(fftshift(s)))); + +endfunction diff --git a/gnuradio-core/src/utils/put_markers.m b/gnuradio-core/src/utils/put_markers.m new file mode 100644 index 00000000..e35aee9d --- /dev/null +++ b/gnuradio-core/src/utils/put_markers.m @@ -0,0 +1,32 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function put_markers (y) + + if (nargin == 0) + y = 25; + endif; + + hold on; + plot (3.06e6, y, '@'); + plot (8.44e6, y, '@'); + +endfunction diff --git a/gnuradio-core/src/utils/rainbow.m b/gnuradio-core/src/utils/rainbow.m new file mode 100644 index 00000000..e19bd679 --- /dev/null +++ b/gnuradio-core/src/utils/rainbow.m @@ -0,0 +1,53 @@ +## Copyright (C) 1999,2000 Kai Habel +## +## 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 2 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} rainbow (@var{n}) +## Create color colormap. +## (red through yellow, green, cyan,blue,magenta to red) +## The argument @var{n} should be a scalar. If it +## is omitted, the length of the current colormap or 64 is assumed. +## @end deftypefn +## @seealso{colormap} + +## Author: Kai Habel + +## 2001-09-13 Paul Kienzle +## * renamed to rainbow for use with tk_octave +## * remove reference to __current_color_map__ + +function map = rainbow (number) + + if (nargin == 0) + number = length(colormap); + elseif (nargin == 1) + if (! is_scalar (number)) + error ("rainbow: argument must be a scalar"); + endif + else + usage ("rainbow (number)"); + endif + + if (number == 1) + map = [1, 0, 0]; + elseif (number > 1) + h = linspace (0, 1, number)'; + map = hsv2rgb ([h, ones(number, 1), ones(number, 1)]); + else + map = []; + endif + +endfunction diff --git a/gnuradio-core/src/utils/read_char_binary.m b/gnuradio-core/src/utils/read_char_binary.m new file mode 100644 index 00000000..d33bd91a --- /dev/null +++ b/gnuradio-core/src/utils/read_char_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_char_binary (filename, count) + + %% usage: read_char (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'char'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_complex_binary.m b/gnuradio-core/src/utils/read_complex_binary.m new file mode 100644 index 00000000..6f538f37 --- /dev/null +++ b/gnuradio-core/src/utils/read_complex_binary.m @@ -0,0 +1,48 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_complex_binary (filename, count) + + %% usage: read_complex_binary (filename, [count]) + %% + %% open filename and return the contents as a column vector, + %% treating them as 32 bit complex numbers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + t = fread (f, [2, count], 'float'); + fclose (f); + v = t(1,:) + t(2,:)*i; + [r, c] = size (v); + v = reshape (v, c, r); + end diff --git a/gnuradio-core/src/utils/read_float_binary.m b/gnuradio-core/src/utils/read_float_binary.m new file mode 100644 index 00000000..ac8461ff --- /dev/null +++ b/gnuradio-core/src/utils/read_float_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_float_binary (filename, count) + + %% usage: read_float_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% 32 bit floats + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'float'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_int_binary.m b/gnuradio-core/src/utils/read_int_binary.m new file mode 100644 index 00000000..ca4f7339 --- /dev/null +++ b/gnuradio-core/src/utils/read_int_binary.m @@ -0,0 +1,46 @@ +% +% Copyright 2001,2002 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_int_binary (filename, count) + + %% usage: read_int_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'int'); + fclose (f); + end +end diff --git a/gnuradio-core/src/utils/read_short_binary.m b/gnuradio-core/src/utils/read_short_binary.m new file mode 100644 index 00000000..361392bf --- /dev/null +++ b/gnuradio-core/src/utils/read_short_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_short_binary (filename, count) + + %% usage: read_short_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'short'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_xambi.m b/gnuradio-core/src/utils/read_xambi.m new file mode 100644 index 00000000..7533ddac --- /dev/null +++ b/gnuradio-core/src/utils/read_xambi.m @@ -0,0 +1,46 @@ +# +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function v = read_xambi (filename) + + ## usage: read_xambi (filename) + ## + ## read binary cross-ambiguity data from radar tools. + ## The file has an 8 float header, the first word of which specifies + ## the number of doppler bins. + ## returns a matrix + + if ((m = nargchk (1,1,nargin))) + usage (m); + endif; + + f = fopen (filename, "rb"); + if (f < 0) + v = 0; + else + header = fread(f, 8, "float"); + ndoppler_bins = header(1) + min_doppler = header(2) + max_doppler = header(3) + v = fread (f, [ndoppler_bins, Inf], "float"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-core/src/utils/runsum.m b/gnuradio-core/src/utils/runsum.m new file mode 100644 index 00000000..0f530b01 --- /dev/null +++ b/gnuradio-core/src/utils/runsum.m @@ -0,0 +1,9 @@ +function r = runsum(x) + len = length(x); + r = zeros (1, len); + r(1) = x(1); + for i = 2:len; + r(i) = r(i-1) + x(i); + endfor; +endfunction; + diff --git a/gnuradio-core/src/utils/single_pole_iir.m b/gnuradio-core/src/utils/single_pole_iir.m new file mode 100644 index 00000000..13d6b4d5 --- /dev/null +++ b/gnuradio-core/src/utils/single_pole_iir.m @@ -0,0 +1,25 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function [b, a] = single_pole_iir (alpha) + b = [alpha]; + a = [1, alpha - 1]; +endfunction \ No newline at end of file diff --git a/gnuradio-core/src/utils/write_float_binary.m b/gnuradio-core/src/utils/write_float_binary.m new file mode 100644 index 00000000..c0d27436 --- /dev/null +++ b/gnuradio-core/src/utils/write_float_binary.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function v = write_float_binary (data, filename) + + ## usage: write_float_binary (data, filename) + ## + ## open filename and write data to it as 32 bit floats + ## + + if ((m = nargchk (2,2,nargin))) + usage (m); + endif; + + f = fopen (filename, "wb"); + if (f < 0) + v = 0; + else + v = fwrite (f, data, "float"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-core/src/utils/write_short_binary.m b/gnuradio-core/src/utils/write_short_binary.m new file mode 100644 index 00000000..ffe502e6 --- /dev/null +++ b/gnuradio-core/src/utils/write_short_binary.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function v = write_short_binary (data, filename) + + ## usage: write_short_binary (data, filename) + ## + ## open filename and write data to it as 16 bit shorts + ## + + if ((m = nargchk (2,2,nargin))) + usage (m); + endif; + + f = fopen (filename, "wb"); + if (f < 0) + v = 0; + else + v = fwrite (f, data, "short"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-examples/AUTHORS b/gnuradio-examples/AUTHORS new file mode 100644 index 00000000..6bd41174 --- /dev/null +++ b/gnuradio-examples/AUTHORS @@ -0,0 +1,2 @@ +Eric Blossom +Matt Ettus diff --git a/gnuradio-examples/ChangeLog b/gnuradio-examples/ChangeLog new file mode 100644 index 00000000..e2c630eb --- /dev/null +++ b/gnuradio-examples/ChangeLog @@ -0,0 +1,381 @@ +2006-06-20 Eric Blossom + + * python/gmsk2/receive_path.py, python/gmsk2/transmit_path.py, + benchmark_gmsk_{tx,rx}.py: refactored to use modulation + independent pkt.py code. Lays the foundation for a single set of + tools that can exercise all modulations. More work required to + meet that goal, but we're closing in. + + * python/gmsk2/tunnel.py: refactored version of + tunnel_ip_null_mac. This creates a virtual ethernet inteface + using the TAP driver, and then tunnels packets across the air + using GMSK and a simple carrier sense MAC. Fixed problem with + truncation of large packets which was leading to stalls. + + * python/gmsk2/tunnel_ip_null_mac.py: removed. Replaced with + tunnel.py + +2006-06-15 Eric Blossom + + * python/usrp/usrp_fft.py (app_flow_graph.set_decim): added + missing return value. + + * python/usrp/usrp_oscope.py, python/usrp/usrp_fft.py: you can now + change the decimation factor in the GUI. + +2006-06-06 Eric Blossom + + * python/gmsk2/mpsk.py: Lots of rework. QPSK is now + working with mpsk_test.py. Need to confirm it on the air, and then + make BPSK work again. + + +2006-05-30 Eric Blossom + + Standardized on mpsk as the prefix. Renamed a bunch of stuff to + restore sanity: + * python/gmsk2/benchmark_xpsk_rx.py -> python/gmsk2/benchmark_mpsk_rx.py + * python/gmsk2/benchmark_xpsk_tx.py -> python/gmsk2/benchmark_mpsk_tx.py + * python/gmsk2/psk_receive_path.py -> python/gmsk2/mpsk_receive_path.py + * python/gmsk2/psk_transmit_path.py -> python/gmsk2/mpsk_transmit_path.py + * python/gmsk2/xpsk.py -> python/gmsk2/mpsk.py + * python/gmsk2/xpsk_pkt.py -> python/gmsk2/mpsk_pkt.py + * python/gmsk2/xpsk_test.py -> python/gmsk2/mpsk_test.py + +2006-05-29 Eric Blossom + + * python/gmsk2/qpsk_tester.py, python/gmsk2/qpsk_usrp_tester.py: + new. Test benches for qpsk code. Thanks Tom! + +2005-12-19 Martin Dvh + + updated multi_usrp examples which should now work 'out-of-the-box' with current cvs + (you need updated usrp,gr-usrp, gnuradio-core and gnuradio-examples) + + * configure.ac: added python/usrp_multi/Makefile + * python/Makefile.am: added multi_usrp + * python/multi_usrp/.cvsignore: new + * python/multi_usrp/Makefile.am: new + * python/multi_usrp/README: Made this into a real readme + * python/multi_usrp/multi_usrp_oscope.py: changed to work with current usrp_multi code in cvs + * python/multi_usrp/multi_usrp_rx_cfile.py: changed to work with current usrp_multi code in cvs + * python/multi_usrp/multi_usrp.py: removed + * python/multi_usrp/multi_usrp_oscope_showcounters.py: removed + * python/multi_usrp/multi_usrp_oscope_simple.py: removed + * python/multi_usrp/multi_usrp_oscope_standalone.py: removed + * python/multi_usrp/multi_usrp_rx_tofile.py: removed + * python/multi_usrp/multi_usrp_rx_tofile_standalone.py: removed + * python/multi_usrp/multi_usrp_test_counting.py: removed + +2006-05-10 Eric Blossom + + * python/gmsk2/psk_transmit_path.py: add diff=False per Bob Vincent. + +2006-04-06 Eric Blossom + + * python/usrp/usrp_fft.py: removed explicit setting of fft_rate. + The code will now pick it up from config files. + +2006-03-12 Eric Blossom + + * python/usrp/usrp_siggen.py: added daughterboard support. + * python/usrp/usrp_oscope.py, python/usrp/usrp_fft.py: fixed so + frequency can be set even after an invalid frequency is passed on + the command line. + +2006-03-10 Eric Blossom + + * python/gmsk2/xpsk.py: doc fixes. + +2006-03-08 Eric Blossom + + * python/usrp/fm_tx_2_daughterboards.py: example that transmits + different signals out two daughterboards. + +2006-02-02 Eric Blossom + + * python/usrp/usrp_oscope.py: support manual scaling of + Y-axis. Smarter defaulting of rx_subdev_spec if user doesn't pick. + * python/usrp/usrp_fft.py: Smarter defaulting of rx_subdev_spec if user doesn't pick. + +2006-02-01 Eric Blossom + + * python/gmsk2/transmit_path.py: fixed so it works on both A and B sides. + +2006-01-30 Eric Blossom + + * python/gmsk2/receive_path.py (receive_path.set_auto_tr): added + set_auto_tr to the receive path to have it work properly with + changes in auto t/r switching semantics. + + * python/usrp/fm_tx4.py (fm_tx_graph.__init__): changes to have it + work in both A and B sides. + +2005-12-19 Martin Dvh + + * multi_usrp/README, multi_usrp/multi_usrp.py, multi_usrp/multi_usrp_oscope.py, + multi_usrp/multi_usrp_oscope_showcounters.py, multi_usrp/multi_usrp_oscope_simple.py, + multi_usrp/multi_usrp_oscope_standalone.py, multi_usrp/multi_usrp_rx_tofile.py, + multi_usrp/multi_usrp_rx_tofile_standalone.py, multi_usrp/multi_usrp_test_counting.py: + new directory and examples to exercise multiple usrps coherently + connected together. These require additional code that is not yet + in the repository. + +2005-12-13 Eric Blossom + + * python/usrp/usrp_wfm_rcv2_nogui.py: new: receive two FM stations + simultaneously. + +2005-12-09 Eric Blossom + + * python/gmsk2/tunnel_ip_null_mac.py: cleaned up. gathered mac + functions together. + + * python/usrp/usrp_wfm_rcv_pll.py (pick_subdevice), + python/usrp/usrp_wfm_rcv_nogui.py (pick_subdevice): use library version. + * python/usrp/fm_tx4.py: explicity call set_enable(True) to turn + on transmitter (required due to policy change). Also removed + pick_tx_subdevice. Now use version in usrp library. + +2005-12-09 Eric Blossom + + Made release 2.6 + +2005-12-08 Eric Blossom + + * python/gmsk/rx.py, python/gmsk/rx2.py, python/gmsk/tx.py, + python/gmsk/tx2.py, python/gmsk/xcvr.py, python/gmsk/xcvr2.py, + ggmsk-test.py, gmsk-test.py: removed. Use the code in ../gmsk2 instead. + + * python/gmsk2/receive_path.py, python/gmsk2/transmit_path.py: + New. Extracted hierarchical blocks from benchmark_gmsk_{tx,rx}.py + +2005-12-06 Eric Blossom + + * python/gmsk2/benchmark_gmsk_tx.py, + python/gmsk2/benchmark_gmsk_rx.py: now support "--bitrate" command + line arg. + * python/gmsk2/pick_bitrate.py: given a bitrate, determine + samples/baud and interp/decim ratio. + +2005-11-11 Eric Blossom + + * python/usrp/usrp_nbfm_ptt.py, python/usrp/usrp_wfm_rcv.py: moved + pick_xx_subdev to library. + +2005-11-01 Eric Blossom + + * python/usrp/dbs_nbfm.py: removed. Use usrp_nbfm_rcv.py instead. + +2005-10-24 Eric Blossom + + * python/usrp/usrp_oscope.py: basically identical to usrp_fft.py, + but uses oscope sink. + + * python/usrp/usrp_wfm_rcv_nogui.py, python/usr/usrp_wfm_rcv.py: + increased usrp decimation factor to 200 reduce host cpu + requirements. With the half-band in the FPGA, good decimation + factors are even values in [8,256]. + +2005-10-14 Eric Blossom + + * python/usrp/usrp_fft.py: gui mods. + * python/usrp/usrp_wfm_rcv.py: reworked gui. + +2005-10-11 Eric Blossom + + * python/usrp/usrp_waterfall.py: removed. Use usrp_fft.py -W instead. + +2005-10-10 Eric Blossom + + * python/audio/audio_copy.py, python/audio/audio_play.py, + python/audio/audio_to_file.py, python/audio/dial_tone.py, + python/audio/mono_tone.py, python/audio/multi_tone.py, + python/audio/spectrum_inversion.py: revised to use standard + command line args and canonical structure. + +2005-09-21 Eric Blossom + + * python/usrp/usrp_fft.py: extensively reworked to use new + daughterboard auto-instantiation framework. + +2005-07-30 Martin Dvh + + * python/usrp/tvrx_tv_rcv.py: PAL/NTSC TV demod. Work in progress. + +2005-07-21 Eric Blossom + + * python/usrp/benchmark_usb.py, python/usrp/usrp_rx_cfile.py, + python/usrp/usrp_oscope.py, python/usrp/dbs_debug: doc fix. + +2005-07-19 Eric Blossom + + * python/usrp/ayfabtu.py: new. Transmit on 25 frequencies simultaneously! + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac: mods for x86_64, $(NO_UNDEFINED) + + * python/usrp/usrp_waterfall.py, python/usrp/dbs_debug.py, + python/usrp/flexrf_debug.py, python/usrp/flexrf_siggen.py, + python/usrp/usrp_fft.py, python/usrp/usrp_oscope.py, + python/usrp/usrp_rx_cfile.py, python/usrp/usrp_rx_file.py, + python/usrp/usrp_siggen.py, python/usrp/usrp_waterfall.py: + gru.hexint fix for python 2.4. + +2005-06-17 Eric Blossom + + * python/apps/README: new directory for applications. + +2005-06-16 Eric Blossom + + * python/usrp/tvrx_wfm_rcv_gui.py: add -d audio_device option; fix + volume increment so up == 1.0/down; fix default range of bottom FFT. + +2005-06-13 Eric Blossom + + * python/usrp/tvrx_wfm_rcv_gui.py: removed limit on what frequency + can be set. + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-04-27 Eric Blossom + + * python/digital_voice/encdec.py: simulate gsm voice encode / + gmsk mod / gmsk demod / gsm voice decode. + +2005-03-29 Eric Blossom + + * python/gmsk/ggmsk-test.py, python/gmsk/gmsk-test.py: new GMSK + test code from Joshua Lackey + + * python/gmsk/tx.py, python/gmsk/rx.py: new tx and rx modules that + depending on command line options do either FSK or GMSK and use + either files, sockets, named pipes or a USRP for their inputs and + outputs. From Bob Vincent + +2005-03-29 Eric Blossom + + * python/audio/audio_copy.py, python/audio/multi_tone.py, + python/audio/mono_tone.py: replace ALSA specific default argument + with "" + +2005-03-04 Eric Blossom + + * python/usrp/nbfm_ptt_quick_and_dirty.py: simple NBFM + push-to-talk transceiver. (Works, but has a latency problem that + needs to be fixed) + +2005-02-28 Eric Blossom + + * python/usrp/fsk_tx.py: reduced gain, added -N (no gui) flag. + * python/usrp/fsk_rx.py: added -N (no gui) flag. + Running Tx and Rx on same machine (1.4 GHz Pentium M) 100kb/sec + burns up about 70% of CPU with -N options on both. + +2005-02-25 Eric Blossom + + Removed usrp0 directory. + Moved contents of usrp1 directory into usrp directory. + +2005-02-22 Eric Blossom + + * python/usrp1/nbfm_rcv.py: added squelch. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 0.2cvs + +2004-10-11 Eric Blossom + + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-10-07 Chuck Swiger + + * python/audio/audio_to_file.py: coerce audio sample rate to int. + +2004-10-07 Eric Blossom + + * python/usrp1/wfm_rcv.py: new. Single channel broadcast FM + receiver for usrp1 + microtune 4937. + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-09-18 Eric Blossom + + These changes happened somewhere around DCC + + * python/usrp/usrp_fft.py: new + * python/usrp1/dsb_tx.py: new double sideband AM transmitter + * python/usrp1/fm_tx4.py: simultaneous 4 channel narrow band FM transmitter + * python/usrp1/fsk_rx.py: FSK Rx module. Needs some work. + * python/usrp1/fsk_tx.py: FSK Tx module. Needs some work. + +2004-08-19 Eric Blossom + + * python/usrp/usrp_rx_file.py (main): added command line parsing. + * python/usrp/usrp_siggen.py: added command line parsing. + + * python/usrp1/test_digital_loopback_lfsr.py, + python/usrp1/test_digital_loopback_counting.py, + python/usrp1/test_digital_counting.py: new. Take advantage of + scheduler fix to implement both the tx and rx path's in the same + flow graph. + + +2004-07-31 Eric Blossom + + * python/usrp0, python/usrp1: new directories for rev specific examples. + * python/usrp1/loopback.py (main): new. + +2004-07-30 Eric Blossom + + * python/usrp/usrp_siggen.py: now directly queries hardware for dac freq. + * python/usrp/usrp_rx_file.py: now directly queries hardware for dac freq. + +2004-07-17 Eric Blossom + + * python/mc4020/fm_demod.py: updated to use new mc4020 block, formatting + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 0.1cvs + +2004-07-03 Eric Blossom + + * python/usrp/usrp_siggen.py: Yeah! The first demo program that + reconfigures the flow graph on the fly! + +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gnuradio-examples/Makefile.am b/gnuradio-examples/Makefile.am new file mode 100644 index 00000000..76111384 --- /dev/null +++ b/gnuradio-examples/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = README.hacking +SUBDIRS = python + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = diff --git a/gnuradio-examples/NEWS b/gnuradio-examples/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/gnuradio-examples/README b/gnuradio-examples/README new file mode 100644 index 00000000..89515bb3 --- /dev/null +++ b/gnuradio-examples/README @@ -0,0 +1,68 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +Welcome! + +This package is a collection of examples for the GNU Radio 2.x toolkit. + +They assume that at a minimum, you've got the gnuradio-core +package installed. In addition, depending on what i/o devices you +have, you may want to consider installing: + + gr-usrp : support for Universal Software Radio Peripheral (Rev 1) + gr-audio-oss : sound card support using OSS + gr-audio-alsa : sound card support using ALSA + gr-audio-osx : sound card support for OS/X + gr-mc4020 : Measurement Computing PCI-DAS 4020/12 A/D card + + +You'll need to set your PYTHONPATH environment variable so that the +GNU Radio toolkit and optional packages can be found by python. + +PYTHONPATH should include the path of the local site-packages +directory. It has the general form: + + ${prefix}/lib/python${pythonversion}/site-packages + +If the above packages were installed using the default prefix +(/usr/local) and you're using python 2.3, this should work: + + $ export PYTHONPATH=/usr/local/lib/python2.3/site-packages + +You may want to add this to your ~/.bash_profile or similar file. + + +Once PYTHONPATH is set, you should be able to run any of the examples +for which you have the required i/o devices. + +To ensure that your setup is sane, try this: + + $ python + >>> from gnuradio import gr + +If this works, your PYTHONPATH is set correctly. + + +Have fun! + +The GNU Radio team + + diff --git a/gnuradio-examples/README.hacking b/gnuradio-examples/README.hacking new file mode 100644 index 00000000..44d42474 --- /dev/null +++ b/gnuradio-examples/README.hacking @@ -0,0 +1,39 @@ +* Standard command line options + +When building applications or examples, if your command has any of +these options, please use the following short and long names: + + + + # General + + parser = OptionParser(option_class=eng_option) + + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-F", "--filename", type="string", default=None) + + # Audio devices + + parser.add_option("-I", "--audio-input", type=string, default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type=string, default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + + # USRP specific + + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Tx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM (default=16)") + parser.add_option("-i", "--interp", type="int", default=32, + help="set fgpa interpolation rate to INTERP (default=32)") + parser.add_option("-n", "--nchannels", type=intx, default=1, + help="set number of channels to NCHANNELS (default=1)") + diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am new file mode 100644 index 00000000..73b7921b --- /dev/null +++ b/gnuradio-examples/python/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = audio mc4020 usrp gmsk2 digital_voice multi_usrp diff --git a/gnuradio-examples/python/apps/README b/gnuradio-examples/python/apps/README new file mode 100644 index 00000000..a3f041bf --- /dev/null +++ b/gnuradio-examples/python/apps/README @@ -0,0 +1,26 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This directory servers as the parent directory for various and sundry +applications such as scanners, HF radios, etc. Each subdirectory +shall have a README file that includes a short description of what the +application does, and a list of hardware dependencies. E.g., requires +a USRP with an xyz daughterboard, connected to a footronics magic box. diff --git a/gnuradio-examples/python/apps/hf_explorer/README b/gnuradio-examples/python/apps/hf_explorer/README new file mode 100644 index 00000000..5f780b3d --- /dev/null +++ b/gnuradio-examples/python/apps/hf_explorer/README @@ -0,0 +1,48 @@ +hfx.py is meant to be a full-featured Long Wave / Medium Wave +and Short Wave (250kHz to 30Mhz) AM and Single Sideband receiver. +It uses the USRP with a Basic RX board, and will need an +antenna and some preamps, about 30db gain will work. See the +'Help' menu or hfx_help for more info. + +---------------------------------------------------------- + +hfx2.py is a major revision built about complex fir filter +coeffecients ability and cleaner python script. Inherits +most features from hfx.py - Powermate knob supported but +not required, tooltip frequency display, single click +tuning, AGC, record to disk, play from disk and record audio. +New feature is ability to tailor the audio passband with two +sliders over the spectrum display. The sliders almost align +with the actual frequency. Preset filter settings for LSB +(-3000 to 0kHz), USB (0 to +3000kHz), CW (-400 to -800Hz) +and AM (-5kHz from carrier to +5kHz). + +AM now switches in a synchronous PLL detector with the +carriers at 7.5kHz. The PLL carrier is displayed in the +bottom display and helps show where on the upper spectrum +the demodulated signal lies. Everything gets shifted up +7.5kHz in AM, center frequency, tooltips, etc. The target +AM carrier needs to be closely tuned in, it will have a +hollow sound untill it is locked, and then the PLL carrier +in the bottom display will jump up and remain relatively +constant. There is a slider "AM sync carrier" to play with +different levels to mix with the signal for demodulation. +The filter in AM is preset to 2500/12500 (7.5kHz +/- 5kHz) +and is handy for removing adjacent channel interference. +Change AM_SYNC_DISPLAY in script for whether to show AM +Sync carrier or not. +Run with "-h" for command line help with setting USRP +ddc center frequency, decimation, rf data record, playback +and audio data recording. + +There are some controls for controlling a varactor and +tuning an antenna - just ignore them unless you want +to build a voltage tuned antenna to track frequency. + +There is also code for Web based control of frequency and +volume - so I can tune the radio with an Ipaq from bed. +Disabled by default - it takes a web server, some +directories and scripts to use. + + + diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx2.py b/gnuradio-examples/python/apps/hf_explorer/hfx2.py new file mode 100755 index 00000000..c09f962c --- /dev/null +++ b/gnuradio-examples/python/apps/hf_explorer/hfx2.py @@ -0,0 +1,786 @@ +#!/usr/bin/env python +# -*- coding: ANSI_X3.4-1968 -*- +# generated by wxGlade 0.4 on Tue Mar 14 10:16:06 2006 +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +#----------------------------------------------------------------- +# +# +-->(fft) +# | +# (src)->(xlate)--+->(audio filter)--+-->(sel_am)-+--------------+ +# | | | +# | (pll) | +# | | | +# | (pll_carrier_scale) | +# | | | +# | (pll_carrier_filter) | +# | | | +# | +--(fft2) | +# | | | +# | +--(c2f3)--+ | +# | | | | +# | (phaser1) (phaser2) | +# | | | | +# | +--(f2c)---+ | +# | | V +# V +---------->(am_det) +# (c2f) | +# | (c2f2) +# | | +# +-->(sel_sb)------------>(combine) +# | +# V +# +--------------------------(scale) +# | | +# | | +# | +++ +# V | | +# (agc)<--(offset)<--(intr)<---(sqr1) +# | +# V +# (dst) +# +#---------------------------------------------------------------------- +# +# Versions 2.2.1 adds loop antenna automatic tuner +# +# 2.3.1 adds web control, made AM Sync display optional, +# added more comments. +# +# 2.4.1 updates usrp interface to support auto subdev + +# Web server control disabled by default. Do not enable +# until directory structure and scripts are in place. +WEB_CONTROL = False + +# Controls display of AM Sync Carrier - turn off for smaller +# window if not needed +AM_SYNC_DISPLAY = False + +import os, wx, sys, math +import wx.lib.evtmgr as em +from gnuradio.wxgui import powermate, fftsink +from gnuradio import gr, audio, eng_notation, usrp, gru +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +ID_BUTTON_1 = wx.NewId() # LSB button +ID_BUTTON_2 = wx.NewId() # USB +ID_BUTTON_3 = wx.NewId() # AM +ID_BUTTON_4 = wx.NewId() # CW +ID_BUTTON_5 = wx.NewId() # Powermate controls: Upper audio freq cutoff +ID_BUTTON_6 = wx.NewId() # " Lower audio freq cutoff +ID_BUTTON_7 = wx.NewId() # " Frequency +ID_BUTTON_8 = wx.NewId() # " Volume +ID_BUTTON_9 = wx.NewId() # " Time +ID_BUTTON_10 = wx.NewId() # Time Seek Forwards +ID_BUTTON_11 = wx.NewId() # Time Seek Backwards +ID_BUTTON_12 = wx.NewId() # Automatic Antenna Tune (AT) enable +ID_BUTTON_13 = wx.NewId() # AT Calibrate point +ID_BUTTON_14 = wx.NewId() # AT Reset +ID_TEXT_1 = wx.NewId() # Band Center, USRP ddc Freq +ID_SPIN_1 = wx.NewId() # Frequency display and control +ID_SLIDER_1 = wx.NewId() # Upper audio freq cutoff +ID_SLIDER_2 = wx.NewId() # Lower audio freq cutoff +ID_SLIDER_3 = wx.NewId() # Frequency +ID_SLIDER_4 = wx.NewId() # Volume +ID_SLIDER_5 = wx.NewId() # Programmable Gain Amp, PGA, RF gain +ID_SLIDER_6 = wx.NewId() # AM Sync carrier level +ID_SLIDER_7 = wx.NewId() # AT control voltage output +ID_EXIT = wx.NewId() # Menu Exit + + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + If there's a daughterboard on A, select A. + If there's a daughterboard on B, select B. + Otherwise, select A. + """ + if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + + +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MyFrame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + + # Menu Bar + self.frame_1_menubar = wx.MenuBar() + self.SetMenuBar(self.frame_1_menubar) + wxglade_tmp_menu = wx.Menu() + self.Exit = wx.MenuItem(wxglade_tmp_menu, ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL) + wxglade_tmp_menu.AppendItem(self.Exit) + self.frame_1_menubar.Append(wxglade_tmp_menu, "File") + # Menu Bar end + self.panel_1 = wx.Panel(self, -1) + self.button_1 = wx.Button(self, ID_BUTTON_1, "LSB") + self.button_2 = wx.Button(self, ID_BUTTON_2, "USB") + self.button_3 = wx.Button(self, ID_BUTTON_3, "AM") + self.button_4 = wx.Button(self, ID_BUTTON_4, "CW") + self.button_5 = wx.ToggleButton(self, ID_BUTTON_5, "Upper") + self.slider_1 = wx.Slider(self, ID_SLIDER_1, 0, -15799, 15799, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.button_6 = wx.ToggleButton(self, ID_BUTTON_6, "Lower") + self.slider_2 = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15799, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.panel_5 = wx.Panel(self, -1) + self.label_1 = wx.StaticText(self, -1, " Band\nCenter") + self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXT_1, "") + self.panel_6 = wx.Panel(self, -1) + self.panel_7 = wx.Panel(self, -1) + self.panel_2 = wx.Panel(self, -1) + self.button_7 = wx.ToggleButton(self, ID_BUTTON_7, "Freq") + self.slider_3 = wx.Slider(self, ID_SLIDER_3, 3000, 0, 6000) + self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPIN_1, "", min=0, max=100) + self.button_8 = wx.ToggleButton(self, ID_BUTTON_8, "Vol") + self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 500) + self.slider_5 = wx.Slider(self, ID_SLIDER_5, 0, 0, 20) + self.button_9 = wx.ToggleButton(self, ID_BUTTON_9, "Time") + self.button_11 = wx.Button(self, ID_BUTTON_11, "Rew") + self.button_10 = wx.Button(self, ID_BUTTON_10, "Fwd") + self.panel_3 = wx.Panel(self, -1) + self.label_2 = wx.StaticText(self, -1, "PGA ") + self.panel_4 = wx.Panel(self, -1) + self.panel_8 = wx.Panel(self, -1) + self.panel_9 = wx.Panel(self, -1) + self.label_3 = wx.StaticText(self, -1, "AM Sync\nCarrier") + self.slider_6 = wx.Slider(self, ID_SLIDER_6, 50, 0, 200, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.label_4 = wx.StaticText(self, -1, "Antenna Tune") + self.slider_7 = wx.Slider(self, ID_SLIDER_7, 1575, 950, 2200, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.panel_10 = wx.Panel(self, -1) + self.button_12 = wx.ToggleButton(self, ID_BUTTON_12, "Auto Tune") + self.button_13 = wx.Button(self, ID_BUTTON_13, "Calibrate") + self.button_14 = wx.Button(self, ID_BUTTON_14, "Reset") + self.panel_11 = wx.Panel(self, -1) + self.panel_12 = wx.Panel(self, -1) + + self.__set_properties() + self.__do_layout() + # end wxGlade + + parser = OptionParser (option_class=eng_option) + parser.add_option ("-c", "--ddc-freq", type="eng_float", default=3.9e6, + help="set Rx DDC frequency to FREQ", metavar="FREQ") + parser.add_option ("-a", "--audio_file", default="", + help="audio output file", metavar="FILE") + parser.add_option ("-r", "--radio_file", default="", + help="radio output file", metavar="FILE") + parser.add_option ("-i", "--input_file", default="", + help="radio input file", metavar="FILE") + parser.add_option ("-d", "--decim", type="int", default=250, + help="USRP decimation") + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=first one with a daughterboard)") + (options, args) = parser.parse_args () + + self.usrp_center = options.ddc_freq + usb_rate = 64e6 / options.decim + self.slider_range = usb_rate * 0.9375 + self.f_lo = self.usrp_center - (self.slider_range/2) + self.f_hi = self.usrp_center + (self.slider_range/2) + self.af_sample_rate = 32000 + fir_decim = long (usb_rate / self.af_sample_rate) + + # data point arrays for antenna tuner + self.xdata = [] + self.ydata = [] + + self.fg = gr.flow_graph() + + # radio variables, initial conditions + self.frequency = self.usrp_center + # these map the frequency slider (0-6000) to the actual range + self.f_slider_offset = self.f_lo + self.f_slider_scale = 10000/options.decim + self.spin_ctrl_1.SetRange(self.f_lo,self.f_hi) + self.text_ctrl_1.SetValue(str(int(self.usrp_center))) + self.slider_5.SetValue(0) + self.AM_mode = False + + self.slider_3.SetValue((self.frequency-self.f_slider_offset)/self.f_slider_scale) + self.spin_ctrl_1.SetValue(int(self.frequency)) + + POWERMATE = True + try: + self.pm = powermate.powermate(self) + except: + sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n") + POWERMATE = False + + if POWERMATE: + powermate.EVT_POWERMATE_ROTATE(self, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON(self, self.on_pmButton) + self.active_button = 7 + + # command line options + if options.audio_file == "": SAVE_AUDIO_TO_FILE = False + else: SAVE_AUDIO_TO_FILE = True + if options.radio_file == "": SAVE_RADIO_TO_FILE = False + else: SAVE_RADIO_TO_FILE = True + if options.input_file == "": self.PLAY_FROM_USRP = True + else: self.PLAY_FROM_USRP = False + + if self.PLAY_FROM_USRP: + self.src = usrp.source_c(decim_rate=options.decim) + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.src) + self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec) + self.src.tune(0, self.subdev, self.usrp_center) + self.tune_offset = 0 # -self.usrp_center - self.src.rx_freq(0) + + else: + self.src = gr.file_source (gr.sizeof_gr_complex,options.input_file) + self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band + + # save radio data to a file + if SAVE_RADIO_TO_FILE: + file = gr.file_sink(gr.sizeof_gr_complex, options.radio_file) + self.fg.connect (self.src, file) + + # 2nd DDC + xlate_taps = gr.firdes.low_pass ( \ + 1.0, usb_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING ) + self.xlate = gr.freq_xlating_fir_filter_ccf ( \ + fir_decim, xlate_taps, self.tune_offset, usb_rate ) + + # Complex Audio filter + audio_coeffs = gr.firdes.complex_band_pass ( + 1.0, # gain + self.af_sample_rate, # sample rate + -3000, # low cutoff + 0, # high cutoff + 100, # transition + gr.firdes.WIN_HAMMING) # window + self.slider_1.SetValue(0) + self.slider_2.SetValue(-3000) + + self.audio_filter = gr.fir_filter_ccc ( 1, audio_coeffs) + + # Main +/- 16Khz spectrum display + self.fft = fftsink.fft_sink_c (self.fg, self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240)) + + # AM Sync carrier + if AM_SYNC_DISPLAY: + self.fft2 = fftsink.fft_sink_c (self.fg, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240)) + + c2f = gr.complex_to_float() + + # AM branch + self.sel_am = gr.multiply_const_cc(0) + # the following frequencies turn out to be in radians/sample + # gr.pll_refout_cc(alpha,beta,min_freq,max_freq) + # suggested alpha = X, beta = .25 * X * X + pll = gr.pll_refout_cc(.5,.0625,(2.*math.pi*7.5e3/self.af_sample_rate),(2.*math.pi*6.5e3/self.af_sample_rate)) + self.pll_carrier_scale = gr.multiply_const_cc(complex(10,0)) + am_det = gr.multiply_cc() + # these are for converting +7.5kHz to -7.5kHz + # for some reason gr.conjugate_cc() adds noise ?? + c2f2 = gr.complex_to_float() + c2f3 = gr.complex_to_float() + f2c = gr.float_to_complex() + phaser1 = gr.multiply_const_ff(1) + phaser2 = gr.multiply_const_ff(-1) + + # filter for pll generated carrier + pll_carrier_coeffs = gr.firdes.complex_band_pass ( + 2.0, # gain + self.af_sample_rate, # sample rate + 7400, # low cutoff + 7600, # high cutoff + 100, # transition + gr.firdes.WIN_HAMMING) # window + + self.pll_carrier_filter = gr.fir_filter_ccc ( 1, pll_carrier_coeffs) + + self.sel_sb = gr.multiply_const_ff(1) + combine = gr.add_ff() + + #AGC + sqr1 = gr.multiply_ff() + intr = gr.iir_filter_ffd ( [.004, 0], [0, .999] ) + offset = gr.add_const_ff(1) + agc = gr.divide_ff() + + + self.scale = gr.multiply_const_ff(0.00001) + dst = audio.sink(long(self.af_sample_rate)) + + self.fg.connect(self.src,self.xlate,self.fft) + self.fg.connect(self.xlate,self.audio_filter,self.sel_am,(am_det,0)) + self.fg.connect(self.sel_am,pll,self.pll_carrier_scale,self.pll_carrier_filter,c2f3) + self.fg.connect((c2f3,0),phaser1,(f2c,0)) + self.fg.connect((c2f3,1),phaser2,(f2c,1)) + self.fg.connect(f2c,(am_det,1)) + self.fg.connect(am_det,c2f2,(combine,0)) + self.fg.connect(self.audio_filter,c2f,self.sel_sb,(combine,1)) + if AM_SYNC_DISPLAY: + self.fg.connect(self.pll_carrier_filter,self.fft2) + self.fg.connect(combine,self.scale) + self.fg.connect(self.scale,(sqr1,0)) + self.fg.connect(self.scale,(sqr1,1)) + self.fg.connect(sqr1, intr, offset, (agc, 1)) + self.fg.connect(self.scale,(agc, 0)) + self.fg.connect(agc,dst) + + if SAVE_AUDIO_TO_FILE: + f_out = gr.file_sink(gr.sizeof_short,options.audio_file) + sc1 = gr.multiply_const_ff(64000) + f2s1 = gr.float_to_short() + self.fg.connect(agc,sc1,f2s1,f_out) + + self.fg.start() + + # for mouse position reporting on fft display + em.eventManager.Register(self.Mouse, wx.EVT_MOTION, self.fft.win) + # and left click to re-tune + em.eventManager.Register(self.Click, wx.EVT_LEFT_DOWN, self.fft.win) + + # start a timer to check for web commands + if WEB_CONTROL: + self.timer = UpdateTimer(self, 1000) # every 1000 mSec, 1 Sec + + + wx.EVT_BUTTON(self,ID_BUTTON_1,self.set_lsb) + wx.EVT_BUTTON(self,ID_BUTTON_2,self.set_usb) + wx.EVT_BUTTON(self,ID_BUTTON_3,self.set_am) + wx.EVT_BUTTON(self,ID_BUTTON_4,self.set_cw) + wx.EVT_BUTTON(self,ID_BUTTON_10,self.fwd) + wx.EVT_BUTTON(self,ID_BUTTON_11,self.rew) + wx.EVT_BUTTON(self, ID_BUTTON_13, self.AT_calibrate) + wx.EVT_BUTTON(self, ID_BUTTON_14, self.AT_reset) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_5,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_6,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_7,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_8,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_9,self.on_button) + wx.EVT_SLIDER(self,ID_SLIDER_1,self.set_filter) + wx.EVT_SLIDER(self,ID_SLIDER_2,self.set_filter) + wx.EVT_SLIDER(self,ID_SLIDER_3,self.slide_tune) + wx.EVT_SLIDER(self,ID_SLIDER_4,self.set_volume) + wx.EVT_SLIDER(self,ID_SLIDER_5,self.set_pga) + wx.EVT_SLIDER(self,ID_SLIDER_6,self.am_carrier) + wx.EVT_SLIDER(self,ID_SLIDER_7,self.antenna_tune) + wx.EVT_SPINCTRL(self,ID_SPIN_1,self.spin_tune) + + wx.EVT_MENU(self, ID_EXIT, self.TimeToQuit) + + def __set_properties(self): + # begin wxGlade: MyFrame.__set_properties + self.SetTitle("HF Explorer 2") + self.slider_1.SetMinSize((450, 38)) + self.slider_2.SetMinSize((450, 38)) + self.panel_2.SetMinSize((640, 240)) + self.button_7.SetValue(1) + self.slider_3.SetMinSize((450, 19)) + self.slider_4.SetMinSize((275, 19)) + self.slider_5.SetMinSize((275, 19)) + if AM_SYNC_DISPLAY: + self.panel_9.SetMinSize((640, 240)) + self.slider_6.SetMinSize((300, 38)) + self.slider_7.SetMinSize((400, 38)) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: MyFrame.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1 = wx.FlexGridSizer(11, 2, 0, 0) + sizer_7 = wx.BoxSizer(wx.HORIZONTAL) + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6 = wx.BoxSizer(wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0) + sizer_2.Add(self.button_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_2.Add(self.button_2, 0, wx.ADJUST_MINSIZE, 0) + sizer_2.Add(self.button_3, 0, wx.ADJUST_MINSIZE, 0) + sizer_2.Add(self.button_4, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.panel_5, 1, wx.EXPAND, 0) + sizer_6.Add(self.label_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.text_ctrl_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.panel_6, 1, wx.EXPAND, 0) + sizer_6.Add(self.panel_7, 1, wx.EXPAND, 0) + grid_sizer_1.Add(sizer_6, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_7, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add(self.slider_3, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add(self.spin_ctrl_1, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(sizer_3, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_8, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(self.slider_4, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(self.slider_5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_9, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.button_11, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.button_10, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.panel_3, 1, wx.EXPAND, 0) + sizer_5.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.panel_4, 1, wx.EXPAND, 0) + grid_sizer_1.Add(sizer_5, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_8, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_9, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.label_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.label_4, 0, wx.ALIGN_BOTTOM|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_7, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.panel_10, 1, wx.EXPAND, 0) + sizer_7.Add(self.button_12, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.button_13, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.button_14, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.panel_11, 1, wx.EXPAND, 0) + sizer_7.Add(self.panel_12, 1, wx.EXPAND, 0) + grid_sizer_1.Add(sizer_7, 1, wx.EXPAND, 0) + sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + sizer_1.SetSizeHints(self) + self.Layout() + # end wxGlade + + # Menu exit + def TimeToQuit(self, event): + self.fg.stop() + self.Close(True) + + # Powermate being turned + def on_rotate(self, event): + if self.active_button == 5: + self.slider_1.SetValue(self.slider_1.GetValue()+event.delta) + if self.slider_2.GetValue() > (self.slider_1.GetValue() - 200) : + self.slider_2.SetValue(self.slider_1.GetValue() - 200) + self.filter() + if self.active_button == 6: + self.slider_2.SetValue(self.slider_2.GetValue()+event.delta) + if self.slider_1.GetValue() < (self.slider_2.GetValue() + 200) : + self.slider_1.SetValue(self.slider_2.GetValue() + 200) + self.filter() + if self.active_button == 7: + new = max(0, min(6000, self.slider_3.GetValue() + event.delta)) + self.slider_3.SetValue(new) + self.frequency = (self.f_slider_scale * new) + self.f_slider_offset + self.spin_ctrl_1.SetValue(self.frequency) + if self.AM_mode == False: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + if self.button_12.GetValue(): + self.auto_antenna_tune() + if self.active_button == 8: + new = max(0, min(500, self.slider_4.GetValue() + event.delta)) + self.slider_4.SetValue(new) + self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.))) + if self.active_button == 9: + if self.PLAY_FROM_USRP == False: + if event.delta == -1: + self.src.seek(-1000000,gr.SEEK_CUR) + elif event.delta == 1: + self.src.seek(1000000,gr.SEEK_CUR) + + + # Powermate pressed to switch controlled function + def on_pmButton(self, event): + if event.value == 0: + if self.active_button == 5: + self.active_button = 6 + self.button_5.SetValue(False) + self.button_6.SetValue(True) + elif self.active_button == 6: + self.active_button = 7 + self.button_6.SetValue(False) + self.button_7.SetValue(True) + elif self.active_button == 7: + self.active_button = 8 + self.button_7.SetValue(False) + self.button_8.SetValue(True) + elif self.active_button == 8: + self.active_button = 9 + self.button_8.SetValue(False) + self.button_9.SetValue(True) + elif self.active_button == 9: + self.active_button = 5 + self.button_9.SetValue(False) + self.button_5.SetValue(True) + + # Clicking one PM control button turns the rest off + def on_button(self, event): + id = event.GetId() + if id == ID_BUTTON_5: + self.active_button = 5 + self.button_6.SetValue(False) + self.button_7.SetValue(False) + self.button_8.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_6: + self.active_button = 6 + self.button_5.SetValue(False) + self.button_7.SetValue(False) + self.button_8.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_7: + self.active_button = 7 + self.button_5.SetValue(False) + self.button_6.SetValue(False) + self.button_8.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_8: + self.active_button = 8 + self.button_5.SetValue(False) + self.button_6.SetValue(False) + self.button_7.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_9: + self.active_button = 9 + self.button_5.SetValue(False) + self.button_6.SetValue(False) + self.button_7.SetValue(False) + self.button_8.SetValue(False) + + # Make sure filter settings are legal + def set_filter(self, event): + slider = event.GetId() + slider1 = self.slider_1.GetValue() + slider2 = self.slider_2.GetValue() + if slider == ID_SLIDER_1: + if slider2 > (self.slider_1.GetValue() - 200) : + self.slider_2.SetValue(slider1 - 200) + elif slider == ID_SLIDER_2: + if slider1 < (self.slider_2.GetValue() + 200) : + self.slider_1.SetValue(slider2 + 200) + self.filter() + + # Calculate taps and apply + def filter(self): + audio_coeffs = gr.firdes.complex_band_pass ( + 1.0, # gain + self.af_sample_rate, # sample rate + self.slider_2.GetValue(), # low cutoff + self.slider_1.GetValue(), # high cutoff + 100, # transition + gr.firdes.WIN_HAMMING) # window + self.audio_filter.set_taps(audio_coeffs) + + def set_lsb(self, event): + self.AM_mode = False + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + self.sel_sb.set_k(1) + self.sel_am.set_k(0) + self.slider_1.SetValue(0) + self.slider_2.SetValue(-3000) + self.filter() + + def set_usb(self, event): + self.AM_mode = False + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + self.sel_sb.set_k(1) + self.sel_am.set_k(0) + self.slider_1.SetValue(3000) + self.slider_2.SetValue(0) + self.filter() + + def set_am(self, event): + self.AM_mode = True + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + self.sel_sb.set_k(0) + self.sel_am.set_k(1) + self.slider_1.SetValue(12500) + self.slider_2.SetValue(2500) + self.filter() + + def set_cw(self, event): + self.AM_mode = False + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + self.AM_mode = False + self.sel_sb.set_k(1) + self.sel_am.set_k(0) + self.slider_1.SetValue(-400) + self.slider_2.SetValue(-800) + self.filter() + + def set_volume(self, event): + self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.))) + + def set_pga(self,event): + if self.PLAY_FROM_USRP: + self.subdev.set_gain(self.slider_5.GetValue()) + + def slide_tune(self, event): + self.frequency = (self.f_slider_scale * self.slider_3.GetValue()) + self.f_slider_offset + if self.AM_mode == False: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + self.spin_ctrl_1.SetValue(self.frequency) + if self.button_12.GetValue(): + self.auto_antenna_tune() + + def spin_tune(self, event): + self.frequency = self.spin_ctrl_1.GetValue() + if self.AM_mode == False: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + self.slider_3.SetValue(int((self.frequency-self.f_slider_offset)/self.f_slider_scale)) + if self.button_12.GetValue(): + self.auto_antenna_tune() + + # Seek forwards in file + def fwd(self, event): + if self.PLAY_FROM_USRP == False: + self.src.seek(10000000,gr.SEEK_CUR) + + # Seek backwards in file + def rew(self, event): + if self.PLAY_FROM_USRP == False: + self.src.seek(-10000000,gr.SEEK_CUR) + + # Mouse over fft display - show frequency in tooltip + def Mouse(self,event): + if self.AM_mode: + fRel = ( event.GetX() - 330. ) / 14.266666 - 7.5 + else: + fRel = ( event.GetX() - 330. ) / 14.266666 + self.fft.win.SetToolTip(wx.ToolTip(eng_notation.num_to_str(self.frequency + (fRel*1e3)))) + + # Mouse clicked on fft display - change frequency + def Click(self,event): + fRel = ( event.GetX() - 330. ) / 14.266666 + if self.AM_mode == False: + self.frequency = self.frequency + (fRel*1e3) + else: + self.frequency = self.frequency + (fRel*1e3) - 7.5e3 + self.spin_ctrl_1.SetValue(int(self.frequency)) + self.slider_3.SetValue(int((self.frequency-self.f_slider_offset)/self.f_slider_scale)) + if self.AM_mode == False: + self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset )) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + + # Set power of AM sync carrier + def am_carrier(self,event): + scale = math.pow(10,(self.slider_6.GetValue())/50.) + self.pll_carrier_scale.set_k(complex(scale,0)) + + # Reset AT data and start calibrate over + def AT_reset(self, event): + self.xdata = [] + self.ydata = [] + + # Save AT setting for a particular frequency + def AT_calibrate(self, event): + self.xdata.append(float(self.frequency)) + self.ydata.append(self.slider_7.GetValue()) + if len(self.xdata) > 1: + self.m = [] + self.b = [] + for i in range(0,len(self.xdata)-1): + self.m.append( (self.ydata[i+1] - self.ydata[i]) / (self.xdata[i+1] - self.xdata[i]) ) + self.b.append( self.ydata[i] - self.m[i] * self.xdata[i] ) + + # Lookup calibrated points and calculate interpolated antenna tune voltage. + # This is to automatically tune a narrowband loop antenna when the freq + # is changed, to keep signals peaked. + def auto_antenna_tune(self): + for i in range(0,len(self.xdata)-1): + if (self.frequency > self.xdata[i]) & (self.frequency < self.xdata[i+1]): + self.slider_7.SetValue(self.m[i]*self.frequency + self.b[i]) + self.antenna_tune(0) + + # Slider to set loop antenna capacitance + def antenna_tune(self, evt): + if self.PLAY_FROM_USRP: + self.src.write_aux_dac(0,3,self.slider_7.GetValue()) + + # Timer events - check for web commands + def OnUpdate(self): + cmds = os.listdir("/var/www/cgi-bin/commands/") + if cmds!=[]: + if cmds[0]=='chfreq': + fd=open("/var/www/cgi-bin/commands/chfreq","r") + new=fd.readline() + fd.close() + if new!='': + os.unlink("/var/www/cgi-bin/commands/chfreq") + if ( int(new) >= self.f_lo ) & ( int(new) <= self.f_hi ): + self.frequency = int(new) + self.slider_3.SetValue(( self.frequency - self.f_slider_offset) / self.f_slider_scale ) + self.spin_ctrl_1.SetValue(self.frequency) + if self.button_12.GetValue(): + self.auto_antenna_tune() + if self.AM_mode: + self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset - 7.5e3 )) + else: + self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset )) + + if cmds[0]=='chvolume': + fd=open("/var/www/cgi-bin/commands/chvolume","r") + new=fd.readline() + fd.close() + if new!='': + os.unlink("/var/www/cgi-bin/commands/chvolume") + if ( int(new) >= 0 ) & ( int(new) <= 500 ): + self.volume = int(new) + self.slider_4.SetValue(self.volume) + self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.))) + + else: # no new web commands, update state + fh = open("/var/www/cgi-bin/state/freq","w") + fh.write(str(int(self.frequency))+'\n') + fh.close() + fh = open("/var/www/cgi-bin/state/volume","w") + fh.write(str(self.slider_4.GetValue())+'\n') + fh.close() + + +# end of class MyFrame + +# wx.Timer to check for web updates +class UpdateTimer(wx.Timer): + def __init__(self, target, dur=1000): + wx.Timer.__init__(self) + self.target = target + self.Start(dur) + + def Notify(self): + """Called every timer interval""" + if self.target: + self.target.OnUpdate() + + +class MyApp(wx.App): + def OnInit(self): + frame = MyFrame(None, -1, "HF Explorer 2") + frame.Show(True) + self.SetTopWindow(frame) + return True + +app = MyApp(0) +app.MainLoop() + diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx_help b/gnuradio-examples/python/apps/hf_explorer/hfx_help new file mode 100644 index 00000000..9a52dd2b --- /dev/null +++ b/gnuradio-examples/python/apps/hf_explorer/hfx_help @@ -0,0 +1,180 @@ + + HF Explorer Help + + ----------------------------------------------------------------------- + + Command Line Switches: + + -c DDC center frequency, set band. + -c 7.2e6 or -c 7.2M for 40 meter ham band. + Default is 3.9e6 80 meter ham band. + Example: + + hfx.py -c 9500k + + starts up in the 31 meter band. + + -a Audio output file. Output file for 32kHz two channel + signed word audio. Two channels are used for + independent sideband. This file can be converted + to a wav file with sox. Example: + + sox -c 2 -r 3200 file.sw file.wav + + sox needs the .sw extension to indicate file type. + If not specified no audio file is created. + + -r Radio output file. File to write RF data to for later + demodulation. Records the entire band to disk, width + determined by sample rate/decimation. Be sure to + note the decimation and center freq for later use! + Example: + + hfx.py -c 900e3 -d 80 -r rf_data_AM-c900e3-d80 + + writes a pre-demod rf file centered on 900kHz with a + bandwidth of 800kHz (That's 80 AM stations!). The + center and decimation could be put in the filename for + proper use later. + If not specified no rf data file is created. + At default 250 decimation disk usage is about + 8Gb / hour. + + -i Radio input file. Use to play back a previously + recorded rf data file. Example: + + hfx.py -c 900e3 -d 80 -i rf_data_AM-c900e3-d80 + + plays back the previously recorded band, no + usrp hardware needed. Tune about the 800kHz wide band. + When playing a recorded file, time controls + fast-forward and rewind are available. + + -d Decimation. Sets sample rate and bandwidth. + This is the factor that the usrp sample rate, 64e6, + is divided by. Default is 250 for 256kHz bandwidth + which is enough to record a ham band without + eating up disk space too fast. The 64e6 sample + rate limits the upper practical frequency to 32MHz. + The Basic RX transformer limits the lower frequency + to about 200kHz. + + + Powermate Knob: + + A Powermate knob is recommended but not necessary. If a knob + is used, it is in one of 3 or 4 modes controlling frequency, + volume, filter and (if playing a recorded file) time. + Pushing the knob switches mode and the buttons on the HFX panel + change to show which mode is in effect. Then just turn the knob + to set frequency, volume, filter or go fast forward or rewind. + + + Bandswitch: + + Across the top are a set of predefined bands and buttons + to rapidly switch to the center of that band. To change a band, + type the frequency in Hz into the box under "Center Frequency", + then press "Set" on the left, then the button you want to + program. From then on (untill the program is exited) pushing + that button takes you to that band. To make a band button + permenant edit the hfx.py script with whatever frequency you + want assigned to what button. + + + Frequency: + + There are 6 ways to set the frequency. + 1) Move the slider with the mouse + 2) Use the Spin Control up/down arrows (very fine 1Hz control) + 3) Type the frequency in Hz into the Spin Control + 4) Turn the Powermate knob + 5) Web control. + 6) Clicking on the FFT display to set demod center. This is very + convenient for tuning +-15kHz when you see a signal on the + display. If in Lower Sideband, clicking just to the right of + a signal will tune to it immediately. Clicking several times + on the far right right or left of the display will rapidly + tune up or down the band. + + + Volume: + + Move the volume slider with the mouse, or push the Powermate knob + untill the volume button is active, or click on the volume button, + then turn the knob. Volume can also be set by web control if web + control is setup and enabled. + + + Filter: + + Similar to volume, switches in any of 30 audio filters from 600 + to 3600Hz in Sideband or up to 5kHz in AM. + + + Mode: + + Demodulation modes are chosen by clicking on the buttons for + Lower Sideband, Upper Sideband, or AM. + + + PGA: + + PGA slider sets the rf gain in the Analog-to-Digital converter + before digitizing. 0 to 20db gain easily shows up on the FFT + display. + + + Time: + + When playing back a recorded RF data file, you can enjoy the + freedom of rewinding or fast-forwarding. Replay a weak signal + or skip through annoying AM commercials. + + + Antennas and Preamps: + + The USRP Basic RX board is not sensitive enough for anything but + the strongest signals. In my experience about 40 db of small + signal gain is required to make the HFX as sensitive as other + receivers. Some working amplifiers are the Ramsey PR-2 with 20db + gain, fairly low noise and more bandwidth than we can use here. + Also the amp modules from Advanced Receiver Research are nice. + I use an ARR 7-7.4MHz GaAsFET 29db amp with .5db noise at the + apex of a 40 meter dipole with excellent results. Another + amp I like is a Minicircuits ZHL-32A 29db amp but they are + expensive and hard to find. Also it may help to use some filters + to keep strong local signals from the ADC, or limit rf input + to the band of interest, etc. + Resonant outdoor antennas, like a dipole, in a low-noise (away + from consumer electronics) environment are nice. Long random wires + with a tuner work. I like a small indoor tuned loop made from 10ft + of 1/4" copper tube, a 365pf tuning cap and a pickup loop connected + to rg-58. + + + Web Control: + + To control your radio remotely, ensure you have a web server + (Apache, etc) working and a compatible directory structure in + place. Directories /var/www/cgi-bin/commands and + /var/www/cgi-bin/state must already exist. You will need a + home page with forms and a set of scripts to put commands in + and put the current state on the home page. email me for further + help. Setting WEB_CONTROL to True in hfx.py turns on the timers + that check for commands and update the state. + + + IF Output: + + There is a provision for outputting un-demodulated complex + through the audio out in stereo for use with Digital Radio + Mondial (DRM) or using a seperate demodulation program like + SDRadio (by I2PHD). + Set IF_OUTPUT to True in weaver_isb_am1_usrp4.py. + + + --Good luck and happy LW/MW/SW Exploring. + Chuck + chuckek@musicriver.homeunix.com + diff --git a/gnuradio-examples/python/apps/hf_radio/README.TXT b/gnuradio-examples/python/apps/hf_radio/README.TXT new file mode 100644 index 00000000..df8a901e --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/README.TXT @@ -0,0 +1,53 @@ +The files in this directory implement a fairly simple HF radio that works +with the basic rx daughter board on the USRP. + +Many thanks to the Gnu Radio folks for a great new way to waste large blocks +of time in infinitely tweaking a huge number of free parameters. + +Start the receiver by running the radio.py in this directory. Or from the +Python prompt type "from radio import *" and you'll get the prompt back +with the receiver running. You can then poke around to see what's going on. + +There are two spectrum displays. One is the output of the USRP and displays +about 300KHz of bandwidth centered at the current tuning freq. The other +displays the output spectrum of the demodulator. + +The demodulator does AM demod using the complex modulus block from gr. It +does SSB demod using the frequency translating fir filter as a complex +hilbert transformer. The taps for this filter were generated using a program +called Scilab and the Scilab program in the file hfir.sci. More details in +the associated files. + +Tune the receiver using the spin buttons under the big frequency display. + +The agc block is a roll your own. The standard agc in the newer CVS updates +seems to work but doesn't seem to have adjustable time constants or provide +access to internal signal nodes which are used for the RSSI. + +The AGC authority (a sort of gain parameter) and the reference level used +in the power to dB computagion can be adjusted using the spin buttons. + +The audio bandwidth can be similarly adjusted from about 50Hz to 10KHz. + +The GUI layout was produced using wxGlade. The file radio.xml is the GUI +specification. It will produce a file called ui.py which is subclassed +by classes defined in radio.py. The ui.py is purely generated by wxGlade +all app specific code for the GUI is in radio.py. + +Most of the actual signal processing code is built up in the other included +files using the hierarchical block facilities. This organization should +make it easier to tweak to your heart's content. + +Known bugs weakness and other + +wxPython and wxGlade seem to conspire to insure that the layout can never +be exactly what you have in mind. + +Some of the controls don't behave as one might like. wx spin controls +and spin boxes only support integers so it is rather a nuisance to make +units come out nice. In the process of development I came up with a reasonable +kluge so there is a mixture of approaches. + +Enjoy. + +M. Revnell 2006-Jan-06 diff --git a/gnuradio-examples/python/apps/hf_radio/hfir.sci b/gnuradio-examples/python/apps/hf_radio/hfir.sci new file mode 100644 index 00000000..a2d5e2a6 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/hfir.sci @@ -0,0 +1,59 @@ +// designs a complex tap fir filter akin to the hilbert transformer. +// +// The hilbert transformer is classified as a linear phase fir +// with allpass magnitude response and 90 degree phase response for +// positive frequencies and -90 degrees phase for negative frequencies. +// Or, if you prefer, normalized frequencies between .5 and 1 since +// negative frequencies don't really have much meaning outside the complex +// domain. +// +// Normally one would use the hilbert transformer in one leg of a complex +// processing block and a compensating delay in the other. +// +// This one differs in the following respects: +// It is low pass with a cutoff of .078125 +// The filter is a lowpass kaiser windowed filter with parameter 3 +// The phase response is 45 degrees for positive frequencies and -45 +// for negative frequencies. +// The coefficent set is used in one path and the same coefficients +// are used time reversed in the other. This results in the net effect +// of +/- 90 degrees as in the usual hilbert application. +// +// The coefficient set can be used in the gnuradio frequency translating +// fir filter for ssb demodulation. +// +// This isn't as computationally efficient as using the hilbert transformer +// and compensating delay but fascinating none the less. +// +// This program is for the scilab language a very powerful free math +// package similar to Matlab with infinitely better price/performace. +// +// compute the prototype lowpass fir +// length is 255 (odd) for the same symmetry reasons as the hilbert transformer + +len = 1023; +l2 = floor(len/2); +md = l2 + 1; +l3 = md + 1; + +h = wfir( 'lp', len, [10.0/256 0], 'kr', [3 0] ); + +H = fft(h); + +H(1:l2)=H(1:l2)*exp(%i*%pi/4); +H(md)=0+%i*0; +H(l3:len)=H(l3:len)*exp(-%i*%pi/4); + +j=real(ifft(H)); +k(1:len)=j(len:-1:1); +x=j+%i.*k; +X=fft(x); +plot(abs(X)) + +f = file('open','taps') +for i=(1:len) + fprintf( f, '%f%+fj', j(i), k(i) ) +end + +file('close',f) + diff --git a/gnuradio-examples/python/apps/hf_radio/input.py b/gnuradio-examples/python/apps/hf_radio/input.py new file mode 100644 index 00000000..3a62a68c --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/input.py @@ -0,0 +1,41 @@ +# Basic USRP setup and control. +# It's only ever been tried with a basic rx daughter card. +# +# Imagine that the gnuradio boilerplate is here. +# +# M. Revnell 2005-Dec + +from gnuradio import gr, gru, optfir +from gnuradio import usrp +import usrp_dbid +import math + +# Put special knowlege of usrp here. + +class input: + def __init__( self, decim ): + self.freq = -2.5e6 + self.src = usrp.source_c( ) + self.subdev = usrp.pick_subdev( self.src, + (usrp_dbid.BASIC_RX, + usrp_dbid.TV_RX)) + + print self.subdev + + self.subdevice = usrp.selected_subdev( self.src, + self.subdev ) + + self.mux = usrp.determine_rx_mux_value( self.src, + self.subdev ) + self.decim = decim + + self.adc_rate = self.src.adc_rate() + self.usrp_rate = self.adc_rate / self.decim + self.src.set_decim_rate( self.decim ) + self.src.set_mux( self.mux ) + usrp.tune( self.src, 0, self.subdevice, self.freq ) + + def set_freq( self, x ): + r = usrp.tune( self.src, 0, self.subdevice, -x ) + if r: + self.freq = -x diff --git a/gnuradio-examples/python/apps/hf_radio/output.py b/gnuradio-examples/python/apps/hf_radio/output.py new file mode 100644 index 00000000..dc9caf52 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/output.py @@ -0,0 +1,17 @@ +# Audio output with a volume control. +# +# M. Revnell 2005-Dec + +from gnuradio import gr, gru +from gnuradio import audio + +class output( gr.hier_block ): + def __init__( self, fg, rate ): + self.out = audio.sink( rate ) + self.vol = gr.multiply_const_ff( 0.1 ) + fg.connect( self.vol, self.out ) + gr.hier_block.__init__(self, fg, self.vol, None ) + + def set( self, val ): + self.vol.set_k( val ) + diff --git a/gnuradio-examples/python/apps/hf_radio/radio.py b/gnuradio-examples/python/apps/hf_radio/radio.py new file mode 100755 index 00000000..9f444b91 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/radio.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +# GUI interactions and high level connections handled here. +# +# Interacts with classes defined by wxGlade in ui.py. +# +# The usual gnuradio copyright boilerplate incorperated here by reference. +# +# M. Revnell 2006-Jan + +from threading import * +import wx +import wx.lib.evtmgr as em +import time + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.wxgui import fftsink +from gnuradio.wxgui import waterfallsink +from gnuradio.wxgui import scopesink + +from input import * +from output import * +from ssbdemod import * +from ssbagc import * +from ui import * +from math import log10 + +class graph( gr.hier_block ): + def __init__( self, fg ): + self.graph = fg + self.fe_decim = 250 + self.src = input( self.fe_decim ) + self.adc_rate = self.src.adc_rate + self.fe_rate = self.adc_rate / self.fe_decim + self.filter_decim = 1 + self.audio_decim = 16 + self.demod_rate = self.fe_rate / self.filter_decim + self.audio_rate = self.demod_rate / self.audio_decim + + self.demod = ssb_demod( fg, self.demod_rate, self.audio_rate ) + self.agc = agc( fg ) + #self.agc = gr.agc_ff() + self.out = output( fg, self.audio_rate ) + + fg.connect( self.src.src, + self.demod, + self.agc, + self.out ) + + gr.hier_block.__init__( self, fg, None, None ) + + def tune( self, freq ): + fe_target = -freq + self.src.set_freq( fe_target ) + fe_freq = self.src.src.rx_freq( 0 ) + demod_cf = fe_target - fe_freq + self.demod.tune( demod_cf ) + +class radio_frame( ui_frame ): + def __init__( self, block, *args, **kwds ): + ui_frame.__init__( self, *args, **kwds ) + self.block = block + self.freq_disp.SetRange(0, 30e6) + f = self.block.src.freq + self.freq_disp.SetValue( -f ) + self.volume.SetRange( 0, 20 ) + self.pga.SetRange( 0, 20 ) + self.rssi_range = 1 + self.rssi.SetRange( self.rssi_range ) + self.agc_max.SetValue( str( self.rssi_range ) ) + self.spin_e0.SetValue( 50 ) + self.spin_e1.SetValue( 50 ) + self.spin_e2.SetValue( 50 ) + self.spin_e3.SetValue( 50 ) + self.spin_e4.SetValue( 50 ) + self.spin_e5.SetValue( 50 ) + self.spin_e6.SetValue( 50 ) + bw = 3.3e3 + self.bandwidth.SetValue( str( bw ) ) + self.block.demod.set_bw( bw ) + self.bw_spin.SetValue( 5 ) + agc_gain = self.block.agc.gain.k() + self.agc_gain_s.SetValue( 5 ) + self.agc_gain.SetValue( str( agc_gain ) ) + agc_ref = self.block.agc.offs.k() + self.agc_ref.SetValue( str( agc_ref ) ) + self.agc_ref_s.SetValue( 5 ) + + self.fespectrum = fftsink.fft_sink_c( + self.block.graph, + self.fe_panel, + fft_size=512, + sample_rate = block.fe_rate, + baseband_freq = 0, + average = False, + size = ( 680, 140 ) ) + + self.ifspectrum = fftsink.fft_sink_c( + self.block.graph, + self.if_panel, + fft_size=512, + sample_rate = block.audio_rate, + baseband_freq = 0, + average = False, + size = ( 680, 140 ) ) + + em.eventManager.Register( self.fe_mouse, + wx.EVT_MOTION, + self.fespectrum.win ) + + em.eventManager.Register( self.fe_click, + wx.EVT_LEFT_DOWN, + self.fespectrum.win ) + + block.graph.connect( block.src.src, self.fespectrum ) + block.graph.connect( block.demod.xlate, self.ifspectrum ) + + def agc_ref_up( self, event ): + self.agc_ref_s.SetValue( 5 ) + r = float( self.agc_ref.GetValue() ) + r = r + 5 + self.agc_ref.SetValue( str( r ) ) + self.block.agc.offs.set_k( r ) + + def agc_ref_down( self, event ): + self.agc_ref_s.SetValue( 5 ) + r = float( self.agc_ref.GetValue() ) + r = r - 5 + self.agc_ref.SetValue( str( r ) ) + self.block.agc.offs.set_k( r ) + + def agc_gain_up( self, event ): + self.agc_gain_s.SetValue( 5 ) + g = float(self.agc_gain.GetValue()) + g = g + 10 + self.agc_gain.SetValue( str( g ) ) + self.block.agc.gain.set_k( g ) + + def agc_gain_down( self, event ): + self.agc_gain_s.SetValue( 5 ) + g = float(self.agc_gain.GetValue()) + g = g - 10 + self.agc_gain.SetValue( str( g ) ) + self.block.agc.gain.set_k( g ) + + def fe_mouse( self, event ): + f = int(self.freq_disp.GetValue()) + f = f+((event.GetX()-346.)*(400./610.))*1000 + self.fespectrum.win.SetToolTip( + wx.ToolTip( eng_notation.num_to_str(f))) + + def fe_click( self, event ): + f = int(self.freq_disp.GetValue()) + f = f+((event.GetX()-346.)*(400./610.))*1000 + self.tune( f ) + + def setrssi( self, level ): + if level < 0: + level = 0 + if level > self.rssi_range: + self.rssi_range = level + self.rssi.SetRange( level ) + self.agc_max.SetValue( str( level )) + self.rssi.SetValue( level ) + self.agc_level.SetValue( str( level )) + + def tune_evt( self, event ): + f = self.freq_disp.GetValue() + self.tune( f ) + + def tune( self, frequency ): + self.freq_disp.SetValue( frequency ) + self.block.tune( frequency ) + + def up_e0( self, event ): + self.spin_e0.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e0 ) + + def down_e0( self, event ): + self.spin_e0.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e0 ) + + def up_e1( self, event ): + self.spin_e1.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e1 ) + + def down_e1( self, event ): + self.spin_e1.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e1 ) + + def up_e2( self, event ): + self.spin_e2.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e2 ) + + def down_e2( self, event ): + self.spin_e2.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e2 ) + + def up_e3( self, event ): + self.spin_e3.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e3 ) + + def down_e3( self, event ): + self.spin_e3.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e3 ) + + def up_e4( self, event ): + self.spin_e4.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e4 ) + + def down_e4( self, event ): + self.spin_e4.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e4 ) + + def up_e5( self, event ): + self.spin_e5.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e5 ) + + def down_e5( self, event ): + self.spin_e5.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e5 ) + + def up_e6( self, event ): + self.spin_e6.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e6 ) + + def down_e6( self, event ): + self.spin_e6.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e6 ) + + def event_pga( self, event ): + self.block.src.src.set_pga( 0, self.pga.GetValue()) + + def event_vol( self, event ): + self.block.out.set( self.volume.GetValue()/20.0 ) + + def set_usb( self, event ): + self.block.demod.upper_sb() + + def set_lsb( self, event ): + self.block.demod.lower_sb() + + def set_am( self, event ): + self.block.demod.set_am() + + def bw_up( self, event ): + self.bw_spin.SetValue( 5 ) + bw = float(self.bandwidth.GetValue()) + bw = bw + 20.0 + if bw > 10e3: + bw = 10e3 + self.bandwidth.SetValue( str( bw ) ) + self.block.demod.set_bw( bw ) + + def bw_down( self, event ): + self.bw_spin.SetValue( 5 ) + bw = float(self.bandwidth.GetValue()) + bw = bw - 20.0 + if bw < 50: + bw = 50 + self.bandwidth.SetValue( str( bw ) ) + self.block.demod.set_bw( bw ) + + +class radio( wx.App ): + def OnInit( self ): + self.graph = gr.flow_graph() + self.block = graph( self.graph ) + self.frame = radio_frame( self.block, None, -1, "Title" ) + self.frame.Show( True ) + self.SetTopWindow( self.frame ) + return True + +a=radio( 0 ) + +l=gr.probe_signal_f() +#l=gr.probe_avg_mag_sqrd_f(1,.001) +a.graph.connect(a.block.agc.offs,l ) +#a.graph.connect(a.block.demod,l) + +def main_function(): + global a + a.MainLoop() + + +def rssi_function(): + global a + global l + while 1: + level = l.level() + wx.CallAfter( a.frame.setrssi, level ) + time.sleep( .1 ) + +thread1 = Thread( target = main_function ) +thread2 = Thread( target = rssi_function ) + +thread1.start() +thread2.start() + +a.graph.start() + diff --git a/gnuradio-examples/python/apps/hf_radio/radio.xml b/gnuradio-examples/python/apps/hf_radio/radio.xml new file mode 100644 index 00000000..81daa19b --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/radio.xml @@ -0,0 +1,441 @@ + + + + + + + frame_1 + + wxVERTICAL + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxEXPAND + 0 + + + wxVERTICAL + + wxEXPAND|wxADJUST_MINSIZE + 0 + + + + 32 + default + + normal + 0 + + + + tune_evt + + + + + wxEXPAND + 0 + + + 0 + 2 + 3 + 0 + + wxEXPAND + 0 + + + 0 + 1 + 7 + 0 + + wxADJUST_MINSIZE + 0 + + + + up_e6 + down_e6 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e5 + down_e5 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e4 + down_e4 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e3 + down_e3 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e2 + down_e2 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e1 + down_e1 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e0 + down_e0 + + + + + + + wxEXPAND + 0 + + + + + + + wxEXPAND + 0 + + + + + + + wxADJUST_MINSIZE + 0 + + + + + set_lsb + + + + + wxADJUST_MINSIZE + 0 + + + + + set_usb + + + + + wxADJUST_MINSIZE + 0 + + + + + set_am + + + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + wxEXPAND + 0 + + + 0 + 2 + 4 + 0 + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + wxADJUST_MINSIZE + 0 + + + + event_vol + + + + + wxADJUST_MINSIZE + 0 + + + + event_pga + + + + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + + wxEXPAND + 0 + + + 0 + 2 + 4 + 0 + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + + agc_gain_up + agc_gain_down + + + + + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + + agc_ref_up + agc_ref_down + + + + + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + + bw_up + bw_down + + + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + + wxEXPAND|wxADJUST_MINSIZE + 0 + + + #ff0000 + + 10 + 315, 10 + + + + + + + + wxEXPAND + 0 + + + + + + + wxEXPAND + 0 + + + + + + + + diff --git a/gnuradio-examples/python/apps/hf_radio/ssb_taps b/gnuradio-examples/python/apps/hf_radio/ssb_taps new file mode 100644 index 00000000..0ef3bbf2 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ssb_taps @@ -0,0 +1,1023 @@ +-0.000035-0.000009j +-0.000066-0.000020j +-0.000080-0.000044j +-0.000084-0.000071j +-0.000077-0.000100j +-0.000063-0.000127j +-0.000041-0.000150j +-0.000013-0.000167j +0.000020-0.000177j +0.000054-0.000180j +0.000089-0.000174j +0.000121-0.000161j +0.000150-0.000140j +0.000173-0.000113j +0.000188-0.000081j +0.000196-0.000046j +0.000194-0.000011j +0.000184+0.000022j +0.000165+0.000052j +0.000139+0.000077j +0.000107+0.000093j +0.000071+0.000102j +0.000034+0.000101j +-0.000002+0.000090j +-0.000036+0.000070j +-0.000064+0.000042j +-0.000086+0.000006j +-0.000098-0.000034j +-0.000101-0.000077j +-0.000093-0.000120j +-0.000076-0.000161j +-0.000049-0.000197j +-0.000014-0.000227j +0.000026-0.000248j +0.000071-0.000259j +0.000117-0.000259j +0.000162-0.000249j +0.000203-0.000228j +0.000237-0.000199j +0.000263-0.000162j +0.000279-0.000120j +0.000284-0.000075j +0.000278-0.000031j +0.000260+0.000010j +0.000232+0.000045j +0.000196+0.000073j +0.000153+0.000090j +0.000106+0.000095j +0.000059+0.000089j +0.000014+0.000071j +-0.000027+0.000041j +-0.000059+0.000002j +-0.000082-0.000046j +-0.000093-0.000098j +-0.000091-0.000152j +-0.000077-0.000206j +-0.000050-0.000255j +-0.000012-0.000298j +0.000034-0.000330j +0.000088-0.000351j +0.000145-0.000359j +0.000202-0.000354j +0.000256-0.000335j +0.000304-0.000304j +0.000343-0.000262j +0.000370-0.000213j +0.000384-0.000158j +0.000384-0.000102j +0.000369-0.000048j +0.000341+0.000002j +0.000302+0.000042j +0.000252+0.000072j +0.000196+0.000088j +0.000137+0.000089j +0.000078+0.000075j +0.000024+0.000047j +-0.000023+0.000005j +-0.000059-0.000048j +-0.000082-0.000109j +-0.000090-0.000175j +-0.000081-0.000242j +-0.000058-0.000306j +-0.000019-0.000364j +0.000032-0.000411j +0.000093-0.000445j +0.000161-0.000465j +0.000232-0.000467j +0.000301-0.000453j +0.000365-0.000423j +0.000419-0.000379j +0.000461-0.000323j +0.000487-0.000259j +0.000497-0.000190j +0.000489-0.000121j +0.000464-0.000056j +0.000423+0.000001j +0.000369+0.000046j +0.000304+0.000076j +0.000233+0.000089j +0.000160+0.000083j +0.000089+0.000060j +0.000025+0.000018j +-0.000027-0.000038j +-0.000065-0.000107j +-0.000086-0.000185j +-0.000088-0.000266j +-0.000071-0.000347j +-0.000035-0.000422j +0.000019-0.000487j +0.000086-0.000538j +0.000164-0.000573j +0.000248-0.000588j +0.000334-0.000582j +0.000415-0.000557j +0.000488-0.000513j +0.000548-0.000452j +0.000592-0.000379j +0.000616-0.000297j +0.000619-0.000213j +0.000600-0.000130j +0.000561-0.000054j +0.000504+0.000010j +0.000432+0.000058j +0.000350+0.000086j +0.000261+0.000093j +0.000173+0.000078j +0.000090+0.000040j +0.000017-0.000017j +-0.000040-0.000092j +-0.000078-0.000180j +-0.000095-0.000275j +-0.000088-0.000374j +-0.000058-0.000469j +-0.000006-0.000555j +0.000065-0.000627j +0.000152-0.000681j +0.000250-0.000712j +0.000352-0.000720j +0.000454-0.000703j +0.000548-0.000663j +0.000630-0.000601j +0.000694-0.000521j +0.000737-0.000428j +0.000755-0.000327j +0.000748-0.000225j +0.000715-0.000128j +0.000659-0.000042j +0.000582+0.000028j +0.000490+0.000077j +0.000387+0.000101j +0.000280+0.000099j +0.000175+0.000070j +0.000080+0.000015j +-0.000001-0.000063j +-0.000061-0.000159j +-0.000097-0.000268j +-0.000106-0.000385j +-0.000087-0.000501j +-0.000040-0.000611j +0.000032-0.000708j +0.000125-0.000786j +0.000235-0.000839j +0.000354-0.000866j +0.000477-0.000863j +0.000595-0.000831j +0.000702-0.000772j +0.000792-0.000688j +0.000859-0.000585j +0.000898-0.000469j +0.000907-0.000347j +0.000886-0.000227j +0.000835-0.000115j +0.000757-0.000019j +0.000657+0.000055j +0.000540+0.000102j +0.000415+0.000119j +0.000287+0.000103j +0.000165+0.000056j +0.000058-0.000020j +-0.000029-0.000122j +-0.000090-0.000243j +-0.000121-0.000378j +-0.000118-0.000517j +-0.000082-0.000653j +-0.000014-0.000778j +0.000082-0.000885j +0.000201-0.000966j +0.000337-0.001017j +0.000481-0.001034j +0.000626-0.001016j +0.000762-0.000965j +0.000882-0.000882j +0.000978-0.000772j +0.001044-0.000643j +0.001076-0.000501j +0.001072-0.000355j +0.001032-0.000215j +0.000958-0.000089j +0.000854+0.000016j +0.000726+0.000091j +0.000582+0.000133j +0.000431+0.000138j +0.000281+0.000105j +0.000143+0.000035j +0.000024-0.000068j +-0.000068-0.000199j +-0.000126-0.000350j +-0.000147-0.000513j +-0.000128-0.000677j +-0.000070-0.000834j +0.000024-0.000974j +0.000150-0.001089j +0.000300-0.001171j +0.000465-0.001216j +0.000637-0.001219j +0.000805-0.001182j +0.000960-0.001105j +0.001091-0.000993j +0.001191-0.000853j +0.001253-0.000692j +0.001274-0.000521j +0.001252-0.000350j +0.001188-0.000189j +0.001085-0.000049j +0.000950+0.000062j +0.000790+0.000136j +0.000614+0.000168j +0.000435+0.000156j +0.000261+0.000099j +0.000105+0.000000j +-0.000024-0.000136j +-0.000117-0.000301j +-0.000169-0.000486j +-0.000175-0.000680j +-0.000134-0.000872j +-0.000048-0.001051j +0.000079-0.001206j +0.000240-0.001326j +0.000426-0.001406j +0.000626-0.001439j +0.000829-0.001424j +0.001022-0.001361j +0.001195-0.001252j +0.001336-0.001106j +0.001437-0.000929j +0.001491-0.000733j +0.001496-0.000529j +0.001449-0.000330j +0.001354-0.000148j +0.001217+0.000005j +0.001044+0.000120j +0.000846+0.000188j +0.000635+0.000206j +0.000424+0.000170j +0.000226+0.000083j +0.000053-0.000053j +-0.000084-0.000228j +-0.000176-0.000434j +-0.000216-0.000659j +-0.000201-0.000889j +-0.000131-0.001111j +-0.000009-0.001312j +0.000158-0.001480j +0.000362-0.001604j +0.000590-0.001677j +0.000829-0.001694j +0.001066-0.001653j +0.001286-0.001556j +0.001477-0.001408j +0.001626-0.001219j +0.001724-0.001000j +0.001765-0.000762j +0.001746-0.000522j +0.001668-0.000293j +0.001534-0.000090j +0.001353+0.000075j +0.001135+0.000190j +0.000893+0.000247j +0.000642+0.000243j +0.000396+0.000176j +0.000172+0.000049j +-0.000017-0.000131j +-0.000159-0.000355j +-0.000244-0.000609j +-0.000266-0.000880j +-0.000222-0.001151j +-0.000114-0.001406j +0.000053-0.001630j +0.000270-0.001810j +0.000524-0.001934j +0.000802-0.001994j +0.001087-0.001987j +0.001362-0.001911j +0.001611-0.001772j +0.001819-0.001576j +0.001973-0.001336j +0.002063-0.001065j +0.002084-0.000779j +0.002033-0.000497j +0.001914-0.000236j +0.001732-0.000011j +0.001498+0.000162j +0.001225+0.000272j +0.000931+0.000312j +0.000633+0.000277j +0.000349+0.000168j +0.000097-0.000009j +-0.000107-0.000246j +-0.000250-0.000528j +-0.000322-0.000841j +-0.000316-0.001166j +-0.000233-0.001484j +-0.000076-0.001775j +0.000148-0.002024j +0.000426-0.002213j +0.000743-0.002332j +0.001080-0.002373j +0.001418-0.002332j +0.001736-0.002211j +0.002017-0.002017j +0.002241-0.001760j +0.002397-0.001457j +0.002473-0.001124j +0.002464-0.000783j +0.002371-0.000453j +0.002198-0.000156j +0.001954+0.000091j +0.001654+0.000269j +0.001316+0.000369j +0.000959+0.000381j +0.000606+0.000303j +0.000279+0.000139j +-0.000003-0.000103j +-0.000220-0.000411j +-0.000359-0.000768j +-0.000408-0.001152j +-0.000365-0.001542j +-0.000229-0.001915j +-0.000006-0.002248j +0.000292-0.002522j +0.000648-0.002719j +0.001042-0.002826j +0.001452-0.002837j +0.001853-0.002750j +0.002223-0.002569j +0.002537-0.002304j +0.002778-0.001971j +0.002930-0.001588j +0.002984-0.001179j +0.002933-0.000770j +0.002782-0.000384j +0.002538-0.000046j +0.002215+0.000222j +0.001831+0.000402j +0.001410+0.000481j +0.000976+0.000452j +0.000557+0.000316j +0.000179+0.000077j +-0.000134-0.000252j +-0.000362-0.000654j +-0.000490-0.001105j +-0.000506-0.001580j +-0.000407-0.002052j +-0.000197-0.002492j +0.000113-0.002875j +0.000508-0.003176j +0.000966-0.003377j +0.001460-0.003464j +0.001963-0.003432j +0.002444-0.003281j +0.002876-0.003019j +0.003231-0.002659j +0.003488-0.002224j +0.003631-0.001739j +0.003649-0.001233j +0.003540-0.000737j +0.003309-0.000282j +0.002969+0.000103j +0.002539+0.000393j +0.002044+0.000568j +0.001515+0.000614j +0.000982+0.000525j +0.000480+0.000304j +0.000039-0.000039j +-0.000311-0.000487j +-0.000547-0.001016j +-0.000652-0.001595j +-0.000615-0.002193j +-0.000436-0.002773j +-0.000122-0.003301j +0.000311-0.003746j +0.000842-0.004081j +0.001440-0.004282j +0.002071-0.004338j +0.002700-0.004243j +0.003289-0.004000j +0.003803-0.003622j +0.004210-0.003132j +0.004485-0.002556j +0.004610-0.001930j +0.004574-0.001291j +0.004379-0.000679j +0.004034-0.000133j +0.003558+0.000313j +0.002977+0.000627j +0.002327+0.000787j +0.001647+0.000779j +0.000977+0.000598j +0.000360+0.000250j +-0.000163-0.000249j +-0.000559-0.000872j +-0.000799-0.001587j +-0.000864-0.002354j +-0.000744-0.003129j +-0.000442-0.003866j +0.000031-0.004522j +0.000651-0.005057j +0.001385-0.005437j +0.002193-0.005637j +0.003030-0.005643j +0.003848-0.005451j +0.004597-0.005069j +0.005234-0.004519j +0.005718-0.003830j +0.006019-0.003044j +0.006114-0.002206j +0.005997-0.001368j +0.005669-0.000583j +0.005147+0.000099j +0.004460+0.000631j +0.003647+0.000975j +0.002757+0.001105j +0.001842+0.001003j +0.000961+0.000668j +0.000168+0.000111j +-0.000482-0.000643j +-0.000944-0.001555j +-0.001183-0.002578j +-0.001176-0.003656j +-0.000912-0.004727j +-0.000397-0.005728j +0.000346-0.006601j +0.001284-0.007292j +0.002368-0.007755j +0.003540-0.007959j +0.004735-0.007886j +0.005885-0.007535j +0.006922-0.006922j +0.007782-0.006078j +0.008412-0.005050j +0.008769-0.003898j +0.008825-0.002691j +0.008572-0.001504j +0.008016-0.000412j +0.007185+0.000510j +0.006123+0.001196j +0.004891+0.001591j +0.003560+0.001657j +0.002212+0.001372j +0.000933+0.000734j +-0.000192-0.000236j +-0.001083-0.001500j +-0.001672-0.002998j +-0.001905-0.004655j +-0.001747-0.006384j +-0.001182-0.008090j +-0.000222-0.009676j +0.001101-0.011045j +0.002732-0.012114j +0.004593-0.012810j +0.006591-0.013081j +0.008621-0.012896j +0.010571-0.012253j +0.012328-0.011175j +0.013785-0.009712j +0.014847-0.007941j +0.015438-0.005962j +0.015507-0.003893j +0.015029-0.001863j +0.014011-0.000011j +0.012494+0.001529j +0.010549+0.002630j +0.008277+0.003179j +0.005809+0.003090j +0.003294+0.002304j +0.000896+0.000795j +-0.001212-0.001423j +-0.002859-0.004299j +-0.003886-0.007744j +-0.004151-0.011630j +-0.003539-0.015799j +-0.001969-0.020066j +0.000601-0.024225j +0.004168-0.028064j +0.008684-0.031367j +0.014056-0.033927j +0.020145-0.035558j +0.026775-0.036101j +0.033735-0.035433j +0.040789-0.033475j +0.047684-0.030197j +0.054164-0.025619j +0.059974-0.019815j +0.064878-0.012907j +0.068665-0.005067j +0.071159+0.003494j +0.072228+0.012531j +0.071791+0.021776j +0.069818+0.030947j +0.066339+0.039761j +0.061435+0.047944j +0.055243+0.055243j +0.047944+0.061435j +0.039761+0.066339j +0.030947+0.069818j +0.021776+0.071791j +0.012531+0.072228j +0.003494+0.071159j +-0.005067+0.068665j +-0.012907+0.064878j +-0.019815+0.059974j +-0.025619+0.054164j +-0.030197+0.047684j +-0.033475+0.040789j +-0.035433+0.033735j +-0.036101+0.026775j +-0.035558+0.020145j +-0.033927+0.014056j +-0.031367+0.008684j +-0.028064+0.004168j +-0.024225+0.000601j +-0.020066-0.001969j +-0.015799-0.003539j +-0.011630-0.004151j +-0.007744-0.003886j +-0.004299-0.002859j +-0.001423-0.001212j +0.000795+0.000896j +0.002304+0.003294j +0.003090+0.005809j +0.003179+0.008277j +0.002630+0.010549j +0.001529+0.012494j +-0.000011+0.014011j +-0.001863+0.015029j +-0.003893+0.015507j +-0.005962+0.015438j +-0.007941+0.014847j +-0.009712+0.013785j +-0.011175+0.012328j +-0.012253+0.010571j +-0.012896+0.008621j +-0.013081+0.006591j +-0.012810+0.004593j +-0.012114+0.002732j +-0.011045+0.001101j +-0.009676-0.000222j +-0.008090-0.001182j +-0.006384-0.001747j +-0.004655-0.001905j +-0.002998-0.001672j +-0.001500-0.001083j +-0.000236-0.000192j +0.000734+0.000933j +0.001372+0.002212j +0.001657+0.003560j +0.001591+0.004891j +0.001196+0.006123j +0.000510+0.007185j +-0.000412+0.008016j +-0.001504+0.008572j +-0.002691+0.008825j +-0.003898+0.008769j +-0.005050+0.008412j +-0.006078+0.007782j +-0.006922+0.006922j +-0.007535+0.005885j +-0.007886+0.004735j +-0.007959+0.003540j +-0.007755+0.002368j +-0.007292+0.001284j +-0.006601+0.000346j +-0.005728-0.000397j +-0.004727-0.000912j +-0.003656-0.001176j +-0.002578-0.001183j +-0.001555-0.000944j +-0.000643-0.000482j +0.000111+0.000168j +0.000668+0.000961j +0.001003+0.001842j +0.001105+0.002757j +0.000975+0.003647j +0.000631+0.004460j +0.000099+0.005147j +-0.000583+0.005669j +-0.001368+0.005997j +-0.002206+0.006114j +-0.003044+0.006019j +-0.003830+0.005718j +-0.004519+0.005234j +-0.005069+0.004597j +-0.005451+0.003848j +-0.005643+0.003030j +-0.005637+0.002193j +-0.005437+0.001385j +-0.005057+0.000651j +-0.004522+0.000031j +-0.003866-0.000442j +-0.003129-0.000744j +-0.002354-0.000864j +-0.001587-0.000799j +-0.000872-0.000559j +-0.000249-0.000163j +0.000250+0.000360j +0.000598+0.000977j +0.000779+0.001647j +0.000787+0.002327j +0.000627+0.002977j +0.000313+0.003558j +-0.000133+0.004034j +-0.000679+0.004379j +-0.001291+0.004574j +-0.001930+0.004610j +-0.002556+0.004485j +-0.003132+0.004210j +-0.003622+0.003803j +-0.004000+0.003289j +-0.004243+0.002700j +-0.004338+0.002071j +-0.004282+0.001440j +-0.004081+0.000842j +-0.003746+0.000311j +-0.003301-0.000122j +-0.002773-0.000436j +-0.002193-0.000615j +-0.001595-0.000652j +-0.001016-0.000547j +-0.000487-0.000311j +-0.000039+0.000039j +0.000304+0.000480j +0.000525+0.000982j +0.000614+0.001515j +0.000568+0.002044j +0.000393+0.002539j +0.000103+0.002969j +-0.000282+0.003309j +-0.000737+0.003540j +-0.001233+0.003649j +-0.001739+0.003631j +-0.002224+0.003488j +-0.002659+0.003231j +-0.003019+0.002876j +-0.003281+0.002444j +-0.003432+0.001963j +-0.003464+0.001460j +-0.003377+0.000966j +-0.003176+0.000508j +-0.002875+0.000113j +-0.002492-0.000197j +-0.002052-0.000407j +-0.001580-0.000506j +-0.001105-0.000490j +-0.000654-0.000362j +-0.000252-0.000134j +0.000077+0.000179j +0.000316+0.000557j +0.000452+0.000976j +0.000481+0.001410j +0.000402+0.001831j +0.000222+0.002215j +-0.000046+0.002538j +-0.000384+0.002782j +-0.000770+0.002933j +-0.001179+0.002984j +-0.001588+0.002930j +-0.001971+0.002778j +-0.002304+0.002537j +-0.002569+0.002223j +-0.002750+0.001853j +-0.002837+0.001452j +-0.002826+0.001042j +-0.002719+0.000648j +-0.002522+0.000292j +-0.002248-0.000006j +-0.001915-0.000229j +-0.001542-0.000365j +-0.001152-0.000408j +-0.000768-0.000359j +-0.000411-0.000220j +-0.000103-0.000003j +0.000139+0.000279j +0.000303+0.000606j +0.000381+0.000959j +0.000369+0.001316j +0.000269+0.001654j +0.000091+0.001954j +-0.000156+0.002198j +-0.000453+0.002371j +-0.000783+0.002464j +-0.001124+0.002473j +-0.001457+0.002397j +-0.001760+0.002241j +-0.002017+0.002017j +-0.002211+0.001736j +-0.002332+0.001418j +-0.002373+0.001080j +-0.002332+0.000743j +-0.002213+0.000426j +-0.002024+0.000148j +-0.001775-0.000076j +-0.001484-0.000233j +-0.001166-0.000316j +-0.000841-0.000322j +-0.000528-0.000250j +-0.000246-0.000107j +-0.000009+0.000097j +0.000168+0.000349j +0.000277+0.000633j +0.000312+0.000931j +0.000272+0.001225j +0.000162+0.001498j +-0.000011+0.001732j +-0.000236+0.001914j +-0.000497+0.002033j +-0.000779+0.002084j +-0.001065+0.002063j +-0.001336+0.001973j +-0.001576+0.001819j +-0.001772+0.001611j +-0.001911+0.001362j +-0.001987+0.001087j +-0.001994+0.000802j +-0.001934+0.000524j +-0.001810+0.000270j +-0.001630+0.000053j +-0.001406-0.000114j +-0.001151-0.000222j +-0.000880-0.000266j +-0.000609-0.000244j +-0.000355-0.000159j +-0.000131-0.000017j +0.000049+0.000172j +0.000176+0.000396j +0.000243+0.000642j +0.000247+0.000893j +0.000190+0.001135j +0.000075+0.001353j +-0.000090+0.001534j +-0.000293+0.001668j +-0.000522+0.001746j +-0.000762+0.001765j +-0.001000+0.001724j +-0.001219+0.001626j +-0.001408+0.001477j +-0.001556+0.001286j +-0.001653+0.001066j +-0.001694+0.000829j +-0.001677+0.000590j +-0.001604+0.000362j +-0.001480+0.000158j +-0.001312-0.000009j +-0.001111-0.000131j +-0.000889-0.000201j +-0.000659-0.000216j +-0.000434-0.000176j +-0.000228-0.000084j +-0.000053+0.000053j +0.000083+0.000226j +0.000170+0.000424j +0.000206+0.000635j +0.000188+0.000846j +0.000120+0.001044j +0.000005+0.001217j +-0.000148+0.001354j +-0.000330+0.001449j +-0.000529+0.001496j +-0.000733+0.001491j +-0.000929+0.001437j +-0.001106+0.001336j +-0.001252+0.001195j +-0.001361+0.001022j +-0.001424+0.000829j +-0.001439+0.000626j +-0.001406+0.000426j +-0.001326+0.000240j +-0.001206+0.000079j +-0.001051-0.000048j +-0.000872-0.000134j +-0.000680-0.000175j +-0.000486-0.000169j +-0.000301-0.000117j +-0.000136-0.000024j +0.000000+0.000105j +0.000099+0.000261j +0.000156+0.000435j +0.000168+0.000614j +0.000136+0.000790j +0.000062+0.000950j +-0.000049+0.001085j +-0.000189+0.001188j +-0.000350+0.001252j +-0.000521+0.001274j +-0.000692+0.001253j +-0.000853+0.001191j +-0.000993+0.001091j +-0.001105+0.000960j +-0.001182+0.000805j +-0.001219+0.000637j +-0.001216+0.000465j +-0.001171+0.000300j +-0.001089+0.000150j +-0.000974+0.000024j +-0.000834-0.000070j +-0.000677-0.000128j +-0.000513-0.000147j +-0.000350-0.000126j +-0.000199-0.000068j +-0.000068+0.000024j +0.000035+0.000143j +0.000105+0.000281j +0.000138+0.000431j +0.000133+0.000582j +0.000091+0.000726j +0.000016+0.000854j +-0.000089+0.000958j +-0.000215+0.001032j +-0.000355+0.001072j +-0.000501+0.001076j +-0.000643+0.001044j +-0.000772+0.000978j +-0.000882+0.000882j +-0.000965+0.000762j +-0.001016+0.000626j +-0.001034+0.000481j +-0.001017+0.000337j +-0.000966+0.000201j +-0.000885+0.000082j +-0.000778-0.000014j +-0.000653-0.000082j +-0.000517-0.000118j +-0.000378-0.000121j +-0.000243-0.000090j +-0.000122-0.000029j +-0.000020+0.000058j +0.000056+0.000165j +0.000103+0.000287j +0.000119+0.000415j +0.000102+0.000540j +0.000055+0.000657j +-0.000019+0.000757j +-0.000115+0.000835j +-0.000227+0.000886j +-0.000347+0.000907j +-0.000469+0.000898j +-0.000585+0.000859j +-0.000688+0.000792j +-0.000772+0.000702j +-0.000831+0.000595j +-0.000863+0.000477j +-0.000866+0.000354j +-0.000839+0.000235j +-0.000786+0.000125j +-0.000708+0.000032j +-0.000611-0.000040j +-0.000501-0.000087j +-0.000385-0.000106j +-0.000268-0.000097j +-0.000159-0.000061j +-0.000063-0.000001j +0.000015+0.000080j +0.000070+0.000175j +0.000099+0.000280j +0.000101+0.000387j +0.000077+0.000490j +0.000028+0.000582j +-0.000042+0.000659j +-0.000128+0.000715j +-0.000225+0.000748j +-0.000327+0.000755j +-0.000428+0.000737j +-0.000521+0.000694j +-0.000601+0.000630j +-0.000663+0.000548j +-0.000703+0.000454j +-0.000720+0.000352j +-0.000712+0.000250j +-0.000681+0.000152j +-0.000627+0.000065j +-0.000555-0.000006j +-0.000469-0.000058j +-0.000374-0.000088j +-0.000275-0.000095j +-0.000180-0.000078j +-0.000092-0.000040j +-0.000017+0.000017j +0.000040+0.000090j +0.000078+0.000173j +0.000093+0.000261j +0.000086+0.000350j +0.000058+0.000432j +0.000010+0.000504j +-0.000054+0.000561j +-0.000130+0.000600j +-0.000213+0.000619j +-0.000297+0.000616j +-0.000379+0.000592j +-0.000452+0.000548j +-0.000513+0.000488j +-0.000557+0.000415j +-0.000582+0.000334j +-0.000588+0.000248j +-0.000573+0.000164j +-0.000538+0.000086j +-0.000487+0.000019j +-0.000422-0.000035j +-0.000347-0.000071j +-0.000266-0.000088j +-0.000185-0.000086j +-0.000107-0.000065j +-0.000038-0.000027j +0.000018+0.000025j +0.000060+0.000089j +0.000083+0.000160j +0.000089+0.000233j +0.000076+0.000304j +0.000046+0.000369j +0.000001+0.000423j +-0.000056+0.000464j +-0.000121+0.000489j +-0.000190+0.000497j +-0.000259+0.000487j +-0.000323+0.000461j +-0.000379+0.000419j +-0.000423+0.000365j +-0.000453+0.000301j +-0.000467+0.000232j +-0.000465+0.000161j +-0.000445+0.000093j +-0.000411+0.000032j +-0.000364-0.000019j +-0.000306-0.000058j +-0.000242-0.000081j +-0.000175-0.000090j +-0.000109-0.000082j +-0.000048-0.000059j +0.000005-0.000023j +0.000047+0.000024j +0.000075+0.000078j +0.000089+0.000137j +0.000088+0.000196j +0.000072+0.000252j +0.000042+0.000302j +0.000002+0.000341j +-0.000048+0.000369j +-0.000102+0.000384j +-0.000158+0.000384j +-0.000213+0.000370j +-0.000262+0.000343j +-0.000304+0.000304j +-0.000335+0.000256j +-0.000354+0.000202j +-0.000359+0.000145j +-0.000351+0.000088j +-0.000330+0.000034j +-0.000298-0.000012j +-0.000255-0.000050j +-0.000206-0.000077j +-0.000152-0.000091j +-0.000098-0.000093j +-0.000046-0.000082j +0.000002-0.000059j +0.000041-0.000027j +0.000071+0.000014j +0.000089+0.000059j +0.000095+0.000106j +0.000090+0.000153j +0.000073+0.000196j +0.000045+0.000232j +0.000010+0.000260j +-0.000031+0.000278j +-0.000075+0.000284j +-0.000120+0.000279j +-0.000162+0.000263j +-0.000199+0.000237j +-0.000228+0.000203j +-0.000249+0.000162j +-0.000259+0.000117j +-0.000259+0.000071j +-0.000248+0.000026j +-0.000227-0.000014j +-0.000197-0.000049j +-0.000161-0.000076j +-0.000120-0.000093j +-0.000077-0.000101j +-0.000034-0.000098j +0.000006-0.000086j +0.000042-0.000064j +0.000070-0.000036j +0.000090-0.000002j +0.000101+0.000034j +0.000102+0.000071j +0.000093+0.000107j +0.000077+0.000139j +0.000052+0.000165j +0.000022+0.000184j +-0.000011+0.000194j +-0.000046+0.000196j +-0.000081+0.000188j +-0.000113+0.000173j +-0.000140+0.000150j +-0.000161+0.000121j +-0.000174+0.000089j +-0.000180+0.000054j +-0.000177+0.000020j +-0.000167-0.000013j +-0.000150-0.000041j +-0.000127-0.000063j +-0.000100-0.000077j +-0.000071-0.000084j +-0.000044-0.000080j +-0.000020-0.000066j +-0.000009-0.000035j diff --git a/gnuradio-examples/python/apps/hf_radio/ssbagc.py b/gnuradio-examples/python/apps/hf_radio/ssbagc.py new file mode 100644 index 00000000..fdf40bc6 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ssbagc.py @@ -0,0 +1,48 @@ +# post detection agc processing +# +# Imagine that the usual gnuradio copyright stuff is right here. +# +# This agc strategy is copied more or less verbatim from +# weaver_isb_am1_usrp3.py by cswiger. +# +# Thanks. +# +# Then modified in a variety of ways. +# +# There doesn't appear to be a way to hook multiple blocks to the +# input port when building a hier block like this. Thus the +# split below. +# +# Basic operation. +# Power is estimated by squaring the input. +# Low pass filter using a 1 pole iir. +# The time constant can be tweaked by changing the taps. +# Currently there is no implementation to change this while operating +# a potentially useful addition. +# The log block turns this into dB +# gain adjusts the agc authority. +# +# M. Revnell 2006-Jan + +from gnuradio import gr, gru + +class agc( gr.hier_block ): + def __init__( self, fg ): + self.split = gr.multiply_const_ff( 1 ) + self.sqr = gr.multiply_ff( ) + self.int0 = gr.iir_filter_ffd( [.004, 0], [0, .999] ) + self.offs = gr.add_const_ff( -30 ) + self.gain = gr.multiply_const_ff( 70 ) + self.log = gr.nlog10_ff( 10, 1 ) + self.agc = gr.divide_ff( ) + + fg.connect( self.split, ( self.agc, 0 ) ) + fg.connect( self.split, ( self.sqr, 0 ) ) + fg.connect( self.split, ( self.sqr, 1 ) ) + fg.connect( self.sqr, self.int0 ) + fg.connect( self.int0, self.log ) + fg.connect( self.log, self.offs ) + fg.connect( self.offs, self.gain ) + fg.connect( self.gain, ( self.agc, 1 ) ) + + gr.hier_block.__init__( self, fg, self.split, self.agc ) diff --git a/gnuradio-examples/python/apps/hf_radio/ssbdemod.py b/gnuradio-examples/python/apps/hf_radio/ssbdemod.py new file mode 100644 index 00000000..c73567b6 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ssbdemod.py @@ -0,0 +1,97 @@ +# This tries to push the hilbert transform for ssb demod back into the +# freq. xlating filter. +# +# The usual gnuradio copyright notice is hereby included by reference. +# +# The starting point for this was weaver_isb_am1_usrp3.py. +# +# The tap coefficients for freq_xlating_fir_filter_ccf were generated +# externally and are read from a file because I didn't want to learn how +# to make fir filters with arbitrary phase response using python numeric +# facilities. +# +# They were generated using Scilab which I am already familiar with. +# M. Revnell Jan 06 + +from gnuradio import gr, gru +from gnuradio import audio +from gnuradio import usrp + +class ssb_demod( gr.hier_block ): + def __init__( self, fg, if_rate, af_rate ): + + self.if_rate = if_rate + self.af_rate = af_rate + self.if_decim = if_rate / af_rate + self.sideband = 1 + + self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) + + self.audio_taps = gr.firdes.low_pass( + 1.0, + self.af_rate, + 3e3, + 600, + gr.firdes.WIN_HAMMING ) + + self.xlate = gr.freq_xlating_fir_filter_ccc( + self.if_decim, + self.xlate_taps, + 0, + self.if_rate ) + + self.split = gr.complex_to_float() + + self.lpf = gr.fir_filter_fff( + 1, self.audio_taps ) + + self.sum = gr.add_ff( ) + self.am_sel = gr.multiply_const_ff( 0 ) + self.sb_sel = gr.multiply_const_ff( 1 ) + self.mixer = gr.add_ff() + self.am_det = gr.complex_to_mag() + + fg.connect( self.xlate, self.split ) + fg.connect( ( self.split,0 ), ( self.sum,0 ) ) + fg.connect( ( self.split,1 ), ( self.sum,1 ) ) + fg.connect( self.sum, self.sb_sel ) + fg.connect( self.xlate, self.am_det ) + fg.connect( self.sb_sel, ( self.mixer, 0 ) ) + fg.connect( self.am_det, self.am_sel ) + fg.connect( self.am_sel, ( self.mixer, 1 ) ) + fg.connect( self.mixer, self.lpf ) + + gr.hier_block.__init__( self, fg, self.xlate, self.lpf ) + + def upper_sb( self ): + self.xlate.set_taps([v.conjugate() for v in self.xlate_taps]) + self.sb_sel.set_k( 1.0 ) + self.am_sel.set_k( 0.0 ) + + def lower_sb( self ): + self.xlate.set_taps(self.xlate_taps) + self.sb_sel.set_k( 1.0 ) + self.am_sel.set_k( 0.0 ) + + def set_am( self ): + taps = gr.firdes.low_pass( 1.0, + self.if_rate, + 5e3, + 2e3, + gr.firdes.WIN_HAMMING ) + self.xlate.set_taps( taps ) + self.sb_sel.set_k( 0.0 ) + self.am_sel.set_k( 1.0 ) + + def set_bw( self, bw ): + self.audio_taps = gr.firdes.low_pass( + 1.0, + self.af_rate, + bw, + 600, + gr.firdes.WIN_HAMMING ) + self.lpf.set_taps( self.audio_taps ) + + def tune( self, freq ): + self.xlate.set_center_freq( freq ) + diff --git a/gnuradio-examples/python/apps/hf_radio/startup.py b/gnuradio-examples/python/apps/hf_radio/startup.py new file mode 100644 index 00000000..093369b5 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/startup.py @@ -0,0 +1 @@ +from radio import * diff --git a/gnuradio-examples/python/apps/hf_radio/ui.py b/gnuradio-examples/python/apps/hf_radio/ui.py new file mode 100755 index 00000000..71b73c12 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ui.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# generated by wxGlade 0.4 on Mon Jan 2 19:02:03 2006 + +import wx + +class ui_frame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: ui_frame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.sizer_1_staticbox = wx.StaticBox(self, -1, "sizer_1") + self.freq_disp = wx.SpinCtrl(self, -1, "", min=0, max=100) + self.spin_e6 = wx.SpinButton(self, -1 ) + self.spin_e5 = wx.SpinButton(self, -1 ) + self.spin_e4 = wx.SpinButton(self, -1 ) + self.spin_e3 = wx.SpinButton(self, -1 ) + self.spin_e2 = wx.SpinButton(self, -1 ) + self.spin_e1 = wx.SpinButton(self, -1 ) + self.spin_e0 = wx.SpinButton(self, -1 ) + self.panel_1 = wx.Panel(self, -1) + self.panel_2 = wx.Panel(self, -1) + self.button_lsb = wx.Button(self, -1, "LSB") + self.button_usb = wx.Button(self, -1, "USB") + self.button_am = wx.Button(self, -1, "AM") + self.label_1 = wx.StaticText(self, -1, "VOLUME") + self.label_2 = wx.StaticText(self, -1, "PGA") + self.agc_level = wx.TextCtrl(self, -1, "") + self.label_6 = wx.StaticText(self, -1, "") + self.volume = wx.SpinCtrl(self, -1, "", min=0, max=100) + self.pga = wx.SpinCtrl(self, -1, "", min=0, max=100) + self.agc_max = wx.TextCtrl(self, -1, "") + self.label_7 = wx.StaticText(self, -1, "") + self.label_4 = wx.StaticText(self, -1, "AGC AUTHORITY") + self.label_5 = wx.StaticText(self, -1, "AGC REF LVL") + self.label_3 = wx.StaticText(self, -1, "BANDWIDTH") + self.label_8 = wx.StaticText(self, -1, "") + self.agc_gain = wx.TextCtrl(self, -1, "") + self.agc_gain_s = wx.SpinButton(self, -1 ) + self.agc_ref = wx.TextCtrl(self, -1, "") + self.agc_ref_s = wx.SpinButton(self, -1 ) + self.bandwidth = wx.TextCtrl(self, -1, "") + self.bw_spin = wx.SpinButton(self, -1 ) + self.label_9 = wx.StaticText(self, -1, "") + self.rssi = wx.Gauge(self, -1, 10, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH) + self.fe_panel = wx.Panel(self, -1) + self.if_panel = wx.Panel(self, -1) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_SPINCTRL, self.tune_evt, self.freq_disp) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e6, self.spin_e6) + self.Bind(wx.EVT_SPIN_UP, self.up_e6, self.spin_e6) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e5, self.spin_e5) + self.Bind(wx.EVT_SPIN_UP, self.up_e5, self.spin_e5) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e4, self.spin_e4) + self.Bind(wx.EVT_SPIN_UP, self.up_e4, self.spin_e4) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e3, self.spin_e3) + self.Bind(wx.EVT_SPIN_UP, self.up_e3, self.spin_e3) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e2, self.spin_e2) + self.Bind(wx.EVT_SPIN_UP, self.up_e2, self.spin_e2) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e1, self.spin_e1) + self.Bind(wx.EVT_SPIN_UP, self.up_e1, self.spin_e1) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e0, self.spin_e0) + self.Bind(wx.EVT_SPIN_UP, self.up_e0, self.spin_e0) + self.Bind(wx.EVT_BUTTON, self.set_lsb, self.button_lsb) + self.Bind(wx.EVT_BUTTON, self.set_usb, self.button_usb) + self.Bind(wx.EVT_BUTTON, self.set_am, self.button_am) + self.Bind(wx.EVT_SPINCTRL, self.event_vol, self.volume) + self.Bind(wx.EVT_SPINCTRL, self.event_pga, self.pga) + self.Bind(wx.EVT_SPIN_DOWN, self.agc_gain_down, self.agc_gain_s) + self.Bind(wx.EVT_SPIN_UP, self.agc_gain_up, self.agc_gain_s) + self.Bind(wx.EVT_SPIN_DOWN, self.agc_ref_down, self.agc_ref_s) + self.Bind(wx.EVT_SPIN_UP, self.agc_ref_up, self.agc_ref_s) + self.Bind(wx.EVT_SPIN_DOWN, self.bw_down, self.bw_spin) + self.Bind(wx.EVT_SPIN_UP, self.bw_up, self.bw_spin) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: ui_frame.__set_properties + self.SetTitle("frame_1") + self.freq_disp.SetFont(wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, "")) + self.rssi.SetMinSize((315, 10)) + self.rssi.SetForegroundColour(wx.Colour(255, 0, 0)) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: ui_frame.__do_layout + sizer_1 = wx.StaticBoxSizer(self.sizer_1_staticbox, wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_4 = wx.GridSizer(2, 4, 0, 0) + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_7 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6 = wx.BoxSizer(wx.HORIZONTAL) + grid_sizer_3 = wx.GridSizer(2, 4, 0, 0) + sizer_3 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1 = wx.GridSizer(2, 3, 0, 0) + grid_sizer_2 = wx.GridSizer(1, 7, 0, 0) + sizer_3.Add(self.freq_disp, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e4, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e3, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e2, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e1, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e0, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_lsb, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_usb, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_am, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add(grid_sizer_1, 1, wx.EXPAND, 0) + sizer_2.Add(sizer_3, 1, wx.EXPAND, 0) + grid_sizer_3.Add(self.label_1, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.agc_level, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.label_6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.volume, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.pga, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.agc_max, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.label_7, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(grid_sizer_3, 1, wx.EXPAND, 0) + grid_sizer_4.Add(self.label_4, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(self.label_5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(self.label_3, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(self.label_8, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.agc_gain, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.agc_gain_s, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(sizer_6, 1, wx.EXPAND, 0) + sizer_7.Add(self.agc_ref, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.agc_ref_s, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(sizer_7, 1, wx.EXPAND, 0) + sizer_5.Add(self.bandwidth, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.bw_spin, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(sizer_5, 1, wx.EXPAND, 0) + grid_sizer_4.Add(self.label_9, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(grid_sizer_4, 1, wx.EXPAND, 0) + sizer_4.Add(self.rssi, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) + sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) + sizer_1.Add(self.fe_panel, 1, wx.EXPAND, 0) + sizer_1.Add(self.if_panel, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + sizer_1.SetSizeHints(self) + self.Layout() + # end wxGlade + + def down_e6(self, event): # wxGlade: ui_frame. + print "Event handler `down_e6' not implemented" + event.Skip() + + def up_e6(self, event): # wxGlade: ui_frame. + print "Event handler `up_e6' not implemented" + event.Skip() + + def down_e5(self, event): # wxGlade: ui_frame. + print "Event handler `down_e5' not implemented" + event.Skip() + + def up_e5(self, event): # wxGlade: ui_frame. + print "Event handler `up_e5' not implemented" + event.Skip() + + def down_e4(self, event): # wxGlade: ui_frame. + print "Event handler `down_e4' not implemented" + event.Skip() + + def up_e4(self, event): # wxGlade: ui_frame. + print "Event handler `up_e4' not implemented" + event.Skip() + + def down_e3(self, event): # wxGlade: ui_frame. + print "Event handler `down_e3' not implemented" + event.Skip() + + def up_e3(self, event): # wxGlade: ui_frame. + print "Event handler `up_e3' not implemented" + event.Skip() + + def down_e2(self, event): # wxGlade: ui_frame. + print "Event handler `down_e2' not implemented" + event.Skip() + + def up_e2(self, event): # wxGlade: ui_frame. + print "Event handler `up_e2' not implemented" + event.Skip() + + def down_e1(self, event): # wxGlade: ui_frame. + print "Event handler `down_e1' not implemented" + event.Skip() + + def up_e1(self, event): # wxGlade: ui_frame. + print "Event handler `up_e1' not implemented" + event.Skip() + + def down_e0(self, event): # wxGlade: ui_frame. + print "Event handler `down_e0' not implemented" + event.Skip() + + def up_e0(self, event): # wxGlade: ui_frame. + print "Event handler `up_e0' not implemented" + event.Skip() + + def event_vol(self, event): # wxGlade: ui_frame. + print "Event handler `event_vol' not implemented" + event.Skip() + + def event_pga(self, event): # wxGlade: ui_frame. + print "Event handler `event_pga' not implemented" + event.Skip() + + def set_lsb(self, event): # wxGlade: ui_frame. + print "Event handler `set_lsb' not implemented" + event.Skip() + + def set_usb(self, event): # wxGlade: ui_frame. + print "Event handler `set_usb' not implemented" + event.Skip() + + def set_am(self, event): # wxGlade: ui_frame. + print "Event handler `set_am' not implemented" + event.Skip() + + def set_bw(self, event): # wxGlade: ui_frame. + print "Event handler `set_bw' not implemented" + event.Skip() + + def tune_evt(self, event): # wxGlade: ui_frame. + print "Event handler `tune_evt' not implemented" + event.Skip() + + def bw_down(self, event): # wxGlade: ui_frame. + print "Event handler `bw_down' not implemented" + event.Skip() + + def bw_up(self, event): # wxGlade: ui_frame. + print "Event handler `bw_up' not implemented" + event.Skip() + + def agc_gain_down(self, event): # wxGlade: ui_frame. + print "Event handler `agc_gain_down' not implemented" + event.Skip() + + def agc_gain_up(self, event): # wxGlade: ui_frame. + print "Event handler `agc_gain_up' not implemented" + event.Skip() + + def agc_ref_down(self, event): # wxGlade: ui_frame. + print "Event handler `agc_ref_down' not implemented" + event.Skip() + + def agc_ref_up(self, event): # wxGlade: ui_frame. + print "Event handler `agc_ref_up' not implemented" + event.Skip() + +# end of class ui_frame + + +class RadioFrame(wx.Frame): + def __init__(self, *args, **kwds): + # content of this block not found: did you rename this class? + pass + + def __set_properties(self): + # content of this block not found: did you rename this class? + pass + + def __do_layout(self): + # content of this block not found: did you rename this class? + pass + +# end of class RadioFrame + + +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # content of this block not found: did you rename this class? + pass + + def __set_properties(self): + # content of this block not found: did you rename this class? + pass + + def __do_layout(self): + # content of this block not found: did you rename this class? + pass + +# end of class MyFrame + + diff --git a/gnuradio-examples/python/audio/Makefile.am b/gnuradio-examples/python/audio/Makefile.am new file mode 100644 index 00000000..27cea62a --- /dev/null +++ b/gnuradio-examples/python/audio/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + audio_copy.py \ + audio_play.py \ + audio_to_file.py \ + dial_tone.py \ + mono_tone.py \ + multi_tone.py \ + spectrum_inversion.py \ + test_resampler.py + + diff --git a/gnuradio-examples/python/audio/audio_copy.py b/gnuradio-examples/python/audio/audio_copy.py new file mode 100755 index 00000000..56fa836d --- /dev/null +++ b/gnuradio-examples/python/audio/audio_copy.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_input) + dst = audio.sink (sample_rate, options.audio_output) + + # Determine the maximum number of outputs on the source and + # maximum number of inputs on the sink, then connect together + # the most channels we can without overlap + nchan = min (src.output_signature().max_streams(), + dst.input_signature().max_streams()) + + for i in range (nchan): + self.connect ((src, i), (dst, i)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-examples/python/audio/audio_play.py b/gnuradio-examples/python/audio/audio_play.py new file mode 100755 index 00000000..e70b0f94 --- /dev/null +++ b/gnuradio-examples/python/audio/audio_play.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-F", "--filename", type="string", default="audio.dat", + help="read input from FILE") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option("-R", "--repeat", action="store_true", default=False) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = gr.file_source (gr.sizeof_float, options.filename, options.repeat) + dst = audio.sink (sample_rate, options.audio_output) + self.connect(src, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/audio_to_file.py b/gnuradio-examples/python/audio/audio_to_file.py new file mode 100755 index 00000000..74e1ea7a --- /dev/null +++ b/gnuradio-examples/python/audio/audio_to_file.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option("-N", "--nsamples", type="eng_float", default=None, + help="number of samples to collect [default=+inf]") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + filename = args[0] + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_input) + dst = gr.file_sink (gr.sizeof_float, filename) + + if options.nsamples is None: + self.connect((src, 0), dst) + else: + head = gr.head(gr.sizeof_float, int(options.nsamples)) + self.connect((src, 0), head, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/dial_squelch.py b/gnuradio-examples/python/audio/dial_squelch.py new file mode 100755 index 00000000..d947e586 --- /dev/null +++ b/gnuradio-examples/python/audio/dial_squelch.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, audio, eng_option +from gnuradio.eng_option import eng_option +from math import pi, cos +from optparse import OptionParser + +""" +This script generates a standard dial tone and then applies a sinusoidal +envelope to vary it's loudness. The audio is then passed through the +power squelch block before it gets sent to the sound card. By varying +the command line parameters, one can see the effect of differing +amounts of power averaging, threshold, and attack/decay ramping. +""" + +class app_flow_graph(gr.flow_graph): + def __init__(self, options, args): + gr.flow_graph.__init__(self) + + # Create dial tone by adding two sine waves + SRC1 = gr.sig_source_f(options.rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0) + SRC2 = gr.sig_source_f(options.rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0) + ADD = gr.add_ff() + + # Convert to vector stream (and back) to apply raised cosine envelope + # You could also do this with a vector_source_f block that repeats. + S2V = gr.stream_to_vector(gr.sizeof_float, options.rate) + ENV = [0.5-cos(2*pi*x/options.rate)/2 for x in range(options.rate)] + MLT = gr.multiply_const_vff(ENV) + V2S = gr.vector_to_stream(gr.sizeof_float, options.rate) + + # Run through power squelch with user supplied or default options + # Zero output when squelch is invoked + SQL = gr.pwr_squelch_ff(options.threshold, options.alpha, options.ramp, False) + DST = audio.sink(options.rate) + + # Solder it all together + self.connect(SRC1, (ADD, 0)) + self.connect(SRC2, (ADD, 1)) + self.connect(ADD, S2V, MLT, V2S, SQL, DST) + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-r", "--rate", type="int", default=8000, help="set audio output sample rate to RATE", metavar="RATE") + parser.add_option("-t", "--threshold", type="eng_float", default=-10.0, help="set power squelch to DB", metavar="DB") + parser.add_option("-a", "--alpha", type="eng_float", default=None, help="set alpha to ALPHA", metavar="ALPHA") + parser.add_option("-m", "--ramp", type="int", default=None, help="set attack/decay ramp to SAMPLES", metavar="SAMPLES") + (options, args) = parser.parse_args() + + if options.alpha == None: + options.alpha = 50.0/options.rate + + if options.ramp == None: + options.ramp = options.rate/50 # ~ 20 ms + + print "Using audio rate of", options.rate + print "Using threshold of", options.threshold, "db" + print "Using alpha of", options.alpha + print "Using ramp of", options.ramp, "samples" + + fg = app_flow_graph(options, args) + + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == "__main__": + main() diff --git a/gnuradio-examples/python/audio/dial_tone.py b/gnuradio-examples/python/audio/dial_tone.py new file mode 100755 index 00000000..3ce84eb5 --- /dev/null +++ b/gnuradio-examples/python/audio/dial_tone.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl) + src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl) + dst = audio.sink (sample_rate, options.audio_output) + self.connect (src0, (dst, 0)) + self.connect (src1, (dst, 1)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/dialtone_v.py b/gnuradio-examples/python/audio/dialtone_v.py new file mode 100755 index 00000000..e704414a --- /dev/null +++ b/gnuradio-examples/python/audio/dialtone_v.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, audio +from math import pi, sin + +""" +This test script demonstrates the use of element-wise vector processing +vs. stream processing. The example is artificial in that the stream +version in dial_tone.py is the normal way to do it; in addition, the +envelope processing here is just for demo purposes and isn't needed. +""" + +# For testing different buffer sizes +rate = 48000 + +fg = gr.flow_graph() + +# Two streams of floats +a = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0); +b = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0); + +# Turn them into vectors of length 'size' +av = gr.stream_to_vector(gr.sizeof_float, rate) +bv = gr.stream_to_vector(gr.sizeof_float, rate) + +# Make a vector adder for float vectors +adder = gr.add_vff(rate) + +# Make a 1 Hz sine envelope +envelope = [sin(2*pi*x/rate)*0.5 for x in range(rate)] +multiplier = gr.multiply_const_vff(envelope) + +# Make an offset adder +offset = gr.add_const_vff((0.5,)*rate) + +# Turn the vector back into a stream of floats +result = gr.vector_to_stream(gr.sizeof_float, rate) + +# Play it +sink = audio.sink(rate) + +fg.connect(a, av) +fg.connect(b, bv) +fg.connect(av, (adder, 0)) +fg.connect(bv, (adder, 1)) +fg.connect(adder, multiplier, offset, result, sink) + +try: + fg.run() +except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/mono_tone.py b/gnuradio-examples/python/audio/mono_tone.py new file mode 100755 index 00000000..84c3b542 --- /dev/null +++ b/gnuradio-examples/python/audio/mono_tone.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +#import os +#print os.getpid() +#raw_input('Attach gdb and press Enter: ') + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option("-D", "--dont-block", action="store_false", default=True, + dest="ok_to_block") + + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 650, ampl) + + dst = audio.sink (sample_rate, + options.audio_output, + options.ok_to_block) + + self.connect (src0, (dst, 0)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/multi_tone.py b/gnuradio-examples/python/audio/multi_tone.py new file mode 100755 index 00000000..c6f83050 --- /dev/null +++ b/gnuradio-examples/python/audio/multi_tone.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +#import os +#print os.getpid() +#raw_input('Attach gdb and press Enter: ') + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option ("-m", "--max-channels", type="int", default="16", + help="set maximum channels to use") + parser.add_option("-D", "--dont-block", action="store_false", default=True, + dest="ok_to_block") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + limit_channels = options.max_channels + + ampl = 0.1 + + # With a tip of the hat to Harry Partch, may he R.I.P. + # See "Genesis of a Music". He was into some very wild tunings... + base = 392 + ratios = { 1 : 1.0, + 3 : 3.0/2, + 5 : 5.0/4, + 7 : 7.0/4, + 9 : 9.0/8, + 11 : 11.0/8 } + + # progression = (1, 5, 3, 7) + # progression = (1, 9, 3, 7) + # progression = (3, 7, 9, 11) + # progression = (7, 11, 1, 5) + progression = (7, 11, 1, 5, 9) + + dst = audio.sink (sample_rate, + options.audio_output, + options.ok_to_block) + + max_chan = dst.input_signature().max_streams() + if (max_chan == -1) or (max_chan > limit_channels): + max_chan = limit_channels + + for i in range (max_chan): + quo, rem = divmod (i, len (progression)) + freq = base * ratios[progression[rem]] * (quo + 1) + src = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, freq, ampl) + self.connect (src, (dst, i)) + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/spectrum_inversion.py b/gnuradio-examples/python/audio/spectrum_inversion.py new file mode 100755 index 00000000..9bb87aa4 --- /dev/null +++ b/gnuradio-examples/python/audio/spectrum_inversion.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# Gang - Here's a simple script that demonstrates spectrum inversion +# using the multiply by [1,-1] method (mixing with Nyquist frequency). +# Requires nothing but a sound card, and sounds just like listening +# to a SSB signal on the wrong sideband. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=8000, + help="set sample rate to RATE (8000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_input) + dst = audio.sink (sample_rate, options.audio_output) + + vec1 = [1, -1] + vsource = gr.vector_source_f(vec1, True) + multiply = gr.multiply_ff() + + self.connect(src, (multiply, 0)) + self.connect(vsource, (multiply, 1)) + self.connect(multiply, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/test_resampler.py b/gnuradio-examples/python/audio/test_resampler.py new file mode 100755 index 00000000..6c9e5a76 --- /dev/null +++ b/gnuradio-examples/python/audio/test_resampler.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-i", "--input-rate", type="eng_float", default=8000, + help="set input sample rate to RATE (%default)") + parser.add_option("-o", "--output-rate", type="eng_float", default=48000, + help="set output sample rate to RATE (%default)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + input_rate = int(options.input_rate) + output_rate = int(options.output_rate) + + interp = gru.lcm(input_rate, output_rate) / input_rate + decim = gru.lcm(input_rate, output_rate) / output_rate + + print "interp =", interp + print "decim =", decim + + ampl = 0.1 + src0 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 650, ampl) + rr = blks.rational_resampler_fff(self, interp, decim) + dst = audio.sink (output_rate, options.audio_output) + self.connect (src0, rr, (dst, 0)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/digital_voice/Makefile.am b/gnuradio-examples/python/digital_voice/Makefile.am new file mode 100644 index 00000000..ed88c22d --- /dev/null +++ b/gnuradio-examples/python/digital_voice/Makefile.am @@ -0,0 +1,23 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + encdec.py diff --git a/gnuradio-examples/python/digital_voice/encdec.py b/gnuradio-examples/python/digital_voice/encdec.py new file mode 100755 index 00000000..11936a4b --- /dev/null +++ b/gnuradio-examples/python/digital_voice/encdec.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, blks +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = 8000 + src = audio.source(sample_rate, options.audio_input) + tx = blks.digital_voice_tx(self) + if_gain = gr.multiply_const_cc(10000) + # channel simulator here... + rx = blks.digital_voice_rx(self) + dst = audio.sink(sample_rate, options.audio_output) + + self.connect(src, tx, if_gain, rx, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/Makefile.am b/gnuradio-examples/python/gmsk2/Makefile.am new file mode 100644 index 00000000..cf2ffb39 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/Makefile.am @@ -0,0 +1,38 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + benchmark_gmsk_rx.py \ + benchmark_gmsk_tx.py \ + benchmark_mpsk_rx.py \ + benchmark_mpsk_tx.py \ + fusb_options.py \ + gen_whitener.py \ + gmsk_test.py \ + pick_bitrate.py \ + receive_path.py \ + transmit_path.py \ + tunnel_ip_null_mac.py + + + + + diff --git a/gnuradio-examples/python/gmsk2/README b/gnuradio-examples/python/gmsk2/README new file mode 100644 index 00000000..b3c343e4 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/README @@ -0,0 +1,81 @@ +Quick overview of what's here: + +* gmsk_test.py: stand-alone program that exercises the GMSK packet tx +and rx code. The two halves are connected with a simulated noisy +channel. It's easy to add extra instrumentation to log various internal +states. We used a variant of this code to get this working in the +first place. + +* benchmark_gmsk_tx.py: generates packets of the size you +specify and sends them across the air using the USRP. Known to work +well using the USRP with the Flex 400 transceiver daughterboard. +You can specify the bitrate to use with the -r command line +parameter. The default is 500k. Some machines will do 1M or more. + +* benchmark_gmsk_rx.py: the receiver half of benchmark_gmsk_tx.py. +Command line arguments are pretty much the same as tx. Works well +with a USRP and Flex 400 transceiver daughterboard. Will also work +with TVRX daugherboard, but you'll need to fiddle with the gain. See +below. Prints a summary of each packet received and keeps a running +total of packets received, and how many of them were error free. +There are two levels of error reporting going on. If the access code +(PN code) and header of a packet were properly detected, then you'll +get an output line. If the CRC32 of the payload was correct you get +"ok = True", else "ok = False". The "pktno" is extracted from the +received packet. If there are skipped numbers, you're missing some +packets. Be sure you've got a suitable antenna connected to the TX/RX +port on each board. A "70 cm" / 420 MHz antenna for a ham +handi-talkie works great. These are available at ham radio supplies, +etc. The boards need to be at least 3m apart. You can also try +experimenting with the rx gain (-g command line option). + +Generally speaking, I start the rx first on one machine, and then fire +up the tx on the other machine. The tx also supports a discontinous +transmission mode where it sends bursts of 5 packets and then waits 1 +second. This is useful for ensuring that all the receiver control +loops lock up fast enough. + +* tunnel.py: This program provides a framework for building your own +MACs. It creates a "TAP" interface in the kernel, typically gr0, +and sends and receives ethernet frames through it. See +/usr/src/linux/Documentation/networking/tuntap.txt and/or Google for +"universal tun tap". The Linux 2.6 kernel includes the tun module, you +don't have to build it. You may have to "modprobe tun" if it's not +loaded by default. If /dev/net/tun doesn't exist, try "modprobe tun". + +To run this program you'll need to be root or running with the +appropriate capability to open the tun interface. You'll need to fire +up two copies on different machines. Once each is running you'll need +to ifconfig the gr0 interface to set the IP address. + +This will allow two machines to talk, but anything beyond the two +machines depends on your networking setup. Left as an exercise... + +On machine A: + + $ su + # ./tunnel.py --freq 423.0M --bitrate 500k + # # in another window on A, also as root... + # ifconfig gr0 10.10.10.1 + + +On machine B: + + $ su + # ./tunnel.py --freq 423.0M --bitrate 500k + # # in another window on B, also as root... + # ifconfig gr0 10.10.10.2 + +Now, on machine A you shold be able to ping machine B: + + $ ping 10.10.10.2 + +and you should see some output for each packet in the +tunnel.py window if you used the -v option. + +Likewise, on machine B: + + $ ping 10.10.10.1 + +This now uses a carrier sense MAC, so you should be able to ssh +between the machines, web browse, etc. diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py b/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py new file mode 100755 index 00000000..d1f70c54 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import struct + +# from current dir +from receive_path import receive_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %r pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-g", "--rx-gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + demod_kwargs = { } # placeholder + + # build the graph + fg = my_graph(blks.gmsk2_demod, + options.rx_subdev_spec, options.bitrate, + options.decim, options.spb, rx_callback, + options, demod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) + print "spb: %3d" % (fg.rxpath.spb(),) + print "decim: %3d" % (fg.rxpath.decim(),) + + ok = fg.rxpath.set_freq(options.freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + fg.rxpath.set_gain(options.rx_gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py b/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py new file mode 100755 index 00000000..2994003a --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import time +import struct +import sys + +# from current dir +from transmit_path import transmit_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("", "--bt", type="float", default=0.3, + help="set bandwidth-time product [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=100.0, + help="transmitter gain [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + pkt_size = int(options.size) + + mod_kwargs = { + 'bt' : options.bt, + } + + # build the graph + fg = my_graph(blks.gmsk2_mod, options.tx_subdev_spec, + options.bitrate, options.interp, options.spb, options.gain, + options, mod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + ok = fg.txpath.set_freq(options.freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + fg.txpath.set_auto_tr(False) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py b/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py new file mode 100755 index 00000000..ad6218b6 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import struct + +# from current dir +from bpsk import bpsk_demod +from dbpsk import dbpsk_demod +from dqpsk import dqpsk_demod +from receive_path import receive_path +import fusb_options + +if 1: + import os + print os.getpid() + raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %r pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + parser.add_option("-m", "--modulation", type="string", default='dbpsk', + help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]") + parser.add_option("", "--excess-bw", type="float", default=0.3, + help="set RRC excess bandwith factor [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("","--log", action="store_true", default=False, + help="enable diagnostic logging") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + demod_kwargs = { + 'excess_bw' : options.excess_bw, + } + + #FIXME: Needs to be worked in to overall structure; this will be fixed + # once static class definitions for modulations are defined + if(options.modulation=='bpsk'): + modulation=bpsk_demod + elif(options.modulation=='dbpsk'): + modulation=dbpsk_demod + else: + modulation=dqpsk_demod + + # build the graph + fg = my_graph(modulation, + options.rx_subdev_spec, options.bitrate, + options.decim, options.spb, + rx_callback, options, demod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) + print "spb: %3d" % (fg.rxpath.spb(),) + print "decim: %3d" % (fg.rxpath.decim(),) + + ok = fg.rxpath.set_freq(options.freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + fg.rxpath.set_gain(options.gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py b/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py new file mode 100755 index 00000000..7b37da7f --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# +# Copyright 2005, 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys + +# from current dir +from bpsk import bpsk_mod +from dbpsk import dbpsk_mod +from dqpsk import dqpsk_mod +from transmit_path import transmit_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("-m", "--modulation", type="string", default='dbpsk', + help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]") + parser.add_option("", "--excess-bw", type="float", default=0.3, + help="set RRC excess bandwith factor [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=100.0, + help="transmitter gain [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + pkt_size = int(options.size) + + mod_kwargs = { + 'excess_bw' : options.excess_bw, + } + + #FIXME: rework when static class defintions are ready for the modulation types + if(options.modulation=='bpsk'): + modulation=bpsk_mod + elif( options.modulation=='dbpsk'): + modulation=dbpsk_mod + else: + modulation=dqpsk_mod + + # build the graph + fg = my_graph(modulation, + options.tx_subdev_spec, options.bitrate, options.interp, + options.spb, options.gain, + options, mod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + ok = fg.txpath.set_freq(options.freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + fg.txpath.set_auto_tr(False) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/bpsk.py b/gnuradio-examples/python/gmsk2/bpsk.py new file mode 100644 index 00000000..14cea7b1 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/bpsk.py @@ -0,0 +1,256 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +BPSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# mPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class bpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, excess_bw): + """ + Hierarchical block for RRC-filtered BPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 11 * spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + fg.connect(self.bytes2chunks, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +class bpsk_demod__coherent_detection_of_psk(gr.hier_block): + def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered BPSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.slicer, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +bpsk_demod = bpsk_demod__coherent_detection_of_psk + diff --git a/gnuradio-examples/python/gmsk2/dbpsk.py b/gnuradio-examples/python/gmsk2/dbpsk.py new file mode 100644 index 00000000..213e90c6 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/dbpsk.py @@ -0,0 +1,282 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +differential BPSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# BPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class dbpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, excess_bw): + """ + Hierarchical block for RRC-filtered QPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 11 * spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + self.bits_per_symbol = bits_per_symbol + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + if True: + self.gray_coder = gr.map_bb(binary_to_gray[arity]) + else: + self.gray_coder = None + + self.diffenc = gr.diff_encoder_bb(arity) + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + if self.gray_coder: + fg.connect(self.bytes2chunks, self.gray_coder) + t = self.gray_coder + else: + t = self.bytes2chunks + + fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.gray_coder, + gr.file_sink(gr.sizeof_char, "graycoder.dat")) + fg.connect(self.diffenc, + gr.file_sink(gr.sizeof_char, "diffenc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + + +class dbpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered BPSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1, 1000) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.diffdec = gr.diff_phasor_cc() + #self.diffdec = gr.diff_decoder_bb(arity) + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.diffdec, self.slicer, self.gray_decoder, self.unpack) + #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + # self.slicer, self.diffdec, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.diffdec, + gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) + #fg.connect(self.diffdec, + # gr.file_sink(gr.sizeof_char, "diffdec.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +dbpsk_demod = dbpsk_demod__coherent_detection_of_differentially_encoded_psk + diff --git a/gnuradio-examples/python/gmsk2/dqpsk.py b/gnuradio-examples/python/gmsk2/dqpsk.py new file mode 100644 index 00000000..490dc6f7 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/dqpsk.py @@ -0,0 +1,280 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +differential QPSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# QPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class dqpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, excess_bw): + """ + Hierarchical block for RRC-filtered QPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 11 * spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + if True: + self.gray_coder = gr.map_bb(binary_to_gray[arity]) + else: + self.gray_coder = None + + self.diffenc = gr.diff_encoder_bb(arity) + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + if self.gray_coder: + fg.connect(self.bytes2chunks, self.gray_coder) + t = self.gray_coder + else: + t = self.bytes2chunks + + fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.gray_coder, + gr.file_sink(gr.sizeof_char, "graycoder.dat")) + fg.connect(self.diffenc, + gr.file_sink(gr.sizeof_char, "diffenc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 2 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + + +class dqpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered QPSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + costas_order = 4 + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.diffdec = gr.diff_phasor_cc() + #self.diffdec = gr.diff_decoder_bb(arity) + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.diffdec, self.slicer, self.gray_decoder, self.unpack) + #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + # self.slicer, self.diffdec, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.diffdec, + gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) + #fg.connect(self.diffdec, + # gr.file_sink(gr.sizeof_char, "diffdec.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 2 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +dqpsk_demod = dqpsk_demod__coherent_detection_of_differentially_encoded_psk + diff --git a/gnuradio-examples/python/gmsk2/fusb_options.py b/gnuradio-examples/python/gmsk2/fusb_options.py new file mode 100644 index 00000000..0d04e30c --- /dev/null +++ b/gnuradio-examples/python/gmsk2/fusb_options.py @@ -0,0 +1,31 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def add_options(parser): + """ + Add Fast USB specifc options to command line parser. + + @param parser: instance of OptionParser + """ + parser.add_option("-B", "--fusb-block-size", type="int", default=0, + help="specify fast usb block size [default=%default]") + parser.add_option("-N", "--fusb-nblocks", type="int", default=0, + help="specify number of fast usb blocks [default=%default]") diff --git a/gnuradio-examples/python/gmsk2/gen_whitener.py b/gnuradio-examples/python/gmsk2/gen_whitener.py new file mode 100755 index 00000000..93aea2b8 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/gen_whitener.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + src = gr.lfsr_32k_source_s() + head = gr.head(gr.sizeof_short, 2048) + self.dst = gr.vector_sink_s() + self.connect(src, head, self.dst) + +if __name__ == '__main__': + try: + fg = my_graph() + fg.run() + f = sys.stdout + i = 0 + for s in fg.dst.data(): + f.write("%3d, " % (s & 0xff,)) + f.write("%3d, " % ((s >> 8) & 0xff,)) + i = i+2 + if i % 16 == 0: + f.write('\n') + + except KeyboardInterrupt: + pass + + diff --git a/gnuradio-examples/python/gmsk2/gmsk_test.py b/gnuradio-examples/python/gmsk2/gmsk_test.py new file mode 100755 index 00000000..7ae69a0a --- /dev/null +++ b/gnuradio-examples/python/gmsk2/gmsk_test.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from gnuradio import gr, blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import random +import struct + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, rx_callback, spb, bt, SNR, freq_error): + gr.flow_graph.__init__(self) + + fg = self + + # Tuning Parameters + gain_mu = 0.002*spb + omega = spb*(1+freq_error) + + # transmitter + self.packet_transmitter = blks.gmsk2_mod_pkts(fg, spb=spb, bt=bt) + + # add some noise + add = gr.add_cc() + noise = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0)) + + # channel filter + rx_filt_taps = gr.firdes.low_pass(1,spb,0.8,0.1,gr.firdes.WIN_HANN) + rx_filt = gr.fir_filter_ccf(1,rx_filt_taps) + + # receiver + self.packet_receiver = blks.gmsk2_demod_pkts(fg, callback=rx_callback, + spb=spb, gain_mu=gain_mu, + freq_error=freq_error, omega=omega) + + fg.connect (self.packet_transmitter, (add,0)) + fg.connect (noise, (add,1)) + fg.connect(add, rx_filt, self.packet_receiver) + + +class stats(object): + def __init__(self): + self.npkts = 0 + self.nright = 0 + +def main(): + st = stats() + + def send_pkt(payload='', eof=False): + fg.packet_transmitter.send_pkt(payload, eof) + + def rx_callback(ok, payload): + st.npkts += 1 + if ok: + st.nright += 1 + if len(payload) <= 16: + print "ok = %5r payload = '%s' %d/%d" % (ok, payload, st.nright, st.npkts) + else: + (pktno,) = struct.unpack('!H', payload[0:2]) + print "ok = %5r pktno = %4d len(payload) = %4d %d/%d" % (ok, pktno, len(payload), + st.nright, st.npkts) + + + parser = OptionParser (option_class=eng_option) + parser.add_option("-M", "--megabytes", type="eng_float", default=1, + help="set megabytes to transmit [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("","--spb", type=int, default=4, + help="set samples per baud to SPB [default=%default]") + parser.add_option("", "--bt", type="eng_float", default=0.3, + help="set bandwidth time product for Gaussian filter [default=%default]") + parser.add_option("", "--snr", type="eng_float", default=20, + help="set SNR in dB for simulation [default=%default]") + parser.add_option("", "--freq-error", type="eng_float", default=0, + help="set frequency error for simulation [default=%default]") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + pkt_size = int(options.size) + + fg = my_graph(rx_callback, options.spb, options.bt, options.snr, options.freq_error) + fg.start() + + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + send_pkt('Hello World') + + # generate and send packets + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + pktno += 1 + + send_pkt('Goodbye World') + send_pkt(eof=True) # tell modulator we're not sending any more pkts + + fg.wait() + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/mpsk_test.py b/gnuradio-examples/python/gmsk2/mpsk_test.py new file mode 100755 index 00000000..1f257d9c --- /dev/null +++ b/gnuradio-examples/python/gmsk2/mpsk_test.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python + +from gnuradio import gr, blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import random +import struct +from mpsk_pkt import * +import cmath + +class my_graph(gr.flow_graph): + + def __init__(self, rx_callback, spb, excess_bw, SNR, freq_error, arity): + gr.flow_graph.__init__(self) + + fg = self + + # Tuning Parameters + gain_mu = 0.05/spb + + # transmitter + self.packet_transmitter = \ + mpsk_mod_pkts(fg, spb=spb, excess_bw=excess_bw, diff=True, arity=arity) + + # ---------------------------------------------------------------- + # Channel model + # ---------------------------------------------------------------- + + awgn = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0)) + add = gr.add_cc() # add some noise + fg.connect(awgn, (add,1)) + radians = 17*pi/180 + phase_rotate = gr.multiply_const_cc(cmath.exp(radians * 1j)) + + # ---------------------------------------------------------------- + + # channel filter + rx_filt_taps = gr.firdes.low_pass(1,spb,0.8,0.1,gr.firdes.WIN_HANN) + #rx_filt_taps = (1,) + rx_filt = gr.fir_filter_ccf(1,rx_filt_taps) + + # receiver + self.packet_receiver = \ + mpsk_demod_pkts(fg, callback=rx_callback, + excess_bw=excess_bw, arity=arity, diff=True, + costas_alpha=.005, gain_mu=gain_mu, spb=spb) + + fg.connect (self.packet_transmitter, (add,0)) + fg.connect(add, phase_rotate, rx_filt, self.packet_receiver) + + +class stats(object): + def __init__(self): + self.npkts = 0 + self.nright = 0 + +def main(): + st = stats() + + def send_pkt(payload='', eof=False): + fg.packet_transmitter.send_pkt(payload, eof) + + def rx_callback(ok, payload): + st.npkts += 1 + if ok: + st.nright += 1 + if len(payload) <= 16: + print "ok = %5r payload = '%s' %d/%d" % (ok, payload, st.nright, st.npkts) + else: + (pktno,) = struct.unpack('!H', payload[0:2]) + print "ok = %5r pktno = %4d len(payload) = %4d %d/%d" % (ok, pktno, len(payload), + st.nright, st.npkts) + + + parser = OptionParser (option_class=eng_option) + parser.add_option("-M", "--megabytes", type="eng_float", default=1, + help="set megabytes to transmit [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("","--spb", type=int, default=4, + help="set samples per baud to SPB [default=%default]") + parser.add_option("", "--excess-bw", type="eng_float", default=0.4, + help="set excess bandwidth for RRC filter [default=%default]") + parser.add_option("", "--snr", type="eng_float", default=40, + help="set SNR in dB for simulation [default=%default]") + parser.add_option("", "--m-arity", type=int, default=4, + help="PSK arity [default=%default]") + parser.add_option("", "--freq-error", type="eng_float", default=0, + help="set frequency error for simulation [default=%default]") + + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + pkt_size = int(options.size) + + fg = my_graph(rx_callback, options.spb, options.excess_bw, options.snr, + options.freq_error, options.m_arity) + fg.start() + + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + send_pkt('Hello World') + + # generate and send packets + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + pktno += 1 + + send_pkt('Goodbye World') + send_pkt(eof=True) # tell modulator we're not sending any more pkts + + fg.wait() + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/pick_bitrate.py b/gnuradio-examples/python/gmsk2/pick_bitrate.py new file mode 100644 index 00000000..b35991ca --- /dev/null +++ b/gnuradio-examples/python/gmsk2/pick_bitrate.py @@ -0,0 +1,143 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +_default_bitrate = 500e3 + +_valid_spbs = (2,3,4,5,6,7) + +def _gen_tx_info(converter_rate): + results = [] + for spb in _valid_spbs: + for interp in range(16, 512 + 1, 4): + bitrate = converter_rate / interp / spb + results.append((bitrate, spb, interp)) + results.sort() + return results + +def _gen_rx_info(converter_rate): + results = [] + for spb in _valid_spbs: + for decim in range(8, 256 + 1, 2): + bitrate = converter_rate / decim / spb + results.append((bitrate, spb, decim)) + results.sort() + return results + +def _filter_info(info, samples_per_baud, xrate): + if samples_per_baud is not None: + info = [x for x in info if x[1] == samples_per_baud] + if xrate is not None: + info = [x for x in info if x[2] == xrate] + return info + +def _pick_best(target_bitrate, bits_per_symbol, info): + """ + @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate) + """ + if len(info) == 0: + raise RuntimeError, "info is zero length!" + + if target_bitrate is None: # return the fastest one + return info[-1] + + # convert bit rate to symbol rate + target_symbolrate = target_bitrate / bits_per_symbol + + # Find the closest matching symbol rate. + # In the event of a tie, the one with the lowest samples_per_baud wins. + # (We already sorted them, so the first one is the one we take) + + best = info[0] + best_delta = abs(target_symbolrate - best[0]) + for x in info[1:]: + delta = abs(target_symbolrate - x[0]) + if delta < best_delta: + best_delta = delta + best = x + + # convert symbol rate back to bit rate + return ((best[0] * bits_per_symbol),) + best[1:] + +def _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + xrate, converter_rate, gen_info): + """ + @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate) + """ + if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1: + raise ValueError, "bits_per_symbol must be an int >= 1" + + if samples_per_baud is not None and xrate is not None: # completely determined + return (float(converter_rate) / xrate / samples_per_baud, + samples_per_baud, xrate) + + if bitrate is None and samples_per_baud is None and xrate is None: + bitrate = _default_bitrate + + # now we have a target bitrate and possibly an xrate or + # samples_per_baud constraint, but not both of them. + + return _pick_best(bitrate, bits_per_symbol, + _filter_info(gen_info(converter_rate), samples_per_baud, xrate)) + +# --------------------------------------------------------------------------------------- + +def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_baud, + interp_rate, converter_rate=128e6): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_baud: samples/baud (aka samples/symbol) + @type samples_per_baud: number or None + @param interp_rate: USRP interpolation factor + @type interp_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + + @returns tuple (bitrate, samples_per_baud, interp_rate) + """ + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + interp_rate, converter_rate, _gen_tx_info) + + +def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_baud, + decim_rate, converter_rate=64e6): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_baud: samples/baud (aka samples/symbol) + @type samples_per_baud: number or None + @param decim_rate: USRP decimation factor + @type decim_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + + @returns tuple (bitrate, samples_per_baud, decim_rate) + """ + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + decim_rate, converter_rate, _gen_rx_info) diff --git a/gnuradio-examples/python/gmsk2/qpsk.py b/gnuradio-examples/python/gmsk2/qpsk.py new file mode 100644 index 00000000..6ca7f0e6 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/qpsk.py @@ -0,0 +1,418 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +PSK and differential PSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# mPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class mpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, arity, excess_bw, diff=False): + """ + Hierarchical block for RRC-filtered PSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param arity: whick PSK: 2, 4, 8 + @type arity: int in {2, 4, 8} + @param diff: differential PSK if true + @type diff: bool + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + if not arity in (2, 4): + raise ValueError, "n must be 2, 4, or 8" + + ntaps = 11 * spb + + bits_per_symbol = int(gru.log2(arity)) + self.bits_per_symbol = bits_per_symbol + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + if True or arity > 2: + self.gray_coder = gr.map_bb(binary_to_gray[arity]) + else: + self.gray_coder = None + + if diff: + self.diffenc = gr.diff_encoder_bb(arity) + else: + self.diffenc = None + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + if self.gray_coder: + fg.connect(self.bytes2chunks, self.gray_coder) + t = self.gray_coder + else: + t = self.bytes2chunks + + if diff: + fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) + else: + fg.connect(t, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.gray_coder, + gr.file_sink(gr.sizeof_char, "graycoder.dat")) + if diff: + fg.connect(self.diffenc, + gr.file_sink(gr.sizeof_char, "diffenc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self): + return self.bits_per_symbol + + +class mpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered PSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param arity: whick PSK: 2, 4, 8 + @type arity: int in {2, 4, 8} + @param diff: differential PSK if true + @type diff: bool + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + if not arity in (2, 4): + raise ValueError, "n must be 2 or 4" + + if not diff and arity==4: + raise NotImplementedError, "non-differential QPSK not supported yet" + + bits_per_symbol = int(gru.log2(arity)) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + if arity == 2: + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + else: + costas_order = 4 + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + if(diff): + self.diffdec = gr.diff_phasor_cc() + #self.diffdec = gr.diff_decoder_bb(arity) + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + if(diff): + fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.diffdec, self.slicer, self.gray_decoder, self.unpack) + else: + fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.slicer, self.gray_decoder, self.unpack) + + #fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + # self.slicer, self.diffdec, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + if(diff): + fg.connect(self.diffdec, + gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) + #fg.connect(self.diffdec, + # gr.file_sink(gr.sizeof_char, "diffdec.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.agc, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self): + return self.bits_per_symbol + + +######################################################################### + +class mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered PSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param arity: whick PSK: 2, 4, 8 + @type arity: int in {2, 4, 8} + @param diff: differential PSK if true + @type diff: bool + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + if not arity in (2, 4): + raise ValueError, "n must be 2 or 4" + + bits_per_symbol = int(gru.log2(arity)) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + if arity == 2: + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + else: + costas_order = 4 + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.slicer, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.agc, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self): + return self.bits_per_symbol + + +mpsk_demod = mpsk_demod__coherent_detection_of_differentially_encoded_psk +#mpsk_demod = mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk diff --git a/gnuradio-examples/python/gmsk2/qpsk_tester.py b/gnuradio-examples/python/gmsk2/qpsk_tester.py new file mode 100644 index 00000000..ea7bae2e --- /dev/null +++ b/gnuradio-examples/python/gmsk2/qpsk_tester.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +import random +from gnuradio import gr + +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)) + +code = string_to_1_0_list(default_access_code) +access_code = to_1_0_string(code) + +use_agc = 0 +use_rrc_tx = 1 +use_rrc_rx = 1 +use_sync_loop = 1 +use_clock_sync = 1 + +def main(): + fg = gr.flow_graph() + +# data = (1,2,3,4,5,6,7,8,9) + random.seed() + data = [random.randint(1,100) for i in range(20000)] + data[0] = 0 # you know, for the diff encoding stuff + bytes_src = gr.vector_source_b(data,False) + + k = 2 + spb = 50 + ntaps = 11*spb + excess_bw = 0.9 + threshold = 12 + constellation = (1+0j, 0+1j, -1+0j, 0-1j) + + bytes2chunks = gr.packed_to_unpacked_bb(k, gr.GR_MSB_FIRST) + diffenc = gr.diff_encoder_bb(4) + chunks2symbols = gr.chunks_to_symbols_bc(constellation) + + if use_rrc_tx: + rrc_taps_tx = gr.firdes.root_raised_cosine(spb, spb, 1.0, \ + excess_bw, ntaps) + rrc_tx = gr.interp_fir_filter_ccf(spb, rrc_taps_tx) + else: + rrc_tx = gr.interp_fir_filter_ccf(1, (1,)) + +################### CHANNEL MODEL ############################# + + phase_rotate = gr.multiply_const_cc(1-0.36j) + channel = gr.add_cc() + awgn = gr.noise_source_c(gr.GR_GAUSSIAN, 0.5) + fg.connect(awgn, (channel,1)) + +################### CHANNEL MODEL ############################# + + if use_agc: + agc = gr.agc_cc(1e-4, 1, 1) + else: + agc = gr.multiply_const_cc(1) + + # Downconverter + if use_sync_loop: + costas_alpha=0.005 + beta = costas_alpha*costas_alpha*0.25 + sync_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 0) + else: + sync_loop = gr.multiply_const_cc(1) + + if use_rrc_rx: + rrc_taps_rx = gr.firdes.root_raised_cosine(1, spb, 1.0, \ + excess_bw, ntaps) + rrc_rx = gr.fir_filter_ccf(1, rrc_taps_rx) + else: + rrc_rx = gr.fir_filter_ccf(1, (1,)) + + # Sampler + if use_clock_sync: + mu = 0.05 + omega = spb + gain_mu = 0.05 + gain_omega = 0.25*gain_mu*gain_mu + omega_rel_limit = 0.5 + clock_sync = gr.clock_recovery_mm_cc(omega, gain_omega, mu, \ + gain_mu, omega_rel_limit) + #clock_sync.set_verbose(True); + else: + clock_sync = gr.fir_filter_ccf(1, (1,)) + + diff_phasor = gr.diff_phasor_cc() + slicer = gr.constellation_decoder_cb((constellation), (0,1,2,3)) + unpack = gr.unpack_k_bits_bb(k) + access = gr.correlate_access_code_bb(access_code,threshold) + + sink = gr.file_sink(gr.sizeof_char, 'output.dat') + + fg.connect(bytes_src, bytes2chunks, diffenc, chunks2symbols, rrc_tx) + fg.connect(rrc_tx, phase_rotate, channel, agc) + fg.connect(agc, sync_loop, rrc_rx, clock_sync, diff_phasor, slicer, sink) + + test = gr.file_sink(gr.sizeof_gr_complex, 'test.dat') + fg.connect(rrc_rx, test) + + fg.connect(chunks2symbols, gr.file_sink(gr.sizeof_gr_complex, 'rrc_tx.dat')) # into TX RRC + fg.connect(channel, gr.file_sink(gr.sizeof_gr_complex, 'channel.dat')) # Out of TX RRC + fg.connect(rrc_rx, gr.file_sink(gr.sizeof_gr_complex, 'rrc_rx.dat')) # Out of RX RRC -> clock_sync + fg.connect(clock_sync, gr.file_sink(gr.sizeof_gr_complex, 'clock_sync.dat')) # Out of M&M sync loop + fg.connect(bytes2chunks, gr.file_sink(gr.sizeof_char, 'source.dat')) + + fg.start() + fg.wait() + +if __name__ == "__main__": + main() + + + + diff --git a/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py b/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py new file mode 100644 index 00000000..bf7698a2 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +import random +from gnuradio import gr, gru, usrp + +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)) + +code = string_to_1_0_list(default_access_code) + +access_code = to_1_0_string(code) + +def main(): + + fg = gr.flow_graph() + f_rf = 5e6 + fs = 400e3 + sr = 100e3 + alpha = 0.5 + M = 4 + k = int(gru.log2(M)) + + # Source + src = usrp.source_c () + adc_rate = src.adc_rate() + usrp_decim = int(adc_rate / fs) + src.set_decim_rate(usrp_decim) + + subdev_spec = usrp.pick_rx_subdevice(src) + subdev = usrp.selected_subdev(src, subdev_spec) + print "Using RX d'board %s" % (subdev.side_and_name(),) + src.set_mux(usrp.determine_rx_mux_value(src, subdev_spec)) + src.tune(0, subdev, f_rf) + + g = subdev.gain_range() + subdev.set_gain(g[1]) + subdev.set_auto_tr(True) + + print "USRP Decimation Rate = %d" % usrp_decim + print "RF Frequency = %d" % f_rf + + agc = gr.multiply_const_cc(0.0025) + + # Downconverter + costas_alpha=0.005 + beta = costas_alpha*costas_alpha*0.25 + sync_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 0) + + # Stage 2 +# fs2 = 200e3 +# D = int(fs / fs2) +# decimator = gr.keep_one_in_n(gr.sizeof_gr_complex, D) +# print "D = %d\nAfter decimator fs = %f" % (D, fs2) + + # Demodulator + taps = gr.firdes.root_raised_cosine(1, fs, sr, alpha, 45) + rrc = gr.fir_filter_ccf(1, taps) + + # Sampler + mu = 0.01 + omega = 4.3 + gain_mu = 0.05 + gain_omega = 0.25*gain_mu*gain_mu + omega_rel_limit = 0.5 + clock_sync = gr.clock_recovery_mm_cc(omega, gain_omega, mu, + gain_mu, omega_rel_limit) + clock_sync.set_verbose(False) + + diff_phasor = gr.diff_phasor_cc() + + threshold = 12 + constellation = (1+0j, 0+1j, -1+0j, 0-1j) + slicer = gr.constellation_decoder_cb((constellation), (0,1,2,3)) + unpack = gr.unpack_k_bits_bb(k) + access = gr.correlate_access_code_bb(access_code,threshold) + + test = gr.file_sink(gr.sizeof_gr_complex, 'test.dat') + sink = gr.file_sink(gr.sizeof_char, 'output.dat') + + fg.connect(src, agc, sync_loop, rrc, clock_sync) + fg.connect(clock_sync, diff_phasor, slicer, unpack, access, sink) + + fg.connect(slicer, gr.file_sink(gr.sizeof_char, 'chunks.dat')) + fg.connect(unpack, gr.file_sink(gr.sizeof_char, 'unpack.dat')) + fg.connect(clock_sync, gr.file_sink(gr.sizeof_gr_complex, 'phasor.dat')) + + fg.start() + fg.wait() + +if __name__ == "__main__": + main() diff --git a/gnuradio-examples/python/gmsk2/receive_path.py b/gnuradio-examples/python/gmsk2/receive_path.py new file mode 100644 index 00000000..505ff7c4 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/receive_path.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp + +# from current dir +from pick_bitrate import pick_rx_bitrate + +# ///////////////////////////////////////////////////////////////////////////// +# receive path +# ///////////////////////////////////////////////////////////////////////////// + +class receive_path(gr.hier_block): + def __init__(self, fg, demod_class, rx_subdev_spec, + bitrate, decim, spb, + rx_callback, options, demod_kwargs): + + self.u = usrp.source_c (fusb_block_size=options.fusb_block_size, + fusb_nblocks=options.fusb_nblocks) + adc_rate = self.u.adc_rate() + + (self._bitrate, self._spb, self._decim) = \ + pick_rx_bitrate(bitrate, demod_class.bits_per_baud(), spb, decim, adc_rate) + + self.u.set_decim_rate(self._decim) + sw_decim = 1 + + if rx_subdev_spec is None: + rx_subdev_spec = usrp.pick_rx_subdevice(self.u) + self.subdev = usrp.selected_subdev(self.u, rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, rx_subdev_spec)) + + # Create filter to get actual channel we want + chan_coeffs = gr.firdes.low_pass (1.0, # gain + sw_decim * self._spb, # sampling rate + 1.0, # midpoint of trans. band + 0.1, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + print "len(rx_chan_coeffs) =", len(chan_coeffs) + + # Decimating Channel filter + # complex in and out, float taps + self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs) + #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs) + + # receiver + self.packet_receiver = \ + blks.demod_pkts(fg, + demod_class(fg, spb=self._spb, **demod_kwargs), + access_code=None, + callback=rx_callback, + threshold=-1) + + fg.connect(self.u, self.chan_filt, self.packet_receiver) + gr.hier_block.__init__(self, fg, None, None) + + g = self.subdev.gain_range() + #self.set_gain((g[0] + g[1])/2) # set gain to midpoint + self.set_gain(g[1]) # set gain to max + self.set_auto_tr(True) # enable Auto Transmit/Receive switching + + # Carrier Sensing Blocks + alpha = 0.001 + thresh = 30 # in dB, will have to adjust + self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) + fg.connect(self.chan_filt, self.probe) + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(0, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + if gain is None: + r = self.subdev.gain_range() + gain = (r[0] + r[1])/2 # set gain to midpoint + self.gain = gain + return self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + return self.subdev.set_auto_tr(enable) + + def bitrate(self): + return self._bitrate + + def spb(self): + return self._spb + + def decim(self): + return self._decim + + + def carrier_sensed(self): + """ + Return True if we think carrier is present. + """ + #return self.probe.level() > X + return self.probe.unmuted() + + def carrier_threshold(self): + """ + Return current setting in dB. + """ + return self.probe.threshold() + + def set_carrier_threshold(self, threshold_in_db): + """ + Set carrier threshold. + + @param threshold_in_db: set detection threshold + @type threshold_in_db: float (dB) + """ + self.probe.set_threshold(threshold_in_db) + diff --git a/gnuradio-examples/python/gmsk2/rx_voice.py b/gnuradio-examples/python/gmsk2/rx_voice.py new file mode 100755 index 00000000..3f5cc3b4 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/rx_voice.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import audio +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +from gnuradio.vocoder import gsm_full_rate + +import random +import struct + +# from current dir +from receive_path import receive_path + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class audio_tx(gr.hier_block): + def __init__(self, fg): + self.packet_src = gr.message_source(33) + voice_decoder = gsm_full_rate.decode_ps() + s2f = gr.short_to_float () + sink_scale = gr.multiply_const_ff(1.0/32767.) + audio_sink = audio.sink(8000) + fg.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink) + gr.hier_block.__init__(self, fg, self.packet_src, audio_sink) + + def msgq(self): + return self.packet_src.msgq() + + +class my_graph(gr.flow_graph): + + def __init__(self, rx_subdev_spec, bitrate, decim_rate, spb, rx_callback, log): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, rx_subdev_spec, bitrate, decim_rate, + spb, rx_callback, log) + + self.audio_tx = audio_tx(self) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + n_rcvd += 1 + if ok: + n_right += 1 + + fg.audio_tx.msgq().insert_tail(gr.message_from_string(payload)) + + print "ok = %r n_rcvd = %4d n_right = %4d" % ( + ok, n_rcvd, n_right) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=100e3, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("","--log", action="store_true", default=False, + help="enable diagnostic logging") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + # build the graph + fg = my_graph(options.rx_subdev_spec, options.bitrate, + options.decim, options.spb, rx_callback, options.log) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) + print "spb: %3d" % (fg.rxpath.spb(),) + print "decim: %3d" % (fg.rxpath.decim(),) + + fg.rxpath.set_freq(options.freq) + fg.rxpath.set_gain(options.gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/transmit_path.py b/gnuradio-examples/python/gmsk2/transmit_path.py new file mode 100644 index 00000000..a1df1579 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/transmit_path.py @@ -0,0 +1,108 @@ +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp + +# from current dir +from pick_bitrate import pick_tx_bitrate + +# ///////////////////////////////////////////////////////////////////////////// +# transmit path +# ///////////////////////////////////////////////////////////////////////////// + +class transmit_path(gr.hier_block): + def __init__(self, fg, mod_class, tx_subdev_spec, + bitrate, interp, spb, gain, + options, mod_kwargs): + + self.normal_gain = gain + + self.u = usrp.sink_c (fusb_block_size=options.fusb_block_size, + fusb_nblocks=options.fusb_nblocks) + dac_rate = self.u.dac_rate(); + + print mod_class + print mod_class.bits_per_baud() + (self._bitrate, self._spb, self._interp) = \ + pick_tx_bitrate(bitrate, mod_class.bits_per_baud(), spb, interp, dac_rate) + + self.u.set_interp_rate(self._interp) + + # determine the daughterboard subdevice we're using + if tx_subdev_spec is None: + tx_subdev_spec = usrp.pick_tx_subdevice(self.u) + self.u.set_mux(usrp.determine_tx_mux_value(self.u, tx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, tx_subdev_spec) + print "Using TX d'board %s" % (self.subdev.side_and_name(),) + + # transmitter + self.packet_transmitter = \ + blks.mod_pkts(fg, + mod_class(fg, spb=self._spb, **mod_kwargs), + access_code=None, + msgq_limit=4, + pad_for_usrp=True) + + self.amp = gr.multiply_const_cc (self.normal_gain) + + fg.connect(self.packet_transmitter, self.amp, self.u) + gr.hier_block.__init__(self, fg, None, None) + + self.set_gain(self.subdev.gain_range()[1]) # set max Tx gain + self.set_auto_tr(True) # enable Auto Transmit/Receive switching + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + self.gain = gain + self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + return self.subdev.set_auto_tr(enable) + + def send_pkt(self, payload='', eof=False): + return self.packet_transmitter.send_pkt(payload, eof) + + def bitrate(self): + return self._bitrate + + def spb(self): + return self._spb + + def interp(self): + return self._interp diff --git a/gnuradio-examples/python/gmsk2/tunnel.py b/gnuradio-examples/python/gmsk2/tunnel.py new file mode 100755 index 00000000..bc10d3e3 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/tunnel.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# ///////////////////////////////////////////////////////////////////////////// +# +# This code sets up up a virtual ethernet interface (typically gr0), +# and relays packets between the interface and the GNU Radio PHY+MAC +# +# What this means in plain language, is that if you've got a couple +# of USRPs on different machines, and if you run this code on those +# machines, you can talk between them using normal TCP/IP networking. +# +# ///////////////////////////////////////////////////////////////////////////// + + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import time +import struct +import sys +import os + +# from current dir +from transmit_path import transmit_path +from receive_path import receive_path +import fusb_options + +#print os.getpid() +#raw_input('Attach and press enter') + + +# ///////////////////////////////////////////////////////////////////////////// +# +# Use the Universal TUN/TAP device driver to move packets to/from kernel +# +# See /usr/src/linux/Documentation/networking/tuntap.txt +# +# ///////////////////////////////////////////////////////////////////////////// + +# Linux specific... +# TUNSETIFF ifr flags from + +IFF_TUN = 0x0001 # tunnel IP packets +IFF_TAP = 0x0002 # tunnel ethernet frames +IFF_NO_PI = 0x1000 # don't pass extra packet info +IFF_ONE_QUEUE = 0x2000 # beats me ;) + +def open_tun_interface(tun_device_filename): + from fcntl import ioctl + + mode = IFF_TAP | IFF_NO_PI + TUNSETIFF = 0x400454ca + + tun = os.open(tun_device_filename, os.O_RDWR) + ifs = ioctl(tun, TUNSETIFF, struct.pack("16sH", "gr%d", mode)) + ifname = ifs[:16].strip("\x00") + return (tun, ifname) + + +# ///////////////////////////////////////////////////////////////////////////// +# the flow graph +# ///////////////////////////////////////////////////////////////////////////// + +class my_graph(gr.flow_graph): + + def __init__(self, mod_class, demod_class, tx_subdev_spec, rx_subdev_spec, + bitrate, decim_rate, interp_rate, spb, + bt, rx_callback, options): + + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, + bt, options) + self.rxpath = receive_path(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options) + + def send_pkt(self, payload='', eof=False): + return self.txpath.send_pkt(payload, eof) + + def carrier_sensed(self): + """ + Return True if the receive path thinks there's carrier + """ + return self.rxpath.carrier_sensed() + + +# ///////////////////////////////////////////////////////////////////////////// +# Carrier Sense MAC +# ///////////////////////////////////////////////////////////////////////////// + +class cs_mac(object): + """ + Prototype carrier sense MAC + + Reads packets from the TUN/TAP interface, and sends them to the PHY. + Receives packets from the PHY via phy_rx_callback, and sends them + into the TUN/TAP interface. + + Of course, we're not restricted to getting packets via TUN/TAP, this + is just an example. + """ + def __init__(self, tun_fd, verbose=False): + self.tun_fd = tun_fd # file descriptor for TUN/TAP interface + self.verbose = verbose + self.fg = None # flow graph (access to PHY) + + def set_flow_graph(self, fg): + self.fg = fg + + def phy_rx_callback(self, ok, payload): + """ + Invoked by thread associated with PHY to pass received packet up. + + @param ok: bool indicating whether payload CRC was OK + @param payload: contents of the packet (string) + """ + if self.verbose: + print "Rx: ok = %r len(payload) = %4d" % (ok, len(payload)) + if ok: + os.write(self.tun_fd, payload) + + def main_loop(self): + """ + Main loop for MAC. + Only returns if we get an error reading from TUN. + + FIXME: may want to check for EINTR and EAGAIN and reissue read + """ + min_delay = 0.001 # seconds + + while 1: + payload = os.read(self.tun_fd, 10*1024) + if not payload: + self.fg.send_pkt(eof=True) + break + + if self.verbose: + print "Tx: len(payload) = %4d" % (len(payload),) + + delay = min_delay + while self.fg.carrier_sensed(): + sys.stderr.write('B') + time.sleep(delay) + if delay < 0.050: + delay = delay * 2 # exponential back-off + + self.fg.send_pkt(payload) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + parser = OptionParser (option_class=eng_option) + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-g", "--rx-gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-c", "--carrier-threshold", type="eng_float", default=30, + help="set carrier detect threshold (dB) [default=%default]") + parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]") + parser.add_option("","--tun-device-filename", default="/dev/net/tun", + help="path to tun device file [default=%default]") + parser.add_option("-v","--verbose", action="store_true", default=False) + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + # open the TUN/TAP interface + (tun_fd, tun_ifname) = open_tun_interface(options.tun_device_filename) + + # Attempt to enable realtime scheduling + r = gr.enable_realtime_scheduling() + if r == gr.RT_OK: + realtime = True + else: + realtime = False + print "Note: failed to enable realtime scheduling" + + + # If the user hasn't set the fusb_* parameters on the command line, + # pick some values that will reduce latency. + + if options.fusb_block_size == 0 and options.fusb_nblocks == 0: + if realtime: # be more aggressive + options.fusb_block_size = gr.prefs().get_long('fusb', 'rt_block_size', 1024) + options.fusb_nblocks = gr.prefs().get_long('fusb', 'rt_nblocks', 16) + else: + options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096) + options.fusb_nblocks = gr.prefs().get_long('fusb', 'nblocks', 16) + + print "fusb_block_size =", options.fusb_block_size + print "fusb_nblocks =", options.fusb_nblocks + + # instantiate the MAC + mac = cs_mac(tun_fd, verbose=True) + + + # build the graph (PHY) + fg = my_graph(blks.gmsk2_mod, blks.gmsk2_demod, + options.tx_subdev_spec, options.rx_subdev_spec, + options.bitrate, options.decim, options.interp, + options.spb, options.bt, mac.phy_rx_callback, + options) + + mac.set_flow_graph(fg) # give the MAC a handle for the PHY + + if fg.txpath.bitrate() != fg.rxpath.bitrate(): + print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % ( + eng_notation.num_to_str(fg.txpath.bitrate()), + eng_notation.num_to_str(fg.rxpath.bitrate())) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + ok = fg.txpath.set_freq(options.freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + ok = fg.rxpath.set_freq(options.freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + fg.rxpath.set_gain(options.rx_gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + fg.rxpath.set_carrier_threshold(options.carrier_threshold) + print "Carrier sense threshold:", options.carrier_threshold, "dB" + + print + print "Allocated virtual ethernet interface: %s" % (tun_ifname,) + print "You must now use ifconfig to set its IP address. E.g.," + print + print " $ sudo ifconfig %s 10.10.10.1" % (tun_ifname,) + print + print "Be sure to use a different address in the same subnet for each machine." + print + + + fg.start() # Start executing the flow graph (runs in separate threads) + + mac.main_loop() # don't expect this to return... + + fg.stop() # but if it does, tell flow graph to stop. + fg.wait() # wait for it to finish + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/tx_voice.py b/gnuradio-examples/python/gmsk2/tx_voice.py new file mode 100755 index 00000000..9e274e5e --- /dev/null +++ b/gnuradio-examples/python/gmsk2/tx_voice.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import audio +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +from gnuradio.vocoder import gsm_full_rate + +import random +import time +import struct +import sys + +# from current dir +from transmit_path import transmit_path + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, tx_subdev_spec, bitrate, interp_rate, spb, bt): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, tx_subdev_spec, bitrate, interp_rate, spb, bt) + + audio_input = "" + sample_rate = 8000 + src = audio.source(sample_rate, audio_input) + src_scale = gr.multiply_const_ff(32767) + f2s = gr.float_to_short() + voice_coder = gsm_full_rate.encode_sp() + self.packets_from_encoder = gr.msg_queue() + packet_sink = gr.message_sink(33, self.packets_from_encoder, False) + self.connect(src, src_scale, f2s, voice_coder, packet_sink) + + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=100e3, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + pkt_size = int(options.size) + + # build the graph + fg = my_graph(options.tx_subdev_spec, options.bitrate, options.interp, + options.spb, options.bt) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + fg.txpath.set_freq(options.freq) + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + while n < nbytes: + packet = fg.packets_from_encoder.delete_head() + s = packet.to_string() + send_pkt(s) + n += len(s) + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + fg.txpath.set_auto_tr(False) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/mc4020/Makefile.am b/gnuradio-examples/python/mc4020/Makefile.am new file mode 100644 index 00000000..21bed3e4 --- /dev/null +++ b/gnuradio-examples/python/mc4020/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + fm_demod.py \ + mc4020_fft.py + + + + diff --git a/gnuradio-examples/python/mc4020/fm_demod.py b/gnuradio-examples/python/mc4020/fm_demod.py new file mode 100755 index 00000000..e58407f7 --- /dev/null +++ b/gnuradio-examples/python/mc4020/fm_demod.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import mc4020 +import sys + +def high_speed_adc (fg, input_rate): + # return gr.file_source (gr.sizeof_short, "dummy.dat", False) + return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + +# +# return a gr.flow_graph +# +def build_graph (freq1, freq2): + input_rate = 20e6 + cfir_decimation = 125 + audio_decimation = 5 + + quad_rate = input_rate / cfir_decimation + audio_rate = quad_rate / audio_decimation + + fg = gr.flow_graph () + + # use high speed ADC as input source + src = high_speed_adc (fg, input_rate) + + # compute FIR filter taps for channel selection + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + input_rate, # sampling rate + 250e3, # low pass cutoff freq + 8*100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + + # input: short; output: complex + chan_filter1 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq1, # 1st station freq + input_rate) + + (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, chan_filter1) + fg.connect (chan_filter1, head1) + fg.connect (tail1, (audio_sink, 0)) + + # two stations at once? + if freq2: + # Extract the second station and connect + # it to a second pipeline... + + # input: short; output: complex + chan_filter2 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq2, # 2nd station freq + input_rate) + + (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation) + + fg.connect (src, chan_filter2) + fg.connect (chan_filter2, head2) + fg.connect (tail2, (audio_sink, 1)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverteed complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (args): + nargs = len (args) + if nargs == 1: + freq1 = float (args[0]) * 1e6 + freq2 = None + elif nargs == 2: + freq1 = float (args[0]) * 1e6 + freq2 = float (args[1]) * 1e6 + else: + sys.stderr.write ('usage: fm_demod freq1 [freq2]\n') + sys.exit (1) + + # connect to RF front end + rf_front_end = gr.microtune_4937_eval_board () + if not rf_front_end.board_present_p (): + raise IOError, 'RF front end not found' + + # set front end gain + rf_front_end.set_AGC (300) + IF_freq = rf_front_end.get_output_freq () + IF_freq = 5.75e6 + + if not freq2: # one station + + rf_front_end.set_RF_freq (freq1) + fg = build_graph (IF_freq, None) + + else: # two stations + + if abs (freq1 - freq2) > 5.5e6: + raise IOError, 'freqs too far apart' + + target_freq = (freq1 + freq2) / 2 + actual_freq = rf_front_end.set_RF_freq (target_freq) + #actual_freq = target_freq + + fg = build_graph (IF_freq + freq1 - actual_freq, + IF_freq + freq2 - actual_freq) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main (sys.argv[1:]) + + diff --git a/gnuradio-examples/python/mc4020/mc4020_fft.py b/gnuradio-examples/python/mc4020/mc4020_fft.py new file mode 100755 index 00000000..3348ad4f --- /dev/null +++ b/gnuradio-examples/python/mc4020/mc4020_fft.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import mc4020 +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink +from optparse import OptionParser +import wx + +class app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + + parser = OptionParser (option_class=eng_option) + (options, args) = parser.parse_args () + + input_rate = 20e6 + src = mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + cvt = gr.short_to_float () + block, fft_win = fftsink.make_fft_sink_f (self, panel, "Rx Data", 512, input_rate) + + self.connect (src, cvt) + self.connect (cvt, block) + vbox.Add (fft_win, 1, wx.EXPAND) + + +def main (): + app = stdgui.stdapp (app_flow_graph, "USRP FFT") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/multi_fft.py b/gnuradio-examples/python/multi-antenna/multi_fft.py new file mode 100755 index 00000000..ca9c614a --- /dev/null +++ b/gnuradio-examples/python/multi-antenna/multi_fft.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +import wx +import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(stdgui.gui_flow_graph): + + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + nchan = 4 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddc() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddc())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) + + self.subdev = self.u.db[0] + self.u.db[1] + + if (len (self.subdev) != 4 or + self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or + self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, di) + + + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + for i in range(nchan): + scope = fftsink.fft_sink_c(self, panel, sample_rate=input_rate/sw_decim, + title="Input %d" % (i,), + ref_level=80, y_per_div=20) + vbox.Add(scope.win, 10, wx.EXPAND) + + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + self.connect((di, i), chan_filt, scope) + else: + self.connect((di, i), scope) + + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + +def main (): + app = stdgui.stdapp(my_graph, "Multi Scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/multi_file.py b/gnuradio-examples/python/multi-antenna/multi_file.py new file mode 100755 index 00000000..e2a6e04f --- /dev/null +++ b/gnuradio-examples/python/multi-antenna/multi_file.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +import wx +import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + parser.add_option("-o", "--output", type="string", default=None, + help="set output basename") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + if options.output is None: + parser.print_help() + sys.stderr.write("You must provide an output filename base with -o OUTPUT\n") + raise SystemExit + else: + basename = options.output + + nchan = 4 + nsecs = 4.0 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddc() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddc())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + sink_data_rate = input_rate/sw_decim + print "Scope data rate = %s" % (eng_notation.num_to_str(sink_data_rate),) + + self.subdev = self.u.db[0] + self.u.db[1] + + if (len(self.subdev) != 4 or + self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or + self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # collect 1 second worth of data + limit = int(nsecs * input_rate * nchan) + print "limit = ", limit + head = gr.head(gr.sizeof_gr_complex, limit) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, head, di) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + for i in range(nchan): + + sink = gr.file_sink(gr.sizeof_gr_complex, + basename + ("-%s-%d.dat" % (eng_notation.num_to_str(sink_data_rate), i))) + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + self.connect((di, i), chan_filt, sink) + else: + self.connect((di, i), sink) + + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + +def main (): + my_graph().run() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/multi_scope.py b/gnuradio-examples/python/multi-antenna/multi_scope.py new file mode 100755 index 00000000..43aa77b0 --- /dev/null +++ b/gnuradio-examples/python/multi-antenna/multi_scope.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +import wx +import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(stdgui.gui_flow_graph): + + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + nchan = 4 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddc() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddc())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) + + self.subdev = self.u.db[0] + self.u.db[1] + + if (len(self.subdev) != 4 or + self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or + self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, di) + + # our destination (8 float inputs) + self.scope = scopesink.scope_sink_f(self, panel, sample_rate=input_rate/sw_decim) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + # bust the deinterleaved complex channels into floats + for i in range(nchan): + + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + c2f = gr.complex_to_float() + self.connect((di, i), chan_filt, c2f) + else: + c2f = gr.complex_to_float() + self.connect((di, i), c2f) + + self.connect((c2f, 0), (self.scope, 2*i + 0)) + self.connect((c2f, 1), (self.scope, 2*i + 1)) + + + self._build_gui(vbox) + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + + def _build_gui(self, vbox): + vbox.Add(self.scope.win, 10, wx.EXPAND) + + + +def main (): + app = stdgui.stdapp(my_graph, "Multi Scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi_usrp/Makefile.am b/gnuradio-examples/python/multi_usrp/Makefile.am new file mode 100644 index 00000000..c2c6a294 --- /dev/null +++ b/gnuradio-examples/python/multi_usrp/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + README \ + multi_usrp_oscope.py \ + multi_usrp_rx_cfile.py + + + diff --git a/gnuradio-examples/python/multi_usrp/README b/gnuradio-examples/python/multi_usrp/README new file mode 100644 index 00000000..c93d7736 --- /dev/null +++ b/gnuradio-examples/python/multi_usrp/README @@ -0,0 +1,260 @@ +Quick start multi-usrp: + +Unpack, build and install usrp, gnuradio-core and gr-usrp +Versions need to be more recent then 2.7cvs/svn 11 may 2006 + +Make sure usrp/fpga/rbf/rev2/multi*.rbf is installed in /usr/local/share/usrp/rev2/ +Make sure usrp/fpga/rbf/rev4/multi*.rbf is installed in /usr/local/share/usrp/rev4/ +(If in doubt, copy manually) + +build and install gr-wxgui gr-audio-xxx and so on. + +unpack gnuradio-examples. + +There is a gnuradio-examples/python/multi_usrp directory which contains examples + + +Put at least a basic RX or dbsrx board in RXA of the master and RXA of the slave board. +Make sure that the usrps have a serial or unique identifier programmed in their eeprom. +(All new rev 4.1 boards have this) +You can do without a serial but then you never know which usrp is the master and which is the slave. + + +CONNECTING THE CABLES +Now connect the 64MHz clocks between the boards with a short sma coax cable. +(See the wiki on how to enable clock-out and clock-in +http://comsec.com/wiki?USRPClockingNotes ) + +You need one board with a clock out and one board with a clock in. + +You can choose any of the two boards as master or slave, this is not dependant on which board has the clock-out or in. +In my experiments I had fewer problems when the board that has the clock-in will be the master board. + +You can use a standard 16-pole flatcable to connect tvrx, basic-rx or dbsrx boards. +Of this 16pin flatcable only two pins are used (io15 and ground) +For all new daughterboards which use up a lot of io pins you have to use a cable with fewer connections. +The savest is using a 2pin headercable connected to io15,gnd (a cable like the ones used to connect frontpanel leds to the mainboard of a PC) + +If using basic rx board: + Connect a 16-pole flatcable from J25 on basicrx/dbs_rx in rxa of the master usrp to J25 on basicrx/dbsrx in RXA of the slave usrp + Don't twist the cable (Make sure the pin1 marker (red line on the flatcable) is on the same side of the connector (at io-8 on the master and at io8 on the slave.)) + For basic_rx this means the marker should be on the side of the dboard with the sma connectors. + For dbs_rx this means the marker should be on the side of the dboard with the two little chips. + In other words, don't twist the cable, you will burn your board if you do. + +You can also connect a flatcable with multiple connectors from master-J25 to slave1-J25 to slave2-J25 to ... +You will however have to think of something to create a common 64Mhz clock for more then two usrps. + +For all other daughterboards, connect a 2wire cable from masterRXA J25 io15,gnd to slaveRXA J25 io15,gnd + + +So now the hardware is setup, software is setup. Lets do some tests. + +Connect power to both usrps. +unpack the gnuradio_examples somewhere (cvs version later then 11 may 2006) +go to the gnuradio-examples/python/multi_usrp folder. + +Now run + ./multi_usrp_oscope.py -x 12345678 + +It should tell you that usrp 12345678 is not found and tell you which serials are available. + +Now run ./multi_usrp_oscope.py -x actualserialnum +You should now get an oscope with two channels, one is from the master and one is from the slave +It will which show the I-signal from channel 0 of the master usrp and I-signal from channel 0 of the slave usrp. +(For testing connect the same signal source to the inputs of both boards) +The signals should be aligned. +If you click the sync button, it will resync the master and slave (should never be needed) + +Now run +./multi_usrp_oscope.py --help +To see all available options. + + +Now you are ready to do phase-locked aligned signal processing. + +You can also capture to file with: +./multi_usrp_rx_cfile.py + +run ./multi_usrp_rx_cfile.py --help to see all available options. + + + +Here follows a description of the detail blocks used in usrp_multi.py + +Multi usrp + +With this code you can connect two or more usrps (with a locked clock) and get synchronised samples. +You must connect a (flat)cable between a dboard on the master in RXA and a dboard on the slave in RXA. +You then put one usrp in master mode, put the other in slave mode. + +The easiest thing to see how this works is just looking at the code in + multi_usrp_oscope.py + multi_usrp_rx_cfile.py + +Use the usrp_multi block which is installed by gr-usrp. +instantiate in the following way: + + self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, nchan=options.nchan ) + +nchan should be 2 or 4. + +You determine which is the master by master_serialno (this is a text string a hexadecimal number). +If you enter a serial number which is not found it will print the serial numbers which are available. +If you give no serial number (master_serialno=None), the code will pick a Master for you. + +You can get a reference to the master and the slave usrp in the following way: + + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + +You only need these references for setting freqs/gains or getting info about daughterboards. +Don't use the output directly but use the aligned output from multi.get_master_source_c() and multi.get_slave_source_c() + +You get references to the aligned output samples in the following way: +aligned_master_source_c=self.multi.get_master_source_c() +aligned_slave_source_c=self.multi.get_slave_source_c() + +These blocks have multiple outputs. +output 0 is the sample counter (high bits in I, low bits in Q) +You normally don't need the samplecounters so you can ignore output 0 + +output 1 is the first aligend output channel (if you enable 2 or 4 channels) +output 2 is the second output channel (only if you enable 4 channels) + +so the usefull 4 channels are: +self.aligned_master_chan1=(self.multi.get_master_source_c(),1) +self.aligned_master_chan2=(self.multi.get_master_source_c(),2) +self.aligned_slave_chan1=(self.multi.get_slave_source_c(),1) +self.aligned_slave_chan2=(self.multi.get_slave_source_c(),2) + +The two samplecounters are: +self.aligned_master_samplecounter=(self.multi.get_master_source_c(),0) +self.aligned_slave_samplecounter=(self.multi.get_slave_source_c(),0) + +You can set the gain or tune the frequency for all 4 receive daughetrboards at once: + self.multi.set_gain_all_rx(options.gain) + result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq) + +This will only work reliably when you have all the same daughterboards. +Otherwise set all freqs and gains individually. + +You must call self.multi.sync() at least once AFTER the flowgraph has started running. +(This will synchronise the streams of the two usrps) + +This work was funded by Toby Oliver at Sensus Analytics / Path Intelligence. +Many Thanks for making this possible. + +It was written by Martin Dudok van Heel at Olifantasia. + + + +Here follows a brief of the new blocks and (changes)functionality written for multi-usrp support. + +You can also look at the generated documentation in +/usr/local/share/doc/gnuradio-core-X.X +/usr/local/share/doc/usrp-X.X +(Make sure to build and install the documentation, go to the doc directory of the sourcetree and issue make doc; make install) + + +gnuradio-examples: +new/changed files: +multi_usrp/multi_usrp_oscope.py +multi_usrp/multi_usrp_rx_cfile.py + + +gnuradio-core: +gr.align_on_samplenumbers_ss (int nchan,int align_interval) + +align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values) + +Parameters: + nchan number of complex_short input channels (including the 32 bit counting channel) + align_interval interval at which the samples are aligned, ignored for now. + +Pay attention on how you connect this block It expects a minimum of 2 usrp_source_s with nchan number of channels and as mode usrp_prims.bmFR_MODE_RX_COUNTING_32BIT enabled. This means that the first complex_short channel is an interleaved 32 bit counter. The samples are aligned by dropping samples untill the samplenumbers match. + +files: +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i + + +gr-usrp + added _write_fpga_reg_masked + added usrp_multi.py + new usrp_multi block which can instantiate two linked usrps as master and slave and alignes their output. + It has a sync() function which should be called AFTER the flowgraph has started running. + bool sync(); + \brief Call this on a master usrp to sync master and slave by outputing a sync pulse on rx_a_io[15]. + The 32 bit samplecounter of master and slave will be reset to zero and all phase and buffer related things in the usrps are reset. + Call this only after the flowgraph has been started, otherwise there will be no effect since everything is kept in reset state as long as the flowgraph is not running. + \returns true if successfull. + +files: +configure.ac +src/Makefile.am +src/usrp1.i +src/usrp1_source_base.cc +src/usrp1_source_base.h +src/usrp_multi.py + +usrp-0.11cvsmulti: +usrp: + new constant bmFR_MODE_RX_COUNTING_32BIT (could also be added as extra mode like FPGA_MODE_COUNTING_32BIT) + Use this for the mode parameter when creating a usrp when you want to use the master/slave setup or if you want to use the 32 bit counter for other things, like testing with gr.check_counting_s(True) + + added register FR_RX_MASTER_SLAVE + added bitno and bitmaskes: + bmFR_MODE_RX_COUNTING_32BIT + + bitnoFR_RX_SYNC + bitnoFR_RX_SYNC_MASTER + bitnoFR_RX_SYNC_SLAVE + + bitnoFR_RX_SYNC_INPUT_IOPIN 15 + bmFR_RX_SYNC_INPUT_IOPIN (1<= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=first one with a daughterboard)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + #align interval is default not yet enabled in gr.align_on_samplenumbers_ss + #parser.add_option("-a", "--align_interval", type="int", default=-1, + # help="Align master and slave every so much samples.") + + # width 8 does not work yet with multi_usrp because it interferes with the 32 bit samplecounter + #parser.add_option("-8", "--width-8", action="store_true", default=False, + # help="Enable 8-bit samples across USB") + parser.add_option("-m", "--mux", type="intx", default=None, + help="set fpga FR_RX_MUX register to MUX") + parser.add_option("-n", "--frame-decim", type="int", default=1, + help="set oscope frame decimation factor to n [default=1]") + parser.add_option("-N", "--nchan", type="int", default=2, + help="set nchannels to NCHAN") + parser.add_option("-q", "--show-q", action="store_true", default=False, + help="show the q value of the complex samples") + parser.add_option("-s", "--show-counters", action="store_true", default=False, + help="show the counters") + parser.add_option("-v", "--v-scale", type="eng_float", default=1000, + help="set oscope initial V/div to SCALE [default=%default]") + parser.add_option("-t", "--t-scale", type="eng_float", default=49e-6, + help="set oscope initial s/div to SCALE [default=50us]") + parser.add_option("-x", "--master-serialno", type="string", default=None, + help="Serial_no of the usrp which should be the MASTER (default= select any)") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + # build the graph + + #self.u = usrp.source_c(which=options.which_usrp,decim_rate=options.decim) + if (options.mux is None) | (4==options.nchan): + init_mux=None #use default mux which is 0x10321032 + else: + init_mux=options.mux + + init_gain=0.0 + init_freq=0.0 + init_align_interval=-1 + + self.multi=usrp_multi.multi_source_align( self, options.master_serialno, options.decim, + options.nchan, init_gain, init_freq, init_mux, init_align_interval) + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.um) + if (options.mux==None) and (options.nchan!=4): + mux=usrp.determine_rx_mux_value(self.um, options.rx_subdev_spec) + mux= (mux<<8 & 0xffffffff) | (mux & 0xff) + self.um.set_mux(mux) + self.us.set_mux(mux) + + # width 8 does not work yet with multi_usrp because it interferes with the 32 bit samplecounter + #if options.width_8: + # width = 8 + # shift = 8 + # format = self.um.make_format(width, shift) + # r = self.um.set_format(format) + # r = self.us.set_format(format) + + # determine the daughterboard subdevice of the first channel we're using + self.subdevm = usrp.selected_subdev(self.um, options.rx_subdev_spec) + self.subdevs = usrp.selected_subdev(self.us, options.rx_subdev_spec) + + input_rate = self.um.adc_freq() / self.um.decim_rate() + + self.scope = scopesink.scope_sink_f(self, panel, sample_rate=input_rate, + frame_decim=options.frame_decim, + v_scale=options.v_scale, + t_scale=options.t_scale) + self.sink_count=0 + self.add_to_scope((self.multi.get_master_source_c(),1),options.show_q) + self.add_to_scope((self.multi.get_slave_source_c(),1),options.show_q) + if 4==options.nchan: + self.add_to_scope((self.multi.get_master_source_c(),2),options.show_q) + self.add_to_scope((self.multi.get_slave_source_c(),2),options.show_q) + + if options.show_counters: + self.add_to_scope((self.multi.get_master_source_c(),0),options.show_q) + self.add_to_scope((self.multi.get_slave_source_c(),0),options.show_q) + + self._build_gui(vbox) + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdevm.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdevm.freq_range() + options.freq = float(r[0]+r[1])/2 + + self.set_gain(options.gain) + + if self.show_debug_info: + self.myform['decim'].set_value(self.um.decim_rate()) + self.myform['fs@usb'].set_value(self.um.adc_freq() / self.um.decim_rate()) + self.myform['dbname'].set_value(self.subdevm.name()) + self.myform['baseband'].set_value(0) + self.myform['ddc'].set_value(0) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + self.multi.print_db_info() + self.unsynced=True + frame.Bind(wx.EVT_IDLE, self.onIdle) + + def add_to_scope(self,source_c,show_q): + c2f= gr.complex_to_float () + self.connect(source_c, c2f) + self.connect((c2f,0), (self.scope,self.sink_count)) + self.sink_count=self.sink_count+1 + if show_q: + self.connect((c2f,1), (self.scope,self.sink_count)) + self.sink_count=self.sink_count+1 + + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + vbox.Add(self.scope.win, 10, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0, 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0, 0) + g = self.subdevm.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + hbox.Add((5,0), 0, 0) + buttonSync = form.button_with_callback(parent=self.panel, label='sync',callback=self.sync_usrps) + hbox.Add(buttonSync,0,wx.EXPAND) + + hbox.Add((5,0), 0, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['decim'] = form.static_float_field( + parent=panel, sizer=hbox, label="Decim") + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + def set_freq(self, target_freq, sync=True): + """ + Set the center frequency we're interested in for all channels, + on all rx daughterboards on MASTER and SLAVE. + + @param target_freq: frequency in Hz + @param sync: sync the usrps after setting the freqs (this will clear any phase differences in the DDCS) + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + result,r1,r2,r3,r4 = self.multi.tune_all_rx(target_freq) + if sync: + self.sync_usrps() #sync master and slave and clear any DDC phase differences + if r1: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r1.baseband_freq) + self.myform['ddc'].set_value(r1.dxc_freq) + return result + + def set_freq_chan0(self, target_freq, sync=True): + """ + Set the center frequency we're interested in for rx chan 0 only on MASTER and SLAVE. + + @param target_freq: frequency in Hz + @param sync: sync the usrps after setting the freqs (this will clear any phase differences in the DDCS) + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + rm = usrp.tune(self.um, 0, self.subdevm, target_freq) + rs = usrp.tune(self.us, 0, self.subdevs, target_freq) + r=rm + if sync: + self.sync_usrps() #sync master and slave and clear any DDC phase differences + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + return True + + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.multi.set_gain_all_rx(gain) + + def set_gain_chan0(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdevm.set_gain(gain) + self.subdevs.set_gain(gain) + + def onIdle(self,evt): + if self.unsynced: + time.sleep(0.5) + self.unsynced=True + self.multi.sync() + self.unsynced=False + #print 'synced' + + def sync_usrps(self): + self.multi.sync() + +def main (): + app = stdgui.stdapp(app_flow_graph, "MULTI_USRP O'scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py b/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py new file mode 100755 index 00000000..6084aba3 --- /dev/null +++ b/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python + +""" +Read samples 2 from two linked synchronised USRP's and write to file formatted as binary +single-precision complex values. +Make sure you read README on how to link the two usrps + +""" + +from gnuradio import gr, eng_notation +from gnuradio import audio +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +import time +from gnuradio import usrp_multi + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set selfpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=0.0, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-n", "--nchan", type="intx", default=2, + help="set nchannels to NCHAN") + parser.add_option("-N", "--nsamples", type="eng_float", default=None, + help="number of samples to collect [default=+inf]") + parser.add_option ("-o", "--output-file-m", default="usrp_rx_m.dat", + help="write master data to FILE", metavar="FILE") + parser.add_option ("--output-file-m2", default="usrp_rx_m2.dat", + help="write master data from second channel to FILE", metavar="FILE") + parser.add_option ("-p", "--output-file-s", default="usrp_rx_s.dat", + help="write slave data to FILE", metavar="FILE") + parser.add_option ("--output-file-s2", default="usrp_rx_s2.dat", + help="write slave data from second channel to FILE", metavar="FILE") + parser.add_option("-x", "--master-serialno", type="string", default=None, + help="Serial_no of the usrp which should be the MASTER (default= select any)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + + # build the graph + self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, + nchan=options.nchan ) + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + + dst_m=gr.file_sink (gr.sizeof_gr_complex, options.output_file_m) + dst_s=gr.file_sink (gr.sizeof_gr_complex, options.output_file_s) + if options.nsamples is None: + self.connect((self.multi.get_master_source_c(),1),dst_m) + self.connect((self.multi.get_slave_source_c(),1),dst_s) + else: + head_m = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + head_s = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + self.connect((self.multi.get_master_source_c(),1),head_m,dst_m) + self.connect((self.multi.get_slave_source_c(),1),head_s,dst_s) + + if(4==options.nchan): + dst_m2=gr.file_sink (gr.sizeof_gr_complex, options.output_file_m2) + dst_s2=gr.file_sink (gr.sizeof_gr_complex, options.output_file_s2) + if options.nsamples is None: + self.connect((self.multi.get_master_source_c(),2),dst_m2) + self.connect((self.multi.get_slave_source_c(),2),dst_s2) + else: + head_m2 = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + head_s2 = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + self.connect((self.multi.get_master_source_c(),2),head_m2,dst_m2) + self.connect((self.multi.get_slave_source_c(),2),head_s2,dst_s2) + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = usrp.pick_rx_subdevice(self.um) + + if (options.nchan!=4): + mux=usrp.determine_rx_mux_value(self.um, options.rx_subdev_spec) + mux= (mux<<8 & 0xffffffff) | (mux & 0xff) + self.um.set_mux(mux) + self.us.set_mux(mux) + + # determine the daughterboard subdevice we're using + self.subdevm = usrp.selected_subdev(self.um, options.rx_subdev_spec) + self.subdevs = usrp.selected_subdev(self.us, options.rx_subdev_spec) + print "Using MASTER RX d'board %s" % (self.subdevm.side_and_name(),) + print "Using SLAVE RX d'board %s" % (self.subdevs.side_and_name(),) + input_rate = self.um.adc_freq() / self.um.decim_rate() + print "USB sample rate %s" % (eng_notation.num_to_str(input_rate)) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdevm.gain_range() + options.gain = float(g[0]+g[1])/2 + + self.multi.set_gain_all_rx(options.gain) + result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq) + if not result: + sys.stderr.write('Failed to set frequency\n') + raise SystemExit, 1 + + def sync_usrps(self): + self.multi.sync() + + +if __name__ == '__main__': + fg=my_graph() + fg.start() + #time.sleep(0.5) + fg.sync_usrps() + raw_input ('Press Enter to quit: ') + fg.stop() + #try: + # fg.start() + # fg.sync_usrps() + #except KeyboardInterrupt: + # pass diff --git a/gnuradio-examples/python/networking/measurement_slave.py b/gnuradio-examples/python/networking/measurement_slave.py new file mode 100755 index 00000000..2bc7c39c --- /dev/null +++ b/gnuradio-examples/python/networking/measurement_slave.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import struct +import socket +import asyncore +import sys +import optparse +import random +from gnuradio.eng_option import eng_option +import gnuradio.gr.gr_threading as _threading + +LOOP_TIMEOUT = 0.001 +BROADCAST_ADDR = '255.255.255.255' + +BROADCAST_PORT = 27010 # UDP +CONTROL_PORT = 27011 # TCP + +PKT_HEADER_SIZE = 4 # 32-bit int + +logfile = None + +def unpack_header(s): + (len,) = struct.unpack('!i', s) + return (len,) + +def pack_header(len): + return struct.pack('!i', len) + + +class control_port_listener(asyncore.dispatcher): + def __init__(self, port=CONTROL_PORT, udp_socket=None, verbose=False): + """ + @param port: TCP port to listen on. + @type port: int + """ + asyncore.dispatcher.__init__(self) + + self._verbose = verbose + self._udp_socket = udp_socket + + host = '' # symbolic name for localhost + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + + try: + self.bind((host, port)) + except socket.error, err: + sys.stderr.write('Failed to bind to %s: %s\n' % + ((host, port), os.strerror (err.args[0]),)) + sys.exit(1) + + self.listen(3) + + def handle_accept(self): + socket, addr = self.accept() + sys.stderr.write("handle_accept: %r\n" % (addr,)) + if not(socket is None): + # instantiate a server + s = control_server(socket, addr, self._udp_socket, self._verbose) + + +class gr_dispatcher(asyncore.dispatcher): + def __init__(self, sock=None, map=None): + asyncore.dispatcher.__init__(self, sock=sock, map=map) + + def read_packet(self): + """ + Returns None or packet + """ + s = self.recvall(PKT_HEADER_SIZE) + if s == '': + return None + + (payload_len,) = unpack_header(s) + + payload_len = int(payload_len) + + if payload_len == 0: + payload = '' + else: + payload = self.recvall(payload_len) + if len(payload) != payload_len: + sys.stderr.write ('short recv, expected %d bytes, got %d\n' % ( + payload_len, len(payload))) + raise RuntimeError, "short recv" + + return payload + + def recvall(self, buffer_size): + result = '' + while len(result) < buffer_size: + data = self.recv(buffer_size - len(result)) + if not data: + return '' + result += data + return result + + +class pkt_receiver_thread(_threading.Thread): + def __init__(self, socket): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.socket = socket + self.keep_running = True + self.start() + + def run(self): + while self.keep_running: + pkt, sender = self.socket.recvfrom(10000) + if pkt: + if len(pkt) > 2: + t = struct.unpack('!H', pkt[0:2]) + seqno = t[0] + else: + seqno = -1 + + logfile.write('RCVD seqno %4d len %4d from %s\n' % (seqno, len(pkt), sender)) + logfile.flush() + + +class control_server(gr_dispatcher): + def __init__(self, socket, addr, udp_socket, verbose=False): + gr_dispatcher.__init__(self, sock=socket) + + self._udp_socket = udp_socket + self.verbose = verbose + self.setblocking(1) + + def writable(self): + return False + + def handle_read(self): + pkt = self.read_packet() + if pkt: + annotate = 'ANNOTATE' + if pkt.startswith(annotate): + logfile.write(pkt[len(annotate)+1:]) + logfile.write('\n') + logfile.flush() + elif pkt.startswith('SEND'): + tokens = pkt.split() + if len(tokens) < 4: + invalid_packet(pkt) + else: + npkts = int(tokens[1]) + size = int(tokens[2]) + power = float(tokens[3]) + send_test_packets(self._udp_socket, npkts, size, power) + else: + invalid_packet(pkt) + + def handle_close(self): + self.close() + + +def invalid_packet(pkt): + sys.stderr.write('received unrecognized packet: %s\n' % (pkt,)) + + +def make_random_payload(size): + p = [0] * size + if 1: + for i in range(size): + p[i] = chr(random.randint(0, 255)) + else: + for i in range(size): + p[i] = chr(i % 256) + return ''.join(p) + + +def send_test_packets(udp_socket, npkts, size, power): + # we ignore power for now... + size = max(2, size) + payload = make_random_payload(size - 2) + for n in range(npkts): + pkt = struct.pack('!H', n) + payload + udp_socket.sendto(pkt, (BROADCAST_ADDR, BROADCAST_PORT)) + #udp_socket.sendall(pkt) + + +def open_udp_broadcast_socket(gr0_host_ip, port): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +# s.bind((gr0_host_ip, port)) + s.bind(('', port)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) +# s.connect((BROADCAST_ADDR, port)) + return s + + +def main(): + global logfile + + usage = 'usage: %prog [options] gr0-ip-addr' + parser = optparse.OptionParser (option_class=eng_option, usage=usage) + parser.add_option('-l', '--logfile', type='string', default=None, + help="specify log file name [default=]") + parser.add_option('-v', '--verbose', action="store_true", default=False, + help="enable verbose diagnostics") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + sys.exit(1) + + gr0_ip_addr = args[0] + if options.logfile is None: + logfile = sys.stdout + else: + logfile = file(options.logfile, 'w') + + udp_socket = open_udp_broadcast_socket(gr0_ip_addr, BROADCAST_PORT) + R = pkt_receiver_thread(udp_socket) + L = control_port_listener(CONTROL_PORT, udp_socket=udp_socket, verbose=options.verbose) + asyncore.loop(LOOP_TIMEOUT) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/Makefile.am b/gnuradio-examples/python/usrp/Makefile.am new file mode 100644 index 00000000..32442d5c --- /dev/null +++ b/gnuradio-examples/python/usrp/Makefile.am @@ -0,0 +1,52 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + am_rcv.py \ + ayfabtu.py \ + benchmark_usb.py \ + fm_tx4.py \ + fsk_loopback.py \ + fsk_rx.py \ + fsk_tx.py \ + max_power.py \ + test_counting.py \ + test_dft_analysis.py \ + test_dft_synth.py \ + test_digital_loopback_counting.py \ + test_digital_loopback_lfsr.py \ + tvrx_am_rcv_gui.py \ + tvrx_tv_rcv.py \ + usrp_fft.py \ + usrp_fft_old.py \ + usrp_nbfm_ptt.py \ + usrp_nbfm_rcv.py \ + usrp_oscope.py \ + usrp_rx_cfile.py \ + usrp_rx_file.py \ + usrp_rx_nogui.py \ + usrp_siggen.py \ + usrp_wfm_rcv.py \ + usrp_wfm_rcv_nogui.py \ + usrp_wfm_rcv2_nogui.py \ + usrp_wfm_rcv_pll.py \ + usrp_wxapt_rcv.py \ + wfm_rcv_file.py diff --git a/gnuradio-examples/python/usrp/am_rcv.py b/gnuradio-examples/python/usrp/am_rcv.py new file mode 100755 index 00000000..2908dcbf --- /dev/null +++ b/gnuradio-examples/python/usrp/am_rcv.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from gnuradio import gr, eng_notation +from gnuradio import audio +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + +from gnuradio.wxgui import stdgui, fftsink +import wx + +class am_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + station = parseargs(argv[1:]) + offset_freq = 30e3 + IF_freq = offset_freq - station + + adc_rate = 64e6 + usrp_decim = 250 + if_rate = adc_rate / usrp_decim # 256 kHz + if_decim = 4 + demod_rate = if_rate / if_decim # 64 kHz + audio_decimation = 2 + audio_rate = demod_rate / audio_decimation # 16 kHz + + # usrp is data source + src = usrp.source_c (0, usrp_decim) + src.set_rx_freq (0, IF_freq) + actual_IF_freq =src.rx_freq(0) + actual_offset = actual_IF_freq + station + + #print actual_IF_freq + #print actual_offset + + src.set_pga(0,20) + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + if_rate, # sampling rate + 9e3, # low pass cutoff freq + 10e3, # width of trans. band + gr.firdes.WIN_HANN) + + ddc = gr.freq_xlating_fir_filter_ccf (if_decim,channel_coeffs,-actual_offset,if_rate) + + magblock = gr.complex_to_mag() + volumecontrol = gr.multiply_const_ff(.003) + + # Deemphasis. Is this necessary on AM? + TAU = 75e-6 # 75us in US, 50us in EUR + fftaps = [ 1 - math.exp(-1/TAU/if_rate), 0] + fbtaps= [ 0 , math.exp(-1/TAU/if_rate) ] + + deemph = gr.iir_filter_ffd(fftaps,fbtaps) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 8 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + if_rate, # sampling rate + 9e3, #audio_rate/2 - width_of_transition_band, + 4e3, # width_of_transition_band, + gr.firdes.WIN_HANN) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + + + + print len(channel_coeffs) + print len(audio_coeffs) + + # now wire it all together + self.connect (src, ddc) + self.connect (ddc, magblock) + self.connect (magblock, volumecontrol) + self.connect (volumecontrol,deemph) + self.connect (deemph,audio_filter) + self.connect (audio_filter, (audio_sink, 0)) + + if 1: + pre_demod = fftsink.fft_sink_c (self, panel, title="Pre-Demodulation", fft_size=128, sample_rate=if_rate) + self.connect (src, pre_demod) + vbox.Add (pre_demod.win, 1, wx.EXPAND) + + if 0: + post_demod = fftsink.fft_sink_c (self, panel, title="Post Demodulation", fft_size=256, sample_rate=demod_rate) + self.connect (ddc, post_demod) + vbox.Add (post_demod.win, 1, wx.EXPAND) + + if 0: + post_filt = fftsink.fft_sink_f (self, panel, title="Post Filter", fft_size=512, sample_rate=audio_rate) + self.connect (magblock,post_filt) + vbox.Add (post_filt.win, 1, wx.EXPAND) + +def parseargs (args): + nargs = len (args) + if nargs == 1: + freq1 = float (args[0]) * 1e3 + else: + sys.stderr.write ('usage: am_rcv freq1\n') + sys.exit (1) + + return freq1 + +if __name__ == '__main__': + app = stdgui.stdapp (am_rx_graph, "AM RX") + app.MainLoop () + diff --git a/gnuradio-examples/python/usrp/ayfabtu.dat b/gnuradio-examples/python/usrp/ayfabtu.dat new file mode 100644 index 00000000..5c65cf48 Binary files /dev/null and b/gnuradio-examples/python/usrp/ayfabtu.dat differ diff --git a/gnuradio-examples/python/usrp/ayfabtu.py b/gnuradio-examples/python/usrp/ayfabtu.py new file mode 100755 index 00000000..7647e93b --- /dev/null +++ b/gnuradio-examples/python/usrp/ayfabtu.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# +# All Your Frequencies are Belong to Us! +# +# Transmit NBFM message on 25 channels simultaneously! +# + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio import audio +from gnuradio import blks +from gnuradio import optfir +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import math +import sys +import random + +from gnuradio.wxgui import stdgui, fftsink +import wx + + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.gauss(0, 1),random.gauss(0, 1))) + + return tuple(result) + +def random_noise_c(): + src = gr.vector_source_c(make_random_complex_tuple(32*1024), True) + return src + + +def plot_taps(taps, sample_rate=2): + return gru.gnuplot_freqz (gru.freqz (taps, 1), sample_rate) + + +class ayfabtu_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + parser = OptionParser (option_class=eng_option) + parser.add_option ("-c", "--duc-freq", type="eng_float", default=29.325e6, + help="set Tx ddc frequency to FREQ", metavar="FREQ") + (options, args) = parser.parse_args () + + nchan = 25 + IF_GAIN = 80000 + AUDIO_GAIN = 100 + + self.dac_rate = 128e6 + self.usrp_interp = 256 + self.usrp_rate = self.dac_rate / self.usrp_interp # 500 kS/s + self.audio_rate = 32000 # 32 kS/s + + self.audio_src = gr.file_source(gr.sizeof_float, "ayfabtu.dat", True) + + ahp_taps = gr.firdes.high_pass(1, # gain + 32e3, # Fs + 300, # cutoff + 600, # trans width + gr.firdes.WIN_HANN) + self.audio_hp = gr.fir_filter_fff(1, ahp_taps) + + self.audio_gain = gr.multiply_const_ff(AUDIO_GAIN) + + null_src = gr.null_source(gr.sizeof_gr_complex) + #noise_src = gr.noise_source_c(gr.GR_UNIFORM, 1, 0) + noise_src = random_noise_c() + + if 0: + artaps = optfir.low_pass(1, # gain + 2, # Fs + .75/32, # freq1 + 1.0/32, # freq2 + 1, # pb ripple in dB + 50, # stopband atten in dB + 2) # + extra taps + else: + artaps = gr.firdes.low_pass(1, # gain + 32e3*15,# Fs + 2.7e3, # cutoff + .3e3, # trans width + gr.firdes.WIN_HANN) + print "len(artaps) =", len(artaps) + self.audio_resampler = blks.rational_resampler_fff(self, 15, 32, artaps) + + self.fm_mod = blks.nbfm_tx(self, 15000, 15000, max_dev=4.5e3) + + + fbtaps = gr.firdes.low_pass(1, # gain + 25*15e3, # rate + 13e3, # cutoff + 2e3, # trans width + gr.firdes.WIN_HANN) + print "len(fbtabs) =", len(fbtaps) + #self.plot = plot_taps(fbtaps, 25*15e3) + self.filter_bank = blks.synthesis_filterbank(self, nchan, fbtaps) + + self.if_gain = gr.multiply_const_cc(IF_GAIN) + + if 0: + ifrtaps = optfir.low_pass(1, + 2, # Fs + .75/3, # freq1 + 1.0/3, # freq2 + 1, # pb ripple in dB + 50, # stopband atten in dB + 2) # + extra taps + else: + ifrtaps = gr.firdes.low_pass(1, + 2, # Fs + .75/3, # freq1 + .25/3, # trans width + gr.firdes.WIN_HANN) + + + print "len(ifrtaps) =", len(ifrtaps) + self.if_resampler = blks.rational_resampler_ccf(self, 4, 3, ifrtaps) + + + self.u = usrp.sink_c(0, 256) + self.u.set_tx_freq(0, options.duc_freq) + self.u.set_pga(0, self.u.pga_max()) + + # wire it all together + + self.connect(self.audio_src, self.audio_hp, self.audio_gain, + self.audio_resampler, self.fm_mod) + + null_sink = gr.null_sink(gr.sizeof_gr_complex) + + for i in range(nchan): + if True or i == 0: + self.connect(self.fm_mod, (self.filter_bank, i)) + else: + self.connect(null_src, (self.filter_bank, i)) + + self.connect(self.filter_bank, self.if_gain, self.if_resampler, self.u) + + +def main (): + app = stdgui.stdapp (ayfabtu_graph, "All Your Frequency Are Belong to Us") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/benchmark_usb.py b/gnuradio-examples/python/usrp/benchmark_usb.py new file mode 100755 index 00000000..8418f506 --- /dev/null +++ b/gnuradio-examples/python/usrp/benchmark_usb.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Benchmark the USB/USRP throughput. Finds the maximum full-duplex speed +the USRP/USB combination can sustain without errors. + +This program does not currently give reliable results. Sorry about that... +""" + +from gnuradio import gr +from gnuradio import usrp +from gnuradio import eng_notation + +import sys + +def run_test (usb_throughput, verbose): + # usb_throughput is in bytes/sec. + # + # Returns True or False + + nsec = 1 + stream_length = int (usb_throughput/2 * nsec) # length of stream to examine + + adc_freq = 64e6 + dac_freq = 128e6 + sizeof_sample = 2 * gr.sizeof_short + + usb_throughput_in_samples = usb_throughput / sizeof_sample + + # allocate usb throughput 50/50 between Tx and Rx + + tx_interp = int (dac_freq) / int (usb_throughput_in_samples / 2) + rx_decim = int (adc_freq) / int (usb_throughput_in_samples / 2) + + # print "tx_interp =", tx_interp, "rx_decim =", rx_decim + assert (tx_interp == 2 * rx_decim) + + fg = gr.flow_graph () + + # Build the Tx pipeline + data_src = gr.lfsr_32k_source_s () + src_head = gr.head (gr.sizeof_short, int (stream_length * 2)) + usrp_tx = usrp.sink_s (0, tx_interp) + fg.connect (data_src, src_head, usrp_tx) + + # and the Rx pipeline + usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK) + head = gr.head (gr.sizeof_short, stream_length) + check = gr.check_lfsr_32k_s () + fg.connect (usrp_rx, head, check) + + fg.run () + + ntotal = check.ntotal () + nright = check.nright () + runlength = check.runlength () + + if verbose: + print "usb_throughput =", eng_notation.num_to_str (usb_throughput) + print "ntotal =", ntotal + print "nright =", nright + print "runlength =", runlength + print "delta =", ntotal - runlength + + return runlength >= stream_length - 80000 + +def main (): + verbose = True + best_rate = 0 + usb_rate = [ 2e6, 4e6, 8e6, 16e6, 32e6 ] + #usb_rate = [ 32e6, 32e6, 32e6, 32e6, 32e6 ] + # usb_rate.reverse () + for rate in usb_rate: + sys.stdout.write ("Testing %sB/sec... " % (eng_notation.num_to_str (rate))) + sys.stdout.flush () + ok = run_test (rate, verbose) + if ok: + best_rate = max (best_rate, rate) + sys.stdout.write ("OK\n") + else: + sys.stdout.write ("FAILED\n") + + print "Max USB/USRP throughput = %sB/sec" % (eng_notation.num_to_str (best_rate),) + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/dsb_tx.py b/gnuradio-examples/python/usrp/dsb_tx.py new file mode 100755 index 00000000..df65761c --- /dev/null +++ b/gnuradio-examples/python/usrp/dsb_tx.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +from gnuradio import gr, eng_notation +from gnuradio import usrp +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + + +def build_graph (cordic_freq): + + audio_rate = 32000 + sw_interp = 4 + usrp_interp = 1000 + audio_file = "/home/eb/demo/testing-audio.dat" + + fg = gr.flow_graph () + + src = gr.file_source (gr.sizeof_float, audio_file, True) + gain = gr.multiply_const_ff (10000) + + interp = gr.interp_fir_filter_fff (sw_interp, (1, 1, 1, 1)) + + f2c = gr.float_to_complex () + + u = usrp.sink_c (0, usrp_interp) + u.set_tx_freq (0, cordic_freq) + + fg.connect (src, gain) + fg.connect (gain, interp) + fg.connect (interp, (f2c, 0)) + fg.connect (interp, (f2c, 1)) + fg.connect (f2c, u) + + return fg + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option ("-c", "--cordic-freq", type="eng_float", default=10e6, + help="set Tx cordic frequency to FREQ", metavar="FREQ") + (options, args) = parser.parse_args () + + print "cordic_freq = %s" % (eng_notation.num_to_str (options.cordic_freq)) + fg = build_graph (options.cordic_freq) + + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/flexrf_debug.py b/gnuradio-examples/python/usrp/flexrf_debug.py new file mode 100755 index 00000000..70c63096 --- /dev/null +++ b/gnuradio-examples/python/usrp/flexrf_debug.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink, scopesink, slider +from optparse import OptionParser +import wx + +class app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + parser.add_option ("-d", "--decim", type="int", default=8, + help="set fgpa decimation rate to DECIM") + parser.add_option ("-c", "--ddc-freq", type="eng_float", default=0, + help="set Digital downconverter frequency to FREQ", metavar="FREQ") + parser.add_option ("-f", "--freq", type="eng_float", default=950e6, + help="set RF downconverter frequency to FREQ", metavar="FREQ") + parser.add_option ("-m", "--mux", type="intx", default=0x32103210, + help="set fpga FR_RX_MUX register to MUX") + parser.add_option ("-g", "--gain", type="eng_float", default=0, + help="set Rx PGA gain in dB (default 0 dB)") + (options, args) = parser.parse_args () + + self.u = usrp.source_c (0, options.decim, 1, gru.hexint(options.mux), 0) + + self.u.set_verbose (0) + + input_rate = self.u.adc_freq () / self.u.decim_rate () + + block = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate) + self.connect (self.u, block) + vbox.Add (block.win, 10, wx.EXPAND) + + if 0: + c2f_1 = gr.complex_to_float () + scope = scopesink.scope_sink_f (self, panel, "Rx Data", input_rate) + vbox.Add (scope.win, 6, wx.EXPAND) + + self.connect (self.u,c2f_1) + self.connect ((c2f_1, 0), (scope, 0)) + self.connect ((c2f_1, 1), (scope, 1)) + + if 0: + rms_complex = gr.rms_cf(.0001) + rms_i = gr.rms_ff(.0001) + rms_q = gr.rms_ff(.0001) + + self.connect(self.u,rms_complex) + self.connect((c2f_1,0),rms_i) + self.connect((c2f_1,1),rms_q) + + ns1 = gr.null_sink(4) + ns2 = gr.null_sink(4) + ns3 = gr.null_sink(4) + + self.connect(rms_complex,ns1) + self.connect(rms_i,ns2) + self.connect(rms_q,ns3) + + # sliders + + #vbox.Add(slider.slider(panel, 0, 104, self.set_gain), 1, wx.ALIGN_CENTER) + + #vbox.Add(slider.slider(panel, 0, 4095, self.set_gain_gc1), 1, wx.ALIGN_CENTER) + #vbox.Add(slider.slider(panel, 0, 31, self.set_gain_gc2), 1, wx.ALIGN_CENTER) + #vbox.Add(slider.slider(panel, 0, 1, self.set_gain_dl), 1, wx.ALIGN_CENTER) + #vbox.Add(slider.slider(panel, 0, 200, self.set_gain_i), 1, wx.ALIGN_CENTER) + #vbox.Add(slider.slider(panel, 0, 200, self.set_gain_q), 1, wx.ALIGN_CENTER) + + self.offset = 0 + #vbox.Add(slider.slider(panel, -200, 200, self.set_offset_i), 1, wx.ALIGN_CENTER) + #vbox.Add(slider.slider(panel, -200, 200, self.set_offset_q), 1, wx.ALIGN_CENTER) + + vbox.Add(slider.slider(panel, 380, 480, self.set_rf_freq), 1, wx.EXPAND|wx.ALIGN_CENTER) + vbox.Add(slider.slider(panel, -32000, +32000, self.set_if_freq), 1, wx.EXPAND|wx.ALIGN_CENTER) + vbox.Add(slider.slider(panel, 0, 4095, self.set_gain), 1, wx.EXPAND|wx.ALIGN_CENTER) + + # build small control area at bottom + hbox = wx.BoxSizer (wx.HORIZONTAL) + hbox.Add ((1, 1), 1, wx.EXPAND) + hbox.Add (wx.StaticText (panel, -1, "Set ddc freq: "), 0, wx.ALIGN_CENTER) + self.tc_freq = wx.TextCtrl (panel, -1, "", style=wx.TE_PROCESS_ENTER) + hbox.Add (self.tc_freq, 0, wx.ALIGN_CENTER) + wx.EVT_TEXT_ENTER (self.tc_freq, self.tc_freq.GetId(), self.handle_text_enter) + hbox.Add ((1, 1), 1, wx.EXPAND) + # add it to the main vbox + vbox.Add (hbox, 0, wx.EXPAND) + + self.update_status_bar () + + def set_rf_freq (self,freq): + (success,actual_freq) = self.set_freq(1e6*freq) + if not success: + print "Failed on ",freq + def set_if_freq (self,freq): + self.u.set_rx_freq(0,freq*1e3) + + def set_gain (self,gain): + self.rfrx.set_gain(gain) + + def set_gain_i (self,gain): + self.u.set_pga(0,gain/10.0) + def set_gain_q (self,gain): + self.u.set_pga(1,gain/10.0) + + def set_offset_i(self,offset): + self.offset = (self.offset & 0x0000ffff) | ((offset&0xffff)<<16) + self.u._write_fpga_reg (3,self.offset) + + def set_offset_q(self,offset): + self.offset = (self.offset & 0xffff0000) | (offset&0xffff) + self.u._write_fpga_reg (3,self.offset) + + def handle_text_enter (self, event): + str = event.GetString () + self.tc_freq.Clear () + self.u.set_rx_freq (0, eng_notation.str_to_num (str)) + self.update_status_bar () + + def update_status_bar (self): + ddc_freq = self.u.rx_freq (0) + decim_rate = self.u.decim_rate () + sample_rate = self.u.adc_freq () / decim_rate + msg = "decim: %d %sS/s DDC: %s" % ( + decim_rate, + eng_notation.num_to_str (sample_rate), + eng_notation.num_to_str (ddc_freq)) + + self.frame.GetStatusBar().SetStatusText (msg, 1) + + def set_gain(self,gain): + assert gain>=0 and gain<4096 + self.u.write_aux_dac(0,0,int(gain)) + +def main (): + app = stdgui.stdapp (app_flow_graph, "USRP FFT") + app.MainLoop () + +if __name__ == '__main__': + main () + + diff --git a/gnuradio-examples/python/usrp/flexrf_siggen.py b/gnuradio-examples/python/usrp/flexrf_siggen.py new file mode 100755 index 00000000..6a59148b --- /dev/null +++ b/gnuradio-examples/python/usrp/flexrf_siggen.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +from gnuradio.wxgui import stdgui, slider +import wx + +class flex_siggen (stdgui.gui_flow_graph): + __slots__ = ['interp', 'waveform_type', 'waveform_ampl', + 'waveform_freq', 'waveform_offset', 'fg', 'usrp', + 'siggen', 'noisegen', 'src', 'file_sink' ] + + def __init__ (self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + parser.add_option ("-a", "--amplitude", type="int", default=32000, + help="amplitude") + parser.add_option ("-i", "--interp", type="int", default=64, + help="set fpga interpolation rate to INTERP") + parser.add_option ("-n", "--nchannels", type="int", default=1, + help="set number of output channels to NCHANNELS") + (options, args) = parser.parse_args () + + self.waveform_type = gr.GR_CONST_WAVE + self.waveform_ampl = options.amplitude + self.waveform_freq = 100.12345e3 + self.waveform_offset = 0 + + self.interp = options.interp + self._instantiate_blocks () + self.usrp.set_nchannels (options.nchannels) + + self.dboard=self.usrp.db[0][0] + + self.set_waveform_type (self.waveform_type) + vbox.Add(slider.slider(panel, 390, 510, self.set_rf_freq), 1, wx.EXPAND|wx.ALIGN_CENTER) + vbox.Add(slider.slider(panel, -45000, +45000, self.set_if_freq), 1, wx.EXPAND|wx.ALIGN_CENTER) + #vbox.Add(slider.slider(panel, 0, 4095, self.set_gain), 1, wx.EXPAND|wx.ALIGN_CENTER) + + def usb_freq (self): + return self.usrp.dac_freq() / self.interp + + def usb_throughput (self): + return self.usb_freq () * 4 + + def set_waveform_type (self, type): + ''' + valid waveform types are: gr.GR_SIN_WAVE, gr.GR_CONST_WAVE, + gr.GR_UNIFORM and gr.GR_GAUSSIAN + ''' + self._configure_graph (type) + self.waveform_type = type + + def set_waveform_ampl (self, ampl): + self.waveform_ampl = ampl + self.siggen.set_amplitude (ampl) + self.noisegen.set_amplitude (ampl) + + def set_waveform_freq (self, freq): + self.waveform_freq = freq + self.siggen.set_frequency (freq) + + def set_if_freq (self, freq): + self.if_freq = freq + self.usrp.set_tx_freq (0,freq*1e3) + + def set_rf_freq (self, freq): + self.rf_freq = freq + (success,actual_freq) = self.dboard.set_freq (freq*1e6) + if not success: + print "Failed on ", freq + + def set_waveform_offset (self, offset): + self.waveform_offset = offset + self.siggen.set_offset (offset) + + def set_interpolator (self, interp): + self.interp = interp + self.siggen.set_sampling_freq (self.usb_freq ()) + self.usrp.set_interp_rate (interp) + + def set_duc_freq (self, freq): + self.usrp.set_tx_freq (0, freq) + + def _instantiate_blocks (self): + self.src = None + self.usrp = usrp.sink_c (0, self.interp) + + self.siggen = gr.sig_source_c (self.usb_freq (), + gr.GR_SIN_WAVE, + self.waveform_freq, + self.waveform_ampl, + self.waveform_offset) + + self.noisegen = gr.noise_source_c (gr.GR_UNIFORM, + self.waveform_ampl) + print "done" + + def _configure_graph (self, type): + was_running = self.is_running () + if was_running: + self.stop () + self.disconnect_all () + if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE: + self.connect (self.siggen, self.usrp) + self.siggen.set_waveform (type) + self.src = self.siggen + elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN: + self.connect (self.noisegen, self.usrp) + self.noisegen.set_type (type) + self.src = self.noisegen + else: + raise ValueError, type + if was_running: + self.start () + + +if __name__ == '__main__': + parser = OptionParser (option_class=eng_option) + parser.add_option ("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE, + help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE) + parser.add_option ("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, + help="generate a constant output") + parser.add_option ("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN, + help="generate Gaussian random output") + parser.add_option ("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM, + help="generate Uniform random output") + parser.add_option ("-f", "--freq", type="eng_float", default=100e3, + help="set waveform frequency to FREQ") + parser.add_option ("-r", "--rf-freq", type="eng_float", default=910e6, + help="set waveform frequency to FREQ") + parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3, + help="set waveform amplitude to AMPLITUDE", metavar="AMPL") + parser.add_option ("-o", "--offset", type="eng_float", default=0, + help="set waveform offset to OFFSET") + parser.add_option ("-c", "--duc-freq", type="eng_float", default=0, + help="set Tx DUC frequency to FREQ", metavar="FREQ") + parser.add_option ("-m", "--mux", type="intx", default=0x98, + help="set output mux register") + + app = stdgui.stdapp (flex_siggen, "USRP FlexRF Siggen") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/fm_tx4.py b/gnuradio-examples/python/usrp/fm_tx4.py new file mode 100755 index 00000000..a9201b3f --- /dev/null +++ b/gnuradio-examples/python/usrp/fm_tx4.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +""" +Transmit N simultaneous narrow band FM signals. + +They will be centered at the frequency specified on the command line, +and will spaced at 25kHz steps from there. + +The program opens N files with names audio-N.dat where N is in [0,7]. +These files should contain floating point audio samples in the range [-1,1] +sampled at 32kS/sec. You can create files like this using +audio_to_file.py +""" + +from gnuradio import gr, eng_notation +from gnuradio import usrp +from gnuradio import audio +from gnuradio import blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import usrp_dbid +import math +import sys + +from gnuradio.wxgui import stdgui, fftsink +from gnuradio import tx_debug_gui +import wx + + +######################################################## +# instantiate one transmit chain for each call + +class pipeline(gr.hier_block): + def __init__(self, fg, filename, lo_freq, audio_rate, if_rate): + + src = gr.file_source (gr.sizeof_float, filename, True) + fmtx = blks.nbfm_tx (fg, audio_rate, if_rate, + max_dev=5e3, tau=75e-6) + + # Local oscillator + lo = gr.sig_source_c (if_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + lo_freq, #frequency + 1.0, # amplitude + 0) # DC Offset + mixer = gr.multiply_cc () + + fg.connect (src, fmtx, (mixer, 0)) + fg.connect (lo, (mixer, 1)) + + gr.hier_block.__init__(self, fg, src, mixer) + + + +class fm_tx_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + MAX_CHANNELS = 7 + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set Tx frequency to FREQ [required]", metavar="FREQ") + parser.add_option("-n", "--nchannels", type="int", default=4, + help="number of Tx channels [1,4]") + parser.add_option("","--debug", action="store_true", default=False, + help="Launch Tx debugger") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.nchannels < 1 or options.nchannels > MAX_CHANNELS: + sys.stderr.write ("fm_tx4: nchannels out of range. Must be in [1,%d]\n" % MAX_CHANNELS) + sys.exit(1) + + if options.freq is None: + sys.stderr.write("fm_tx4: must specify frequency with -f FREQ\n") + parser.print_help() + sys.exit(1) + + # ---------------------------------------------------------------- + # Set up constants and parameters + + self.u = usrp.sink_c () # the USRP sink (consumes samples) + + self.dac_rate = self.u.dac_rate() # 128 MS/s + self.usrp_interp = 400 + self.u.set_interp_rate(self.usrp_interp) + self.usrp_rate = self.dac_rate / self.usrp_interp # 320 kS/s + self.sw_interp = 10 + self.audio_rate = self.usrp_rate / self.sw_interp # 32 kS/s + + # determine the daughterboard subdevice we're using + if options.tx_subdev_spec is None: + options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u) + + m = usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec) + #print "mux = %#04x" % (m,) + self.u.set_mux(m) + self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec) + print "Using TX d'board %s" % (self.subdev.side_and_name(),) + + self.subdev.set_gain(self.subdev.gain_range()[1]) # set max Tx gain + self.set_freq(options.freq) + self.subdev.set_enable(True) # enable transmitter + + sum = gr.add_cc () + + # Instantiate N NBFM channels + step = 25e3 + offset = (0 * step, 1 * step, -1 * step, 2 * step, -2 * step, 3 * step, -3 * step) + for i in range (options.nchannels): + t = pipeline (self, "audio-%d.dat" % (i % 4), offset[i], + self.audio_rate, self.usrp_rate) + self.connect (t, (sum, i)) + + gain = gr.multiply_const_cc (4000.0 / options.nchannels) + + # connect it all + self.connect (sum, gain) + self.connect (gain, self.u) + + # plot an FFT to verify we are sending what we want + if 1: + post_mod = fftsink.fft_sink_c(self, panel, title="Post Modulation", + fft_size=512, sample_rate=self.usrp_rate, + y_per_div=20, ref_level=40) + self.connect (sum, post_mod) + vbox.Add (post_mod.win, 1, wx.EXPAND) + + + if options.debug: + self.debugger = tx_debug_gui.tx_debug_gui(self.subdev) + self.debugger.Show(True) + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. Finally, we feed + any residual_freq to the s/w freq translater. + """ + + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq) + print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq) + print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq) + print "r.inverted =", r.inverted + + # Could use residual_freq in s/w freq translator + return True + + return False + +def main (): + app = stdgui.stdapp (fm_tx_graph, "Multichannel FM Tx") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py b/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py new file mode 100755 index 00000000..1cb16101 --- /dev/null +++ b/gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python + +""" +Transmit 2 signals, one out each daughterboard. + +Outputs SSB (USB) signals on side A and side B at frequencies +specified on command line. + +Side A is 600 Hz tone. +Side B is 350 + 440 Hz tones. +""" + +from gnuradio import gr +from gnuradio.eng_notation import num_to_str, str_to_num +from gnuradio import usrp +from gnuradio import audio +from gnuradio import blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import usrp_dbid +import math +import sys + + +class example_signal_0(gr.hier_block): + """ + Sinusoid at 600 Hz. + """ + def __init__(self, fg, sample_rate): + + src = gr.sig_source_c (sample_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + 600, # frequency + 1.0, # amplitude + 0) # DC Offset + + gr.hier_block.__init__(self, fg, None, src) + + +class example_signal_1(gr.hier_block): + """ + North American dial tone (350 + 440 Hz). + """ + def __init__(self, fg, sample_rate): + + src0 = gr.sig_source_c (sample_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + 350, # frequency + 1.0, # amplitude + 0) # DC Offset + + src1 = gr.sig_source_c (sample_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + 440, # frequency + 1.0, # amplitude + 0) # DC Offset + sum = gr.add_cc() + fg.connect(src0, (sum, 0)) + fg.connect(src1, (sum, 1)) + + gr.hier_block.__init__(self, fg, None, sum) + + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__ (self) + + usage="%prog: [options] side-A-tx-freq side-B-tx-freq" + parser = OptionParser (option_class=eng_option, usage=usage) + (options, args) = parser.parse_args () + + if len(args) != 2: + parser.print_help() + raise SystemExit + else: + freq0 = str_to_num(args[0]) + freq1 = str_to_num(args[1]) + + # ---------------------------------------------------------------- + # Set up USRP to transmit on both daughterboards + + self.u = usrp.sink_c(nchan=2) # say we want two channels + + self.dac_rate = self.u.dac_rate() # 128 MS/s + self.usrp_interp = 400 + self.u.set_interp_rate(self.usrp_interp) + self.usrp_rate = self.dac_rate / self.usrp_interp # 320 kS/s + + # we're using both daughterboard slots, thus subdev is a 2-tuple + self.subdev = (self.u.db[0][0], self.u.db[1][0]) + print "Using TX d'board %s" % (self.subdev[0].side_and_name(),) + print "Using TX d'board %s" % (self.subdev[1].side_and_name(),) + + # set up the Tx mux so that + # channel 0 goes to Slot A I&Q and channel 1 to Slot B I&Q + self.u.set_mux(0xba98) + + self.subdev[0].set_gain(self.subdev[0].gain_range()[1]) # set max Tx gain + self.subdev[1].set_gain(self.subdev[1].gain_range()[1]) # set max Tx gain + + self.set_freq(0, freq0) + self.set_freq(1, freq1) + self.subdev[0].set_enable(True) # enable transmitter + self.subdev[1].set_enable(True) # enable transmitter + + # ---------------------------------------------------------------- + # build two signal sources, interleave them, amplify and connect them to usrp + + sig0 = example_signal_0(self, self.usrp_rate) + sig1 = example_signal_1(self, self.usrp_rate) + + intl = gr.interleave(gr.sizeof_gr_complex) + self.connect(sig0, (intl, 0)) + self.connect(sig1, (intl, 1)) + + # apply some gain + if_gain = 10000 + ifamp = gr.multiply_const_cc(if_gain) + + # and wire them up + self.connect(intl, ifamp, self.u) + + + def set_freq(self, side, target_freq): + """ + Set the center frequency we're interested in. + + @param side: 0 = side A, 1 = side B + @param target_freq: frequency in Hz + @rtype: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + + print "Tuning side %s to %sHz" % (("A", "B")[side], num_to_str(target_freq)) + r = self.u.tune(self.subdev[side]._which, self.subdev[side], target_freq) + if r: + print " r.baseband_freq =", num_to_str(r.baseband_freq) + print " r.dxc_freq =", num_to_str(r.dxc_freq) + print " r.residual_freq =", num_to_str(r.residual_freq) + print " r.inverted =", r.inverted + print " OK" + return True + + else: + print " Failed!" + + return False + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/max_power.py b/gnuradio-examples/python/usrp/max_power.py new file mode 100755 index 00000000..b4ad86b0 --- /dev/null +++ b/gnuradio-examples/python/usrp/max_power.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Setup USRP for maximum power consumption. +""" + + +from gnuradio import gr +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +def ramp_source (fg): + period = 2**16 + src = gr.vector_source_s (range (-period/2, period/2, 1), True) + return src + +def build_graph (tx_enable, rx_enable): + max_usb_rate = 8e6 # 8 MS/sec + dac_freq = 128e6 + adc_freq = 64e6 + + tx_nchan = 2 + tx_mux = 0x0000ba98 + tx_interp = int (dac_freq / (max_usb_rate/2 * tx_nchan)) # 16 + + rx_nchan = 2 + rx_mux = 0x00003210 + rx_decim = int ((adc_freq * rx_nchan) / (max_usb_rate/2)) # 32 + + fg = gr.flow_graph () + + if tx_enable: + tx_src0 = gr.sig_source_c (dac_freq/tx_interp, gr.GR_CONST_WAVE, 0, 16e3, 0) + usrp_tx = usrp.sink_c (0, tx_interp, tx_nchan, tx_mux) + usrp_tx.set_tx_freq (0, 10e6) + usrp_tx.set_tx_freq (1, 9e6) + fg.connect (tx_src0, usrp_tx) + + if rx_enable: + usrp_rx = usrp.source_c (0, rx_decim, rx_nchan, rx_mux) + usrp_rx.set_rx_freq (0, 5.5e6) + usrp_rx.set_rx_freq (1, 6.5e6) + rx_dst0 = gr.null_sink (gr.sizeof_gr_complex) + fg.connect (usrp_rx, rx_dst0) + + return fg + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option ("-t", action="store_true", dest="tx_enable", + default=False, help="enable Tx path") + parser.add_option ("-r", action="store_true", dest="rx_enable", + default=False, help="enable Rx path") + (options, args) = parser.parse_args () + fg = build_graph (options.tx_enable, options.rx_enable) + + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/siggen_min2.py b/gnuradio-examples/python/usrp/siggen_min2.py new file mode 100755 index 00000000..8709e337 --- /dev/null +++ b/gnuradio-examples/python/usrp/siggen_min2.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + + + +def build_graph (): + + # interp = 32 + interp = 64 + nchan = 2 + + if nchan == 1: + mux = 0x0098 + #mux = 0x9800 + else: + mux = 0xba98 + + f0 = 100e3 + a0 = 16e3 + duc0 = 5e6 + + f1 = 50e3 + a1 = 16e3 + duc1 = 7e6 + + fg = gr.flow_graph () + + u = usrp.sink_c (0, interp, nchan, mux) + sample_rate = u.dac_freq () / interp + print "sample_rate = ", eng_notation.num_to_str (sample_rate) + print "usb_sample_rate = ", eng_notation.num_to_str (sample_rate * nchan) + + u.set_tx_freq (0, duc0) + u.set_tx_freq (1, duc1) + + interleave = gr.interleave (gr.sizeof_gr_complex) + fg.connect (interleave, u) + + src0 = gr.sig_source_c (sample_rate, gr.GR_SIN_WAVE, f0, a0, 0) + fg.connect (src0, (interleave, 0)) + + if nchan == 2: + if 1: + src1 = gr.sig_source_c (sample_rate, gr.GR_SIN_WAVE, f1, a1, 0) + else: + src1 = gr.noise_source_c (gr.GR_UNIFORM, a1) + fg.connect (src1, (interleave, 1)) + + return fg + + +if __name__ == '__main__': + fg = build_graph () + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () + diff --git a/gnuradio-examples/python/usrp/test_counting.py b/gnuradio-examples/python/usrp/test_counting.py new file mode 100755 index 00000000..ed9328a3 --- /dev/null +++ b/gnuradio-examples/python/usrp/test_counting.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Check Rx path or USRP Rev 1. + +This configures the USRP to return a periodic sequence of integers +""" + +from gnuradio import gr +from gnuradio import usrp + +def build_graph (): + rx_decim = 32 + + fg = gr.flow_graph () + usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_COUNTING) + sink = gr.check_counting_s () + fg.connect (usrp_rx, sink) + + # file_sink = gr.file_sink (gr.sizeof_short, 'counting.dat') + # fg.connect (usrp_rx, file_sink) + + return fg + +def main (): + fg = build_graph () + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/test_dft_analysis.py b/gnuradio-examples/python/usrp/test_dft_analysis.py new file mode 100755 index 00000000..a1d9eda4 --- /dev/null +++ b/gnuradio-examples/python/usrp/test_dft_analysis.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, blks +from gnuradio.wxgui import stdgui, fftsink, slider +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import wx + +class test_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self, frame, panel, vbox, argv) + + parser = OptionParser (option_class=eng_option) + (options, args) = parser.parse_args () + + sample_rate = 16e3 + mpoints = 4 + ampl = 1000 + freq = 0 + + lo_freq = 1e6 + lo_ampl = 1 + + vbox.Add(slider.slider(panel, + -sample_rate/2, sample_rate/2, + self.set_lo_freq), 0, wx.ALIGN_CENTER) + + + src = gr.sig_source_c(sample_rate, gr.GR_CONST_WAVE, + freq, ampl, 0) + + self.lo = gr.sig_source_c(sample_rate, gr.GR_SIN_WAVE, + lo_freq, lo_ampl, 0) + + mixer = gr.multiply_cc() + self.connect(src, (mixer, 0)) + self.connect(self.lo, (mixer, 1)) + + # We add these throttle blocks so that this demo doesn't + # suck down all the CPU available. Normally you wouldn't use these. + thr = gr.throttle(gr.sizeof_gr_complex, sample_rate) + + taps = gr.firdes.low_pass(1, # gain + 1, # rate + 1.0/mpoints * 0.4, # cutoff + 1.0/mpoints * 0.1, # trans width + gr.firdes.WIN_HANN) + print len(taps) + analysis = blks.analysis_filterbank(self, mpoints, taps) + + self.connect(mixer, thr) + self.connect(thr, analysis) + + for i in range(mpoints): + fft = fftsink.fft_sink_c(self, frame, fft_size=128, + sample_rate=sample_rate/mpoints, + fft_rate=5, + title="Ch %d" % (i,)) + self.connect((analysis, i), fft) + vbox.Add(fft.win, 1, wx.EXPAND) + + def set_lo_freq(self, freq): + self.lo.set_frequency(freq) + + + +def main (): + app = stdgui.stdapp (test_graph, "Test DFT filterbank") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/test_dft_synth.py b/gnuradio-examples/python/usrp/test_dft_synth.py new file mode 100755 index 00000000..60a49e3b --- /dev/null +++ b/gnuradio-examples/python/usrp/test_dft_synth.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, blks +from gnuradio.wxgui import stdgui, fftsink +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import wx +import random + + +def make_random_complex_tuple(L, gain=1): + result = [] + for x in range(L): + result.append(gain * complex(random.gauss(0, 1),random.gauss(0, 1))) + + return tuple(result) + +def random_noise_c(gain=1): + src = gr.vector_source_c(make_random_complex_tuple(32*1024, gain), True) + return src + + +class test_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self, frame, panel, vbox, argv) + + parser = OptionParser (option_class=eng_option) + (options, args) = parser.parse_args () + + sample_rate = 16e6 + mpoints = 16 + ampl = 1000 + + enable = mpoints * [0] + enable[0] = 1 + + taps = gr.firdes.low_pass(1, # gain + 1, # rate + 1.0/mpoints * 0.4, # cutoff + 1.0/mpoints * 0.1, # trans width + gr.firdes.WIN_HANN) + + synth = blks.synthesis_filterbank(self, mpoints, taps) + + null_source = gr.null_source(gr.sizeof_gr_complex) + + if 0: + for i in range(mpoints): + s = gr.sig_source_c(sample_rate/mpoints, gr.GR_SIN_WAVE, + 300e3, ampl * enable[i], 0) + self.connect(s, (synth, i)) + + else: + for i in range(mpoints): + if i == 0: + s = gr.sig_source_c(sample_rate/mpoints, gr.GR_SIN_WAVE, + 300e3, ampl * enable[i], 0) + #s = random_noise_c(ampl) + self.connect(s, (synth, i)) + else: + self.connect(null_source, (synth, i)) + + + # We add these throttle blocks so that this demo doesn't + # suck down all the CPU available. Normally you wouldn't use these. + thr = gr.throttle(gr.sizeof_gr_complex, sample_rate) + fft = fftsink.fft_sink_c(self, frame, fft_size=1024, + sample_rate=sample_rate) + vbox.Add(fft.win, 1, wx.EXPAND) + + self.connect(synth, thr, fft) + + +def main (): + app = stdgui.stdapp (test_graph, "Test DFT filterbank") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/test_digital_loopback_counting.py b/gnuradio-examples/python/usrp/test_digital_loopback_counting.py new file mode 100755 index 00000000..e985e4b4 --- /dev/null +++ b/gnuradio-examples/python/usrp/test_digital_loopback_counting.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Digital loopback (Tx to Rx) for the USRP Rev1. +""" + + +from gnuradio import gr +from gnuradio import usrp + + +def ramp_source (fg): + period = 2**16 + src = gr.vector_source_s (range (-period/2, period/2, 1), True) + return src + +def build_graph (): + tx_interp = 32 # tx should be twice rx + rx_decim = 16 + + fg = gr.flow_graph () + + data_src = ramp_source (fg) + # usrp_tx = usrp.sink_s (0, tx_interp, 1, 0x98) + usrp_tx = usrp.sink_s (0, tx_interp) + fg.connect (data_src, usrp_tx) + + usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK) + sink = gr.check_counting_s () + fg.connect (usrp_rx, sink) + + # file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat") + # fg.connect (usrp_rx, file_sink) + + return fg + +def main (): + fg = build_graph () + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py b/gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py new file mode 100755 index 00000000..ae78c714 --- /dev/null +++ b/gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Digital loopback (Tx to Rx) for the USRP Rev1. +""" + +from gnuradio import gr +from gnuradio import usrp + + +def build_graph (): + tx_interp = 32 # tx should be twice rx + rx_decim = 16 + + fg = gr.flow_graph () + + data_src = gr.lfsr_32k_source_s () + + # usrp_tx = usrp.sink_s (0, tx_interp, 1, 0x98) + usrp_tx = usrp.sink_s (0, tx_interp) + + fg.connect (data_src, usrp_tx) + + usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK) + + sink = gr.check_lfsr_32k_s () + fg.connect (usrp_rx, sink) + + # file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat") + # fg.connect (usrp_rx, file_sink) + + return fg + +def main (): + fg = build_graph () + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py b/gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py new file mode 100755 index 00000000..e4ad3693 --- /dev/null +++ b/gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# +# Demodulate an AM signal from the TVRX or a recorded file. +# The file format must be 256 ksps, complex data. +# + +from gnuradio import gr, gru, eng_notation +from gnuradio import audio_oss as audio +from gnuradio import usrp +from gnuradio import tv_rx +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math +from gnuradio.wxgui import stdgui, fftsink, scopesink +import wx + +# +# return a gr.flow_graph +# +class wfm_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + #set rf freq + rf_freq = 120.e6 + + # Decimation rate from USRP ADC to IF. + usrp_decim = 100 + + # Calculate the sampling rate of the USRP and capture file. + # Decimate the IF sampling rate down by 4 to 64 ksps + # This is a flow graph that has an input (capture file) and output (audio channel). + #self = gr.flow_graph () + + # Signal source is assumed to be 256 kspb / complex data stream. + which_side = 0 + # usrp is data source + if which_side == 0: + src = usrp.source_c (0, usrp_decim, 1, gru.hexint(0xf0f0f0f0), 0) + else: + src = usrp.source_c (0, usrp_decim, 1, gru.hexint(0xf0f0f0f2), 0) + + if_rate = 640e3 # src.adc_freq() / usrp_decim + if_decim = 5 + demod_rate = if_rate / if_decim + + audio_decimation = 4 + audio_rate = demod_rate / audio_decimation + + # set up frontend + dboard = tv_rx.tv_rx (src, which_side) + self.dboard = dboard + (success, actual_freq) = dboard.set_freq(rf_freq) + assert success + + if_freq = rf_freq - actual_freq + src.set_rx_freq (0, -if_freq) + + print "actual freq ", actual_freq + print "IF freq ", if_freq + + dboard.set_gain(50) + + #src = gr.file_source (gr.sizeof_gr_complex, "samples/atis_ffz_am_baseband_256k_complex.dat") + #src = gr.file_source (gr.sizeof_gr_complex, "samples/garagedoor1.dat", True) + + #channel_coeffs = gr.firdes.band_pass ( + # 1.0, # gain + # if_rate, + # 10, # center of low transition band + # 10000, # center of hi transition band + # 200, # width of transition band + # gr.firdes.WIN_HAMMING) + + channel_coeffs = gr.firdes.low_pass (1.0, if_rate, 10e3, 4e3, gr.firdes.WIN_HANN) + print "len(channel_coeffs) = ", len(channel_coeffs) + + # Tune to the desired frequency. + ddc = gr.freq_xlating_fir_filter_ccf (if_decim, channel_coeffs, -20e3, if_rate) + + # Demodule with classic sqrt (I*I + Q*Q) + magblock = gr.complex_to_mag() + + # Scale the audio + volumecontrol = gr.multiply_const_ff(.1) + + #band-pass + audio_coeffs = gr.firdes.band_pass ( + 1.0, # gain + demod_rate, + 10, # center of low transition band + 6000, # center of hi transition band + 200, # width of transition band + gr.firdes.WIN_HAMMING) + + + # Low pass filter the demodulator output + #audio_coeffs = gr.firdes.low_pass (1.0, demod_rate, 500, 200, gr.firdes.WIN_HANN) + print "len(audio_coeffs) = ", len(audio_coeffs) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + self.connect (src, ddc) + self.connect (ddc, magblock) + self.connect (magblock, volumecontrol) + self.connect (volumecontrol, audio_filter) + self.connect (audio_filter, (audio_sink, 0)) + + d_win = fftsink.fft_sink_c (self, panel, title="RF", fft_size=512, sample_rate=if_rate) + self.connect (src,d_win) + vbox.Add (d_win.win, 4, wx.EXPAND) + + p_win = fftsink.fft_sink_c (self, panel, title="IF", fft_size=512, sample_rate=demod_rate) + self.connect (ddc,p_win) + vbox.Add (p_win.win, 4, wx.EXPAND) + + r_win = fftsink.fft_sink_f (self, panel, title="Audio", fft_size=512, sample_rate=audio_rate) + self.connect (audio_filter,r_win) + vbox.Add (r_win.win, 4, wx.EXPAND) + + #audio_oscope = scopesink.scope_sink_f (self, panel, "Oscope Data", audio_rate) + #self.connect (audio_filter, audio_oscope) + #vbox.Add (audio_oscope.win, 4, wx.EXPAND) + +if __name__ == '__main__': + + app = stdgui.stdapp (wfm_rx_graph, "TVRX AM RX") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/usrp_fft.py b/gnuradio-examples/python/usrp/usrp_fft.py new file mode 100755 index 00000000..f760e39a --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_fft.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +from optparse import OptionParser +import wx +import sys + + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + If there's a daughterboard on A, select A. + If there's a daughterboard on B, select B. + Otherwise, select A. + """ + if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=first one with a daughterboard)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-W", "--waterfall", action="store_true", default=False, + help="Enable waterfall display") + parser.add_option("-8", "--width-8", action="store_true", default=False, + help="Enable 8-bit samples across USB") + parser.add_option("-S", "--oscilloscope", action="store_true", default=False, + help="Enable oscilloscope display") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + # build the graph + + self.u = usrp.source_c(decim_rate=options.decim) + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + + if options.width_8: + width = 8 + shift = 8 + format = self.u.make_format(width, shift) + print "format =", hex(format) + r = self.u.set_format(format) + print "set_format =", r + + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + + input_rate = self.u.adc_freq() / self.u.decim_rate() + + if options.waterfall: + self.scope = \ + waterfallsink.waterfall_sink_c (self, panel, fft_size=1024, sample_rate=input_rate) + elif options.oscilloscope: + self.scope = scopesink.scope_sink_c(self, panel, sample_rate=input_rate) + else: + self.scope = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate) + + self.connect(self.u, self.scope) + + self._build_gui(vbox) + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdev.freq_range() + options.freq = float(r[0]+r[1])/2 + + self.set_gain(options.gain) + + if self.show_debug_info: + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + self.myform['dbname'].set_value(self.subdev.name()) + self.myform['baseband'].set_value(0) + self.myform['ddc'].set_value(0) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + vbox.Add(self.scope.win, 10, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0, 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0, 0) + g = self.subdev.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + hbox.Add((5,0), 0, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + def _form_set_decim(kv): + return self.set_decim(kv['decim']) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['decim'] = form.int_field( + parent=panel, sizer=hbox, label="Decim", + callback=myform.check_input_and_call(_form_set_decim, self._set_status_msg)) + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = self.u.tune(0, self.subdev, target_freq) + + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + return True + + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + def set_decim(self, decim): + ok = self.u.set_decim_rate(decim) + if not ok: + print "set_decim failed" + input_rate = self.u.adc_freq() / self.u.decim_rate() + self.scope.set_sample_rate(input_rate) + if self.show_debug_info: # update displayed values + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + return ok + +def main (): + app = stdgui.stdapp(app_flow_graph, "USRP FFT", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/usrp_fft_old.py b/gnuradio-examples/python/usrp/usrp_fft_old.py new file mode 100755 index 00000000..c0776ea5 --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_fft_old.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink, scopesink +from optparse import OptionParser +import wx + +class app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + parser.add_option ("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM") + parser.add_option ("-c", "--ddc-freq", type="eng_float", default=0, + help="set Rx DDC frequency to FREQ", metavar="FREQ") + parser.add_option ("-m", "--mux", type="intx", default=0x32103210, + help="set fpga FR_RX_MUX register to MUX") + parser.add_option ("-g", "--gain", type="eng_float", default=0, + help="set Rx PGA gain in dB (default 0 dB)") + (options, args) = parser.parse_args () + + self.u = usrp.source_c (0, options.decim, 1, gru.hexint(options.mux), 0) + self.u.set_rx_freq (0, options.ddc_freq) + + self.u.set_pga (0, options.gain) + self.u.set_pga (1, options.gain) + + self.u.set_verbose (0) + + input_rate = self.u.adc_freq () / self.u.decim_rate () + + fft = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate) + #fft = fftsink.fft_sink_c (self, panel, fft_size=1024, fft_rate=50, sample_rate=input_rate) + self.connect (self.u, fft) + vbox.Add (fft.win, 10, wx.EXPAND) + + if 0: + c2f_1 = gr.complex_to_float () + scope = scopesink.scope_sink_f (self, panel, "Rx Data", input_rate) + vbox.Add (scope.win, 4, wx.EXPAND) + + self.connect (self.u,c2f_1) + self.connect ((c2f_1, 0), (scope, 0)) + self.connect ((c2f_1, 1), (scope, 1)) + + # build small control area at bottom + hbox = wx.BoxSizer (wx.HORIZONTAL) + hbox.Add ((1, 1), 1, wx.EXPAND) + hbox.Add (wx.StaticText (panel, -1, "Set ddc freq: "), 0, wx.ALIGN_CENTER) + self.tc_freq = wx.TextCtrl (panel, -1, "", style=wx.TE_PROCESS_ENTER) + hbox.Add (self.tc_freq, 0, wx.ALIGN_CENTER) + wx.EVT_TEXT_ENTER (self.tc_freq, self.tc_freq.GetId(), self.handle_text_enter) + hbox.Add ((1, 1), 1, wx.EXPAND) + # add it to the main vbox + vbox.Add (hbox, 0, wx.EXPAND) + + self.update_status_bar () + + def handle_text_enter (self, event): + str = event.GetString () + self.tc_freq.Clear () + self.u.set_rx_freq (0, eng_notation.str_to_num (str)) + self.update_status_bar () + + def update_status_bar (self): + ddc_freq = self.u.rx_freq (0) + decim_rate = self.u.decim_rate () + sample_rate = self.u.adc_freq () / decim_rate + msg = "decim: %d %sS/s DDC: %s" % ( + decim_rate, + eng_notation.num_to_str (sample_rate), + eng_notation.num_to_str (ddc_freq)) + + self.frame.GetStatusBar().SetStatusText (msg, 1) + + + +def main (): + app = stdgui.stdapp (app_flow_graph, "USRP FFT") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py b/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py new file mode 100755 index 00000000..3e930bbb --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_nbfm_ptt.py @@ -0,0 +1,491 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +import sys +import wx +from optparse import OptionParser + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio import audio +from gnuradio import blks +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink, scopesink, slider, form +import usrp_dbid + +from Numeric import convolve, array + +#import os +#print "pid =", os.getpid() +#raw_input('Press Enter to continue: ') + +# //////////////////////////////////////////////////////////////////////// +# Control Stuff +# //////////////////////////////////////////////////////////////////////// + +class ptt_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + self.frame = frame + self.space_bar_pressed = False + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option ("-f", "--freq", type="eng_float", default=442.1e6, + help="set Tx and Rx frequency to FREQ", metavar="FREQ") + parser.add_option ("-g", "--rx-gain", type="eng_float", default=None, + help="set rx gain [default=midpoint in dB]") + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option ("-N", "--no-gui", action="store_true", default=False) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + self.txpath = transmit_path(self, options.tx_subdev_spec, options.audio_input) + self.rxpath = receive_path(self, options.rx_subdev_spec, options.rx_gain, options.audio_output) + self._build_gui(frame, panel, vbox, argv, options.no_gui) + + self.set_transmit(False) + self.set_freq(options.freq) + self.set_rx_gain(self.rxpath.gain) # update gui + self.set_volume(self.rxpath.volume) # update gui + self.set_squelch(self.rxpath.threshold()) # update gui + + + def set_transmit(self, enabled): + self.txpath.set_enable(enabled) + self.rxpath.set_enable(not(enabled)) + if enabled: + self.frame.SetStatusText ("Transmitter ON", 1) + else: + self.frame.SetStatusText ("Receiver ON", 1) + + + def set_rx_gain(self, gain): + self.myform['rx_gain'].set_value(gain) # update displayed value + self.rxpath.set_gain(gain) + + def set_tx_gain(self, gain): + self.txpath.set_gain(gain) + + def set_squelch(self, threshold): + self.rxpath.set_squelch(threshold) + self.myform['squelch'].set_value(self.rxpath.threshold()) + + def set_volume (self, vol): + self.rxpath.set_volume(vol) + self.myform['volume'].set_value(self.rxpath.volume) + #self.update_status_bar () + + def set_freq(self, freq): + r1 = self.txpath.set_freq(freq) + r2 = self.rxpath.set_freq(freq) + #print "txpath.set_freq =", r1 + #print "rxpath.set_freq =", r2 + if r1 and r2: + self.myform['freq'].set_value(freq) # update displayed value + return r1 and r2 + + def _build_gui(self, frame, panel, vbox, argv, no_gui): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + self.panel = panel + + # FIXME This REALLY needs to be replaced with a hand-crafted button + # that sends both button down and button up events + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((10,0), 1) + self.status_msg = wx.StaticText(panel, -1, "Press Space Bar to Transmit") + of = self.status_msg.GetFont() + self.status_msg.SetFont(wx.Font(15, of.GetFamily(), of.GetStyle(), of.GetWeight())) + hbox.Add(self.status_msg, 0, wx.ALIGN_CENTER) + hbox.Add((10,0), 1) + vbox.Add(hbox, 0, wx.EXPAND | wx.ALIGN_CENTER) + + panel.Bind(wx.EVT_KEY_DOWN, self._on_key_down) + panel.Bind(wx.EVT_KEY_UP, self._on_key_up) + panel.Bind(wx.EVT_KILL_FOCUS, self._on_kill_focus) + panel.SetFocus() + + if 1 and not(no_gui): + rx_fft = fftsink.fft_sink_c (self, panel, title="Rx Input", fft_size=512, + sample_rate=self.rxpath.if_rate, + ref_level=80, y_per_div=20) + self.connect (self.rxpath.u, rx_fft) + vbox.Add (rx_fft.win, 1, wx.EXPAND) + + if 1 and not(no_gui): + rx_fft = fftsink.fft_sink_c (self, panel, title="Post s/w DDC", + fft_size=512, sample_rate=self.rxpath.quad_rate, + ref_level=80, y_per_div=20) + self.connect (self.rxpath.ddc, rx_fft) + vbox.Add (rx_fft.win, 1, wx.EXPAND) + + if 0 and not(no_gui): + foo = scopesink.scope_sink_f (self, panel, title="Squelch", + sample_rate=32000) + self.connect (self.rxpath.fmrx.div, (foo,0)) + self.connect (self.rxpath.fmrx.gate, (foo,1)) + self.connect (self.rxpath.fmrx.squelch_lpf, (foo,2)) + vbox.Add (foo.win, 1, wx.EXPAND) + + if 0 and not(no_gui): + tx_fft = fftsink.fft_sink_c (self, panel, title="Tx Output", + fft_size=512, sample_rate=self.txpath.usrp_rate) + self.connect (self.txpath.amp, tx_fft) + vbox.Add (tx_fft.win, 1, wx.EXPAND) + + + # add control area at the bottom + + self.myform = myform = form.form() + + # first row + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0, 0) + myform['freq'] = form.float_field( + parent=panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + # second row + hbox = wx.BoxSizer(wx.HORIZONTAL) + myform['volume'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", + weight=3, range=self.rxpath.volume_range(), + callback=self.set_volume) + hbox.Add((5,0), 0) + myform['squelch'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Squelch", + weight=3, range=self.rxpath.squelch_range(), + callback=self.set_squelch) + hbox.Add((5,0), 0) + myform['rx_gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Rx Gain", + weight=3, range=self.rxpath.subdev.gain_range(), + callback=self.set_rx_gain) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + self._build_subpanel(vbox) + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + #if not(self.show_debug_info): + # return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + #myform['decim'] = form.static_float_field( + # parent=panel, sizer=hbox, label="Decim") + + #hbox.Add((5,0), 1) + #myform['fs@usb'] = form.static_float_field( + # parent=panel, sizer=hbox, label="Fs@USB") + + #hbox.Add((5,0), 1) + #myform['dbname'] = form.static_text_field( + # parent=panel, sizer=hbox) + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + def _on_key_down(self, evt): + # print "key_down:", evt.m_keyCode + if evt.m_keyCode == wx.WXK_SPACE and not(self.space_bar_pressed): + self.space_bar_pressed = True + self.set_transmit(True) + + def _on_key_up(self, evt): + # print "key_up", evt.m_keyCode + if evt.m_keyCode == wx.WXK_SPACE: + self.space_bar_pressed = False + self.set_transmit(False) + + def _on_kill_focus(self, evt): + # if we lose the keyboard focus, turn off the transmitter + self.space_bar_pressed = False + self.set_transmit(False) + + +# //////////////////////////////////////////////////////////////////////// +# Transmit Path +# //////////////////////////////////////////////////////////////////////// + +class transmit_path(gr.hier_block): + def __init__(self, fg, subdev_spec, audio_input): + + self.u = usrp.sink_c () + + dac_rate = self.u.dac_rate(); + self.if_rate = 320e3 # 320 kS/s + self.usrp_interp = int(dac_rate // self.if_rate) + self.u.set_interp_rate(self.usrp_interp) + self.sw_interp = 10 + self.audio_rate = self.if_rate // self.sw_interp # 32 kS/s + + self.audio_gain = 10 + self.normal_gain = 32000 + + self.audio = audio.source(int(self.audio_rate), audio_input) + self.audio_amp = gr.multiply_const_ff(self.audio_gain) + + lpf = gr.firdes.low_pass (1, # gain + self.audio_rate, # sampling rate + 3800, # low pass cutoff freq + 300, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + hpf = gr.firdes.high_pass (1, # gain + self.audio_rate, # sampling rate + 325, # low pass cutoff freq + 50, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + audio_taps = convolve(array(lpf),array(hpf)) + self.audio_filt = gr.fir_filter_fff(1,audio_taps) + + self.pl = blks.ctcss_gen_f(fg, self.audio_rate,123.0) + self.add_pl = gr.add_ff() + fg.connect(self.pl,(self.add_pl,1)) + + self.fmtx = blks.nbfm_tx(fg, self.audio_rate, self.if_rate) + self.amp = gr.multiply_const_cc (self.normal_gain) + + # determine the daughterboard subdevice we're using + if subdev_spec is None: + subdev_spec = usrp.pick_tx_subdevice(self.u) + self.u.set_mux(usrp.determine_tx_mux_value(self.u, subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, subdev_spec) + print "TX using", self.subdev.name() + + fg.connect(self.audio, self.audio_amp, self.audio_filt, + (self.add_pl,0), self.fmtx, self.amp, self.u) + + gr.hier_block.__init__(self, fg, None, None) + + self.set_gain(self.subdev.gain_range()[1]) # set max Tx gain + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. Finally, we feed + any residual_freq to the s/w freq translater. + """ + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + # Use residual_freq in s/w freq translator + return True + + return False + + def set_gain(self, gain): + self.gain = gain + self.subdev.set_gain(gain) + + def set_enable(self, enable): + self.subdev.set_enable(enable) # set H/W Tx enable + if enable: + self.amp.set_k (self.normal_gain) + else: + self.amp.set_k (0) + + + +# //////////////////////////////////////////////////////////////////////// +# Receive Path +# //////////////////////////////////////////////////////////////////////// + +class receive_path(gr.hier_block): + def __init__(self, fg, subdev_spec, gain, audio_output): + + self.u = usrp.source_c () + adc_rate = self.u.adc_rate() + + self.if_rate = 256e3 # 256 kS/s + usrp_decim = int(adc_rate // self.if_rate) + if_decim = 4 + self.u.set_decim_rate(usrp_decim) + self.quad_rate = self.if_rate // if_decim # 64 kS/s + audio_decim = 2 + audio_rate = self.quad_rate // audio_decim # 32 kS/s + + if subdev_spec is None: + subdev_spec = usrp.pick_rx_subdevice(self.u) + self.subdev = usrp.selected_subdev(self.u, subdev_spec) + print "RX using", self.subdev.name() + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec)) + + # Create filter to get actual channel we want + chan_coeffs = gr.firdes.low_pass (1.0, # gain + self.if_rate, # sampling rate + 13e3, # low pass cutoff freq + 4e3, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + print "len(rx_chan_coeffs) =", len(chan_coeffs) + + # Decimating Channel filter with frequency translation + # complex in and out, float taps + self.ddc = gr.freq_xlating_fir_filter_ccf(if_decim, # decimation rate + chan_coeffs, # taps + 0, # frequency translation amount + self.if_rate) # input sample rate + + # instantiate the guts of the single channel receiver + self.fmrx = blks.nbfm_rx(fg, audio_rate, self.quad_rate) + + # standard squelch block + self.squelch = blks.standard_squelch(fg, audio_rate) + + # audio gain / mute block + self._audio_gain = gr.multiply_const_ff(1.0) + + # sound card as final sink + audio_sink = audio.sink (int(audio_rate), audio_output) + + # now wire it all together + fg.connect (self.u, self.ddc, self.fmrx, self.squelch, self._audio_gain, audio_sink) + gr.hier_block.__init__(self, fg, self.u, audio_sink) + + if gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + gain = float(g[0]+g[1])/2 + + self.enabled = True + self.set_gain(gain) + v = self.volume_range() + self.set_volume((v[0]+v[1])/2) + s = self.squelch_range() + self.set_squelch((s[0]+s[1])/2) + + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + def set_volume (self, vol): + g = self.volume_range() + self.volume = max(g[0], min(g[1], vol)) + self._update_audio_gain() + + def set_enable(self, enable): + self.enabled = enable + self._update_audio_gain() + + def _update_audio_gain(self): + if self.enabled: + self._audio_gain.set_k(10**(self.volume/10)) + else: + self._audio_gain.set_k(0) + + def squelch_range(self): + return self.squelch.squelch_range() + + def set_squelch(self, threshold): + print "SQL =", threshold + self.squelch.set_threshold(threshold) + + def threshold(self): + return self.squelch.threshold() + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter in the + FPGA. Finally, we feed any residual_freq to the s/w freq + translator. + """ + r = self.u.tune(0, self.subdev, target_freq) + if r: + # Use residual_freq in s/w freq translater + # print "residual_freq =", r.residual_freq + self.ddc.set_center_freq(-r.residual_freq) + return True + + return False + + def set_gain(self, gain): + self.gain = gain + self.subdev.set_gain(gain) + + +# //////////////////////////////////////////////////////////////////////// +# Main +# //////////////////////////////////////////////////////////////////////// + +def main(): + app = stdgui.stdapp(ptt_graph, "NBFM Push to Talk") + app.MainLoop() + +if __name__ == '__main__': + main() diff --git a/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py b/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py new file mode 100755 index 00000000..018a5b76 --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_nbfm_rcv.py @@ -0,0 +1,362 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import slider, powermate +from gnuradio.wxgui import stdgui, fftsink, form +from optparse import OptionParser +import usrp_dbid +import sys +import math +import wx + + +#//////////////////////////////////////////////////////////////////////// +# Control Stuff +#//////////////////////////////////////////////////////////////////////// + +class my_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-V", "--volume", type="eng_float", default=None, + help="set volume (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + parser.add_option("-N", "--no-gui", action="store_true", default=False) + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + self.frame = frame + self.panel = panel + + self.state = "FREQ" + self.freq = 0 + self.freq_step = 25e3 + + self.rxpath = receive_path(self, options.rx_subdev_spec, options.gain, options.audio_output) + + self._build_gui(vbox, options.no_gui) + + # set initial values + + if options.volume is not None: + self.set_volume(options.volume) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + self.set_gain(self.rxpath.gain) # update gui + self.set_volume(self.rxpath.volume) # update gui + self.set_squelch(self.rxpath.threshold()) # update gui + + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + + def _build_gui(self, vbox, no_gui): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + + self.src_fft = None + if 1 and not(no_gui): + self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP", + fft_size=512, sample_rate=self.rxpath.if_rate, + ref_level=80, y_per_div=20) + self.connect (self.rxpath.u, self.src_fft) + vbox.Add (self.src_fft.win, 4, wx.EXPAND) + + if 1 and not(no_gui): + rx_fft = fftsink.fft_sink_c (self, self.panel, title="Post s/w DDC", + fft_size=512, sample_rate=self.rxpath.quad_rate, + ref_level=80, y_per_div=20) + self.connect (self.rxpath.ddc, rx_fft) + vbox.Add (rx_fft.win, 4, wx.EXPAND) + + if 1 and not(no_gui): + post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph", + fft_size=512, sample_rate=self.rxpath.audio_rate, + y_per_div=10, ref_level=-40) + self.connect (self.rxpath.fmrx.deemph, post_deemph_fft) + vbox.Add (post_deemph_fft.win, 4, wx.EXPAND) + + if 0: + post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=-40) + self.connect (self.guts.audio_filter, post_filt) + vbox.Add (fft_win4, 4, wx.EXPAND) + + + # control area form at bottom + self.myform = myform = form.form() + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + #hbox.Add((5,0), 0) + #myform['freq_slider'] = \ + # form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, + # range=(87.9e6, 108.1e6, 0.1e6), + # callback=self.set_freq) + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['volume'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", + weight=3, range=self.volume_range(), + callback=self.set_volume) + hbox.Add((5,0), 0) + myform['squelch'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Squelch", + weight=3, range=self.rxpath.squelch_range(), + callback=self.set_squelch) + hbox.Add((5,0), 0) + myform['gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, range=self.rxpath.subdev.gain_range(), + callback=self.set_gain) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + try: + self.knob = powermate.powermate(self.frame) + self.rot = 0 + powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button) + except: + print "FYI: No Powermate or Contour Knob found" + + + def on_rotate (self, event): + self.rot += event.delta + if (self.state == "FREQ"): + if self.rot >= 3: + self.set_freq(self.freq + self.freq_step) + self.rot -= 3 + elif self.rot <=-3: + self.set_freq(self.freq - self.freq_step) + self.rot += 3 + else: + step = self.volume_range()[2] + if self.rot >= 3: + self.set_volume(self.rxpath.volume + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_volume(self.rxpath.volume - step) + self.rot += 3 + + def on_button (self, event): + if event.value == 0: # button up + return + self.rot = 0 + if self.state == "FREQ": + self.state = "VOL" + else: + self.state = "FREQ" + self.update_status_bar () + + + def set_squelch(self, threshold_in_db): + self.rxpath.set_squelch(threshold_in_db) + self.myform['squelch'].set_value(self.rxpath.threshold()) + + def set_volume (self, vol): + self.rxpath.set_volume(vol) + self.myform['volume'].set_value(self.rxpath.volume) + self.update_status_bar () + + def set_freq(self, target_freq): + r = self.rxpath.set_freq(target_freq) + if r: + self.freq = target_freq + self.myform['freq'].set_value(target_freq) # update displayed value + #self.myform['freq_slider'].set_value(target_freq) # update displayed value + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.rxpath.set_gain(gain) + + def update_status_bar (self): + msg = "Volume:%r Setting:%s" % (self.rxpath.volume, self.state) + self._set_status_msg(msg, 1) + if self.src_fft: + self.src_fft.set_baseband_freq(self.freq) + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + +#//////////////////////////////////////////////////////////////////////// +# Receive Path +#//////////////////////////////////////////////////////////////////////// + +USE_SIMPLE_SQUELCH = False + +class receive_path(gr.hier_block): + def __init__(self, fg, subdev_spec, gain, audio_output): + + self.u = usrp.source_c () + adc_rate = self.u.adc_rate() + + self.if_rate = 256e3 # 256 kS/s + usrp_decim = int(adc_rate // self.if_rate) + if_decim = 4 + self.u.set_decim_rate(usrp_decim) + self.quad_rate = self.if_rate // if_decim # 64 kS/s + audio_decim = 2 + self.audio_rate = self.quad_rate // audio_decim # 32 kS/s + + + if subdev_spec is None: + subdev_spec = usrp.pick_rx_subdevice(self.u) + self.subdev = usrp.selected_subdev(self.u, subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec)) + + # Create filter to get actual channel we want + chan_coeffs = gr.firdes.low_pass (1.0, # gain + self.if_rate, # sampling rate + 13e3, # low pass cutoff freq + 4e3, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + print "len(rx_chan_coeffs) =", len(chan_coeffs) + + # Decimating Channel filter with frequency translation + # complex in and out, float taps + self.ddc = gr.freq_xlating_fir_filter_ccf(if_decim, # decimation rate + chan_coeffs, # taps + 0, # frequency translation amount + self.if_rate) # input sample rate + + if USE_SIMPLE_SQUELCH: + self.squelch = gr.simple_squelch_cc(20) + else: + self.squelch = blks.standard_squelch(fg, self.audio_rate) + + # instantiate the guts of the single channel receiver + self.fmrx = blks.nbfm_rx(fg, self.audio_rate, self.quad_rate) + + # audio gain / mute block + self._audio_gain = gr.multiply_const_ff(1.0) + + # sound card as final sink + audio_sink = audio.sink (int(self.audio_rate), audio_output) + + # now wire it all together + if USE_SIMPLE_SQUELCH: + fg.connect (self.u, self.ddc, self.squelch, self.fmrx, + self._audio_gain, audio_sink) + else: + fg.connect (self.u, self.ddc, self.fmrx, self.squelch, + self._audio_gain, audio_sink) + + gr.hier_block.__init__(self, fg, self.u, audio_sink) + + if gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + gain = float(g[0]+g[1])/2 + + self.set_gain(gain) + + v = self.volume_range() + self.set_volume((v[0]+v[1])/2) + s = self.squelch_range() + self.set_squelch((s[0]+s[1])/2) + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + def set_volume (self, vol): + g = self.volume_range() + self.volume = max(g[0], min(g[1], vol)) + self._update_audio_gain() + + def _update_audio_gain(self): + self._audio_gain.set_k(10**(self.volume/10)) + + def squelch_range(self): + r = self.squelch.squelch_range() + #print "squelch_range: ", r + return r + + def set_squelch(self, threshold): + #print "SQL =", threshold + self.squelch.set_threshold(threshold) + + def threshold(self): + t = self.squelch.threshold() + #print "t =", t + return t + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter in the + FPGA. Finally, we feed any residual_freq to the s/w freq + translator. + """ + + r = usrp.tune(self.u, 0, self.subdev, target_freq) + if r: + # Use residual_freq in s/w freq translater + # print "residual_freq =", r.residual_freq + self.ddc.set_center_freq(-r.residual_freq) + return True + + return False + + def set_gain(self, gain): + self.gain = gain + self.subdev.set_gain(gain) + + +# //////////////////////////////////////////////////////////////////////// +# Main +# //////////////////////////////////////////////////////////////////////// + +if __name__ == '__main__': + app = stdgui.stdapp (my_graph, "USRP NBFM RX") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/usrp_oscope.py b/gnuradio-examples/python/usrp/usrp_oscope.py new file mode 100755 index 00000000..f4469f99 --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_oscope.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# print "Loading revised usrp_oscope with additional options for scopesink..." + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +from optparse import OptionParser +import wx +import sys + + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + If there's a daughterboard on A, select A. + If there's a daughterboard on B, select B. + Otherwise, select A. + """ + if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=first one with a daughterboard)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-8", "--width-8", action="store_true", default=False, + help="Enable 8-bit samples across USB") + parser.add_option("-n", "--frame-decim", type="int", default=1, + help="set oscope frame decimation factor to n [default=1]") + parser.add_option("-v", "--v-scale", type="eng_float", default=1000, + help="set oscope initial V/div to SCALE [default=%default]") + parser.add_option("-t", "--t-scale", type="eng_float", default=49e-6, + help="set oscope initial s/div to SCALE [default=50us]") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + # build the graph + + self.u = usrp.source_c(decim_rate=options.decim) + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + + if options.width_8: + width = 8 + shift = 8 + format = self.u.make_format(width, shift) + #print "format =", hex(format) + r = self.u.set_format(format) + #print "set_format =", r + + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + + input_rate = self.u.adc_freq() / self.u.decim_rate() + + self.scope = scopesink.scope_sink_c(self, panel, sample_rate=input_rate, + frame_decim=options.frame_decim, + v_scale=options.v_scale, + t_scale=options.t_scale) + self.connect(self.u, self.scope) + + self._build_gui(vbox) + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdev.freq_range() + options.freq = float(r[0]+r[1])/2 + + self.set_gain(options.gain) + + if self.show_debug_info: + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + self.myform['dbname'].set_value(self.subdev.name()) + self.myform['baseband'].set_value(0) + self.myform['ddc'].set_value(0) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + vbox.Add(self.scope.win, 10, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0, 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0, 0) + g = self.subdev.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + hbox.Add((5,0), 0, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + def _form_set_decim(kv): + return self.set_decim(kv['decim']) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['decim'] = form.int_field( + parent=panel, sizer=hbox, label="Decim", + callback=myform.check_input_and_call(_form_set_decim, self._set_status_msg)) + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = usrp.tune(self.u, 0, self.subdev, target_freq) + + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + return True + + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + def set_decim(self, decim): + ok = self.u.set_decim_rate(decim) + if not ok: + print "set_decim failed" + input_rate = self.u.adc_freq() / self.u.decim_rate() + self.scope.set_sample_rate(input_rate) + if self.show_debug_info: # update displayed values + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + return ok + +def main (): + app = stdgui.stdapp(app_flow_graph, "USRP O'scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/usrp_rx_cfile.py b/gnuradio-examples/python/usrp/usrp_rx_cfile.py new file mode 100755 index 00000000..306e101d --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_rx_cfile.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python + +""" +Read samples from the USRP and write to file formatted as binary +outputs single precision complex float values or complex short values (interleaved 16 bit signed short integers). + +""" + +from gnuradio import gr, eng_notation +from gnuradio import audio +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-8", "--width-8", action="store_true", default=False, + help="Enable 8-bit samples across USB") + parser.add_option( "--no-hb", action="store_true", default=False, + help="don't use halfband filter in usrp") + parser.add_option( "-s","--output-shorts", action="store_true", default=False, + help="output interleaved shorts in stead of complex floats") + parser.add_option("-N", "--nsamples", type="eng_float", default=None, + help="number of samples to collect [default=+inf]") + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + filename = args[0] + + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + + # build the graph + if options.no_hb or (options.decim<8): + self.fpga_filename="std_4rx_0tx.rbf" #Min decimation of this firmware is 4. contains 4 Rx paths without halfbands and 0 tx paths. + if options.output_shorts: + self.u = usrp.source_s(decim_rate=options.decim,fpga_filename=self.fpga_filename) + else: + self.u = usrp.source_c(decim_rate=options.decim,fpga_filename=self.fpga_filename) + else: + #standard fpga firmware "std_2rxhb_2tx.rbf" contains 2 Rx paths with halfband filters and 2 tx paths (the default) min decimation 8 + if options.output_shorts: + self.u = usrp.source_s(decim_rate=options.decim) + else: + self.u = usrp.source_c(decim_rate=options.decim) + if options.width_8: + sample_width = 8 + sample_shift = 8 + format = self.u.make_format(sample_width, sample_shift) + r = self.u.set_format(format) + if options.output_shorts: + self.dst = gr.file_sink(gr.sizeof_short, filename) + else: + self.dst = gr.file_sink(gr.sizeof_gr_complex, filename) + if options.nsamples is None: + self.connect(self.u, self.dst) + else: + if options.output_shorts: + self.head = gr.head(gr.sizeof_short, int(options.nsamples)*2) + else: + self.head = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + self.connect(self.u, self.head, self.dst) + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = usrp.pick_rx_subdevice(self.u) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB sample rate %s" % (eng_notation.num_to_str(input_rate)) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + self.subdev.set_gain(options.gain) + + r = self.u.tune(0, self.subdev, options.freq) + if not r: + sys.stderr.write('Failed to set frequency\n') + raise SystemExit, 1 + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/usrp_rx_nogui.py b/gnuradio-examples/python/usrp/usrp_rx_nogui.py new file mode 100755 index 00000000..b33d626e --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_rx_nogui.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, usrp, optfir, audio, eng_notation, blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +""" +This example application demonstrates receiving and demodulating +different types of signals using the USRP. + +A receive chain is built up of the following signal processing +blocks: + +USRP - Daughter board source generating complex baseband signal. +CHAN - Low pass filter to select channel bandwidth +RFSQL - RF squelch zeroing output when input power below threshold +AGC - Automatic gain control leveling signal at [-1.0, +1.0] +DEMOD - Demodulation block appropriate to selected signal type. + This converts the complex baseband to real audio frequencies, + and applies an appropriate low pass decimating filter. +CTCSS - Optional tone squelch zeroing output when tone is not present. +RSAMP - Resampler block to convert audio sample rate to user specified + sound card output rate. +AUDIO - Audio sink for playing final output to speakers. + +The following are required command line parameters: + +-f FREQ USRP receive frequency +-m MOD Modulation type, select from AM, FM, or WFM + +The following are optional command line parameters: + +-R SUBDEV Daughter board specification, defaults to first found +-c FREQ Calibration offset. Gets added to receive frequency. + Defaults to 0.0 Hz. +-g GAIN Daughterboard gain setting. Defaults to mid-range. +-o RATE Sound card output rate. Defaults to 32000. Useful if + your sound card only accepts particular sample rates. +-r RFSQL RF squelch in db. Defaults to -50.0. +-p FREQ CTCSS frequency. Opens squelch when tone is present. + +Once the program is running, ctrl-break (Ctrl-C) stops operation. + +Please see fm_demod.py and am_demod.py for details of the demodulation +blocks. +""" + +# (usrp_decim, channel_decim, audio_decim, channel_pass, channel_stop, demod) +demod_params = { + 'AM' : (250, 16, 1, 5000, 8000, blks.demod_10k0a3e_cf), + 'FM' : (250, 8, 4, 8000, 9000, blks.demod_20k0f3e_cf), + 'WFM' : (250, 1, 8, 90000, 100000, blks.demod_200kf3e_cf) + } + +class usrp_source_c(gr.hier_block): + """ + Create a USRP source object supplying complex floats. + + Selects user supplied subdevice or chooses first available one. + + Calibration value is the offset from the tuned frequency to + the actual frequency. + """ + def __init__(self, fg, subdev_spec, decim, gain=None, calibration=0.0): + self._decim = decim + self._src = usrp.source_c() + if subdev_spec is None: + subdev_spec = usrp.pick_rx_subdevice(self._src) + self._subdev = usrp.selected_subdev(self._src, subdev_spec) + self._src.set_mux(usrp.determine_rx_mux_value(self._src, subdev_spec)) + self._src.set_decim_rate(self._decim) + + # If no gain specified, set to midrange + if gain is None: + g = self._subdev.gain_range() + gain = (g[0]+g[1])/2.0 + + self._subdev.set_gain(gain) + self._cal = calibration + gr.hier_block.__init__(self, fg, self._src, self._src) + + def tune(self, freq): + result = usrp.tune(self._src, 0, self._subdev, freq+self._cal) + # TODO: deal with residual + + def rate(self): + return self._src.adc_rate()/self._decim + +class app_flow_graph(gr.flow_graph): + def __init__(self, options, args): + gr.flow_graph.__init__(self) + self.options = options + self.args = args + + (usrp_decim, channel_decim, audio_decim, + channel_pass, channel_stop, demod) = demod_params[options.modulation] + + USRP = usrp_source_c(self, # Flow graph + options.rx_subdev_spec, # Daugherboard spec + usrp_decim, # IF decimation ratio + options.gain, # Receiver gain + options.calibration) # Frequency offset + USRP.tune(options.frequency) + + if_rate = USRP.rate() + channel_rate = if_rate // channel_decim + audio_rate = channel_rate // audio_decim + + CHAN_taps = optfir.low_pass(1.0, # Filter gain + if_rate, # Sample rate + channel_pass, # One sided modulation bandwidth + channel_stop, # One sided channel bandwidth + 0.1, # Passband ripple + 60) # Stopband attenuation + + CHAN = gr.freq_xlating_fir_filter_ccf(channel_decim, # Decimation rate + CHAN_taps, # Filter taps + 0.0, # Offset frequency + if_rate) # Sample rate + + RFSQL = gr.pwr_squelch_cc(options.rf_squelch, # Power threshold + 125.0/channel_rate, # Time constant + channel_rate/20, # 50ms rise/fall + False) # Zero, not gate output + + AGC = gr.agc_cc(1.0/channel_rate, # Time constant + 1.0, # Reference power + 1.0, # Initial gain + 1.0) # Maximum gain + + DEMOD = demod(self, channel_rate, audio_decim) + + # From RF to audio + self.connect(USRP, CHAN, RFSQL, AGC, DEMOD) + + # Optionally add CTCSS and RSAMP if needed + tail = DEMOD + if options.ctcss != None and options.ctcss > 60.0: + CTCSS = gr.ctcss_squelch_ff(audio_rate, # Sample rate + options.ctcss) # Squelch tone + self.connect(DEMOD, CTCSS) + tail = CTCSS + + if options.output_rate != audio_rate: + out_lcm = gru.lcm(audio_rate, options.output_rate) + out_interp = int(out_lcm // audio_rate) + out_decim = int(out_lcm // options.output_rate) + RSAMP = blks.rational_resampler_fff(self, out_interp, out_decim) + self.connect(tail, RSAMP) + tail = RSAMP + + # Send to default audio output + AUDIO = audio.sink(options.output_rate, "") + self.connect(tail, AUDIO) + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-f", "--frequency", type="eng_float", + help="set receive frequency to Hz", metavar="Hz") + parser.add_option("-R", "--rx-subdev-spec", type="subdev", + help="select USRP Rx side A or B", metavar="SUBDEV") + parser.add_option("-c", "--calibration", type="eng_float", default=0.0, + help="set frequency offset to Hz", metavar="Hz") + parser.add_option("-g", "--gain", type="int", default=None, + help="set RF gain", metavar="dB") + parser.add_option("-m", "--modulation", type="choice", choices=('AM','FM','WFM'), + help="set modulation type (AM,FM)", metavar="TYPE") + parser.add_option("-o", "--output-rate", type="int", default=32000, + help="set audio output rate to RATE", metavar="RATE") + parser.add_option("-r", "--rf-squelch", type="eng_float", default=-50.0, + help="set RF squelch to dB", metavar="dB") + parser.add_option("-p", "--ctcss", type="float", + help="set CTCSS squelch to FREQ", metavar="FREQ") + (options, args) = parser.parse_args() + + if options.frequency < 1e6: + options.frequency *= 1e6 + + fg = app_flow_graph(options, args) + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == "__main__": + main() diff --git a/gnuradio-examples/python/usrp/usrp_siggen.py b/gnuradio-examples/python/usrp/usrp_siggen.py new file mode 100755 index 00000000..59e01e0a --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_siggen.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from optparse import OptionParser +import sys + + +class my_graph(gr.flow_graph): + def __init__ (self): + gr.flow_graph.__init__(self) + + # controllable values + self.interp = 64 + self.waveform_type = gr.GR_SIN_WAVE + self.waveform_ampl = 16000 + self.waveform_freq = 100.12345e3 + self.waveform_offset = 0 + self._instantiate_blocks () + self.set_waveform_type (self.waveform_type) + + def usb_freq (self): + return self.u.dac_freq() / self.interp + + def usb_throughput (self): + return self.usb_freq () * 4 + + def set_waveform_type (self, type): + ''' + valid waveform types are: gr.GR_SIN_WAVE, gr.GR_CONST_WAVE, + gr.GR_UNIFORM and gr.GR_GAUSSIAN + ''' + self._configure_graph (type) + self.waveform_type = type + + def set_waveform_ampl (self, ampl): + self.waveform_ampl = ampl + self.siggen.set_amplitude (ampl) + self.noisegen.set_amplitude (ampl) + + def set_waveform_freq (self, freq): + self.waveform_freq = freq + self.siggen.set_frequency (freq) + + def set_waveform_offset (self, offset): + self.waveform_offset = offset + self.siggen.set_offset (offset) + + def set_interpolator (self, interp): + self.interp = interp + self.siggen.set_sampling_freq (self.usb_freq ()) + self.u.set_interp_rate (interp) + + def _instantiate_blocks (self): + self.src = None + self.u = usrp.sink_c (0, self.interp) + + self.siggen = gr.sig_source_c (self.usb_freq (), + gr.GR_SIN_WAVE, + self.waveform_freq, + self.waveform_ampl, + self.waveform_offset) + + self.noisegen = gr.noise_source_c (gr.GR_UNIFORM, + self.waveform_ampl) + + # self.file_sink = gr.file_sink (gr.sizeof_gr_complex, "siggen.dat") + + def _configure_graph (self, type): + was_running = self.is_running () + if was_running: + self.stop () + self.disconnect_all () + if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE: + self.connect (self.siggen, self.u) + # self.connect (self.siggen, self.file_sink) + self.siggen.set_waveform (type) + self.src = self.siggen + elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN: + self.connect (self.noisegen, self.u) + self.noisegen.set_type (type) + self.src = self.noisegen + else: + raise ValueError, type + if was_running: + self.start () + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq) + print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq) + print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq) + print "r.inverted =", r.inverted + return True + + return False + + + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option ("-T", "--tx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Tx side A or B") + parser.add_option ("-f", "--rf-freq", type="eng_float", default=None, + help="set RF center frequency to FREQ") + parser.add_option ("-i", "--interp", type="int", default=64, + help="set fgpa interpolation rate to INTERP") + + parser.add_option ("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE, + help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE) + parser.add_option ("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, + help="generate a constant output") + parser.add_option ("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN, + help="generate Gaussian random output") + parser.add_option ("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM, + help="generate Uniform random output") + + parser.add_option ("-w", "--waveform-freq", type="eng_float", default=100e3, + help="set waveform frequency to FREQ") + parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3, + help="set waveform amplitude to AMPLITUDE", metavar="AMPL") + parser.add_option ("-o", "--offset", type="eng_float", default=0, + help="set waveform offset to OFFSET") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + raise SystemExit + + if options.rf_freq is None: + sys.stderr.write("usrp_siggen: must specify RF center frequency with -f RF_FREQ\n") + parser.print_help() + raise SystemExit + + fg = my_graph() + fg.set_interpolator (options.interp) + fg.set_waveform_type (options.type) + fg.set_waveform_freq (options.waveform_freq) + fg.set_waveform_ampl (options.amplitude) + fg.set_waveform_offset (options.offset) + + # determine the daughterboard subdevice we're using + if options.tx_subdev_spec is None: + options.tx_subdev_spec = usrp.pick_tx_subdevice(fg.u) + + m = usrp.determine_tx_mux_value(fg.u, options.tx_subdev_spec) + #print "mux = %#04x" % (m,) + fg.u.set_mux(m) + fg.subdev = usrp.selected_subdev(fg.u, options.tx_subdev_spec) + print "Using TX d'board %s" % (fg.subdev.side_and_name(),) + + fg.subdev.set_gain(fg.subdev.gain_range()[1]) # set max Tx gain + + if not fg.set_freq(options.rf_freq): + sys.stderr.write('Failed to set RF frequency\n') + raise SystemExit + + fg.subdev.set_enable(True) # enable transmitter + + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/usrp/usrp_tv_rcv.py b/gnuradio-examples/python/usrp/usrp_tv_rcv.py new file mode 100755 index 00000000..ed78273a --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_tv_rcv.py @@ -0,0 +1,394 @@ +#!/usr/bin/env python +""" +Realtime capture and display of analog Tv stations. +Can also use a file as source or sink +When you use an output file you can show the results frame-by-frame using ImageMagick +When you want to use the realtime sdl display window you must first install gr-video-sdl (is in gnuradio cvs). +When you use a file source, in stead of the usrp, make sure you capture interleaved shorts. +(Use usrp_rx_file.py, or use usrp_rx_cfile.py --output-shorts if you have a recent enough usrp_rx_cfile.py) +There is no synchronisation yet. The sync blocks are in development but not yet in cvs. + +""" +from gnuradio import gr, gru, eng_notation, optfir +try: + from gnuradio import video_sdl +except: + print "FYI: gr-video-sdl is not installed" + print "realtime SDL video output window will not be available" +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import slider, powermate +from gnuradio.wxgui import stdgui, fftsink, form +from optparse import OptionParser +import usrp_dbid +import sys +import math +import wx + +# To debug, insert this in your test code... +#import os +#print 'Blocked waiting for GDB attach (pid = %d)' % (os.getpid(),) +#raw_input ('Press Enter to continue: ') +# remainder of your test code follows... + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. + + @return a subdev_spec + """ + return usrp.pick_subdev(u, (usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.BASIC_RX)) + + +class tv_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + usage="%prog: [options] [input_filename]. \n If you don't specify an input filename the usrp will be used as source\n " \ + "Make sure your input capture file containes interleaved shorts not complex floats" + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=64, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=519.25e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-c", "--contrast", type="eng_float", default=1.0, + help="set contrast (default is 1.0)") + parser.add_option("-b", "--brightness", type="eng_float", default=0.0, + help="set brightness (default is 0)") + parser.add_option("-8", "--width-8", action="store_true", default=False, + help="Enable 8-bit samples across USB") + parser.add_option("-p", "--pal", action="store_true", default=False, + help="PAL video format (this is the default)") + parser.add_option("-n", "--ntsc", action="store_true", default=False, + help="NTSC video format") + parser.add_option("-o", "--out-filename", type="string", default="sdl", + help="For example out_raw_uchar.gray. If you don't specify an output filename you will get a video_sink_sdl realtime output window. You then need to have gr-video-sdl installed)") + parser.add_option("-r", "--repeat", action="store_false", default=True, + help="repeat file in a loop") + parser.add_option("-N", "--no-hb", action="store_true", default=False, + help="don't use halfband filter in usrp") + + (options, args) = parser.parse_args() + if not ((len(args) == 1) or (len(args) == 0)): + parser.print_help() + sys.exit(1) + + if len(args) == 1: + filename = args[0] + else: + filename = None + + self.frame = frame + self.panel = panel + + self.contrast = options.contrast + self.brightness = options.brightness + self.state = "FREQ" + self.freq = 0 + + # build graph + + self.u=None + + usrp_decim = options.decim # 32 + + if not (options.out_filename=="sdl"): + options.repeat=False + + if not ((filename is None) or (filename=="usrp")): + self.filesource = gr.file_source(gr.sizeof_short,filename,options.repeat) # file is data source + self.istoc = gr.interleaved_short_to_complex() + self.connect(self.filesource,self.istoc) + adc_rate=64e6 + self.src=self.istoc + options.gain=0.0 + self.gain=0.0 + else: + if options.no_hb or (options.decim<8): + self.fpga_filename="std_4rx_0tx.rbf" #contains 4 Rx paths without halfbands and 0 tx paths + else: + self.fpga_filename="std_2rxhb_2tx.rbf" # contains 2 Rx paths with halfband filters and 2 tx paths (the default) + self.u = usrp.source_c(0,fpga_filename=self.fpga_filename) # usrp is data source + if options.width_8: + sample_width = 8 + sample_shift = 8 + format = self.u.make_format(sample_width, sample_shift) + r = self.u.set_format(format) + adc_rate = self.u.adc_rate() # 64 MS/s + self.u.set_decim_rate(usrp_decim) + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + self.src=self.u + + usrp_rate = adc_rate / usrp_decim # 320 kS/s + + f2uc=gr.float_to_uchar() + # sdl window as final sink + if not (options.pal or options.ntsc): + options.pal=True #set default to PAL + if options.pal: + lines_per_frame=625.0 + frames_per_sec=25.0 + show_width=768 + elif options.ntsc: + lines_per_frame=525.0 + frames_per_sec=29.97002997 + show_width=640 + width=int(usrp_rate/(lines_per_frame*frames_per_sec)) + height=int(lines_per_frame) + + if (options.out_filename=="sdl"): + #Here comes the tv screen, you have to build and install gr-video-sdl for this (subproject of gnuradio, only in cvs for now) + try: + video_sink = video_sdl.sink_uc ( frames_per_sec, width, height,0,show_width,height) + except: + print "gr-video-sdl is not installed" + print "realtime \"sdl\" video output window is not available" + raise SystemExit, 1 + self.dst=video_sink + else: + print "You can use the imagemagick display tool to show the resulting imagesequence" + print "use the following line to show the demodulated TV-signal:" + print "display -depth 8 -size " +str(width)+ "x" + str(height) + " gray:" + options.out_filename + print "(Use the spacebar to advance to next frames)" + options.repeat=False + file_sink=gr.file_sink(gr.sizeof_char, options.out_filename) + self.dst =file_sink + + self.agc=gr.agc_cc(1e-7,1.0,1.0) #1e-7 + self.am_demod = gr.complex_to_mag () + self.set_blacklevel=gr.add_const_ff(0.0) + self.invert_and_scale = gr.multiply_const_ff (0.0) #-self.contrast *128.0*255.0/(200.0) + + # now wire it all together + #sample_rate=options.width*options.height*options.framerate + + process_type='do_no_sync' + if process_type=='do_no_sync': + self.connect (self.src, self.agc,self.am_demod,self.invert_and_scale, self.set_blacklevel,f2uc,self.dst) + elif process_type=='do_tv_sync_adv': + #defaults: gr.tv_sync_adv (double sampling_freq, unsigned int tv_format,bool output_active_video_only=false, bool do_invert=false, double wanted_black_level=0.0, double wanted_white_level=255.0, double avg_alpha=0.1, double initial_gain=1.0, double initial_offset=0.0,bool debug=false) + self.tv_sync_adv=gr.tv_sync_adv(usrp_rate,0,False,False,0.0,255.0,0.01,1.0,0.0,False) #note, this block is not yet in cvs + self.connect (self.src, self.am_demod,self.invert_and_scale,self.tv_sync_adv,s2f,f2uc,self.dst) + elif process_type=='do_nullsink': + #self.connect (self.src, self.am_demod,self.invert_and_scale,f2uc,video_sink) + c2r=gr.complex_to_real() + nullsink=gr.null_sink(gr.sizeof_float) + self.connect (self.src, c2r,nullsink) #video_sink) + elif process_type=='do_tv_sync_corr': + frame_size=width*height #int(usrp_rate/25.0) + nframes=10# 32 + search_window=20*nframes + debug=False + video_alpha=0.3 #0.1 + corr_alpha=0.3 + tv_corr=gr.tv_correlator_ff(frame_size,nframes, search_window, video_alpha, corr_alpha,debug) #Note: this block is not yet in cvs + shift=gr.add_const_ff(-0.7) + self.connect (self.src, self.agc,self.am_demod,tv_corr,self.invert_and_scale, self.set_blacklevel,f2uc,self.dst) #self.agc, + else: # process_type=='do_test_image': + src_vertical_bars = gr.sig_source_f (usrp_rate, gr.GR_SIN_WAVE, 10.0 *usrp_rate/320, 255,128) + self.connect(src_vertical_bars,f2uc,self.dst) + + self._build_gui(vbox, usrp_rate, usrp_rate, usrp_rate) + + + if abs(options.freq) < 1e6: + options.freq *= 1e6 + + # set initial values + self.set_gain(options.gain) + self.set_contrast(self.contrast) + self.set_brightness(options.brightness) + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + + def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + + if 0: + self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP", + fft_size=512, sample_rate=usrp_rate) + self.connect (self.src, self.src_fft) + vbox.Add (self.src_fft.win, 4, wx.EXPAND) + + if 0: + post_demod_fft = fftsink.fft_sink_f (self, self.panel, title="Post Demod", + fft_size=512, sample_rate=demod_rate, + y_per_div=10, ref_level=-40) + self.connect (self.am_demod, post_demod_fft) + vbox.Add (post_demod_fft.win, 4, wx.EXPAND) + + if 0: + post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=-40) + self.connect (self.set_blacklevel, post_filt) + vbox.Add (fft_win4, 4, wx.EXPAND) + + + # control area form at bottom + self.myform = myform = form.form() + + if not (self.u is None): + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0) + myform['freq_slider'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, + range=(50.25e6, 900.25e6, 0.25e6), + callback=self.set_freq) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['contrast'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Contrast", + weight=3, range=(-2.0, 2.0, 0.1), + callback=self.set_contrast) + hbox.Add((5,0), 1) + + myform['brightness'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Brightness", + weight=3, range=(-255.0, 255.0, 1.0), + callback=self.set_brightness) + hbox.Add((5,0), 0) + + if not (self.u is None): + myform['gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, range=self.subdev.gain_range(), + callback=self.set_gain) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + try: + self.knob = powermate.powermate(self.frame) + self.rot = 0 + powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button) + except: + print "FYI: No Powermate or Contour Knob found" + + + def on_rotate (self, event): + self.rot += event.delta + if (self.state == "FREQ"): + if self.rot >= 3: + self.set_freq(self.freq + .1e6) + self.rot -= 3 + elif self.rot <=-3: + self.set_freq(self.freq - .1e6) + self.rot += 3 + elif (self.state == "CONTRAST"): + step = 0.1 + if self.rot >= 3: + self.set_contrast(self.contrast + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_contrast(self.contrast - step) + self.rot += 3 + else: + step = 1 + if self.rot >= 3: + self.set_brightness(self.brightness + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_brightness(self.brightness - step) + self.rot += 3 + + def on_button (self, event): + if event.value == 0: # button up + return + self.rot = 0 + if self.state == "FREQ": + self.state = "CONTRAST" + elif self.state == "CONTRAST": + self.state = "BRIGHTNESS" + else: + self.state = "FREQ" + self.update_status_bar () + + + def set_contrast (self, contrast): + self.contrast = contrast + self.invert_and_scale.set_k(-self.contrast *128.0*255.0/(200.0)) + self.myform['contrast'].set_value(self.contrast) + self.update_status_bar () + + def set_brightness (self, brightness): + self.brightness = brightness + self.set_blacklevel.set_k(self.brightness +255.0) + self.myform['brightness'].set_value(self.brightness) + self.update_status_bar () + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + if not (self.u is None): + r = usrp.tune(self.u, 0, self.subdev, target_freq) + if r: + self.freq = target_freq + self.myform['freq'].set_value(target_freq) # update displayed value + self.myform['freq_slider'].set_value(target_freq) # update displayed value + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + if not (self.u is None): + self.gain=gain + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + self.update_status_bar() + + def update_status_bar (self): + msg = "Setting:%s Contrast:%r Brightness:%r Gain: %r" % (self.state, self.contrast,self.brightness,self.gain) + self._set_status_msg(msg, 1) + #self.src_fft.set_baseband_freq(self.freq) + + + +if __name__ == '__main__': + app = stdgui.stdapp (tv_rx_graph, "USRP TV RX black-and-white") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py b/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py new file mode 100755 index 00000000..e563188b --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python + +""" +Reads from a file and generates PAL TV pictures in black and white +which can be displayed using ImageMagick or realtime using gr-video-sdl +(To capture the input file Use usrp_rx_file.py, or use usrp_rx_cfile.py --output-shorts if you have a recent enough usrp_rx_cfile.py) +Can also use usrp directly as capture source, but then you need a higher decimation factor (64) +and thus get a lower horizontal resulution. +There is no synchronisation yet. The sync blocks are in development but not yet in cvs. + +""" + +from gnuradio import gr, eng_notation +from gnuradio import audio +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +try: + from gnuradio import video_sdl +except: + print "FYI: gr-video-sdl is not installed" + print "realtime \"sdl\" video output window will not be available" + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] output_filename. \n Special output_filename \"sdl\" will use video_sink_sdl as realtime output window. " \ + "You then need to have gr-video-sdl installed. \n" \ + "Make sure your input capture file containes interleaved shorts not complex floats" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-c", "--contrast", type="eng_float", default=1.0, + help="set contrast (default is 1.0)") + parser.add_option("-b", "--brightness", type="eng_float", default=0.0, + help="set brightness (default is 0)") + parser.add_option("-d", "--decim", type="int", default=8, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-i", "--in-filename", type="string", default=None, + help="Use input file as source. samples must be interleaved shorts \n " + + "Use usrp_rx_file.py or usrp_rx_cfile.py --output-shorts. \n" + "Special name \"usrp\" results in realtime capturing and processing using usrp. \n" + + "You then probably need a decimation factor of 64 or higher.") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ.\nNote that the frequency of the video carrier is not at the middle of the TV channel", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-p", "--pal", action="store_true", default=False, + help="PAL video format (this is the default)") + parser.add_option("-n", "--ntsc", action="store_true", default=False, + help="NTSC video format") + parser.add_option("-r", "--repeat", action="store_false", default=True, + help="repeat in_file in a loop") + parser.add_option("-8", "--width-8", action="store_true", default=False, + help="Enable 8-bit samples across USB") + parser.add_option("-N", "--nframes", type="eng_float", default=None, + help="number of frames to collect [default=+inf]") + parser.add_option( "--no-hb", action="store_true", default=False, + help="don't use halfband filter in usrp") + (options, args) = parser.parse_args () + if not (len(args) == 1): + parser.print_help() + sys.stderr.write('You must specify the output. FILENAME or sdl \n'); + sys.exit(1) + + filename = args[0] + + if options.in_filename is None: + parser.print_help() + sys.stderr.write('You must specify the input -i FILENAME or -i usrp\n'); + raise SystemExit, 1 + + if not (filename=="sdl"): + options.repeat=False + + if not (options.in_filename=="usrp"): + self.filesource = gr.file_source(gr.sizeof_short,options.in_filename,options.repeat) # file is data source, capture with usr_rx_csfile.py + self.istoc = gr.interleaved_short_to_complex() + self.connect(self.filesource,self.istoc) + self.adc_rate=64e6 + self.src=self.istoc + else: + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + if abs(options.freq) < 1e6: + options.freq *= 1e6 + if options.no_hb or (options.decim<8): + self.fpga_filename="std_4rx_0tx.rbf" #contains 4 Rx paths without halfbands and 0 tx paths + else: + self.fpga_filename="std_2rxhb_2tx.rbf" # contains 2 Rx paths with halfband filters and 2 tx paths (the default) + + # build the graph + self.u = usrp.source_c(decim_rate=options.decim,fpga_filename=self.fpga_filename) + self.src=self.u + if options.width_8: + sample_width = 8 + sample_shift = 8 + format = self.u.make_format(sample_width, sample_shift) + r = self.u.set_format(format) + self.adc_rate=self.u.adc_freq() + if options.rx_subdev_spec is None: + options.rx_subdev_spec = usrp.pick_rx_subdevice(self.u) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + self.subdev.set_gain(options.gain) + + r = self.u.tune(0, self.subdev, options.freq) + if not r: + sys.stderr.write('Failed to set frequency\n') + raise SystemExit, 1 + + input_rate = self.adc_rate / options.decim + print "video sample rate %s" % (eng_notation.num_to_str(input_rate)) + + self.agc=gr.agc_cc(1e-7,1.0,1.0) #1e-7 + self.am_demod = gr.complex_to_mag () + self.set_blacklevel=gr.add_const_ff(options.brightness +255.0) + self.invert_and_scale = gr.multiply_const_ff (-options.contrast *128.0*255.0/(200.0)) + self.f2uc=gr.float_to_uchar() + + # sdl window as final sink + if not (options.pal or options.ntsc): + options.pal=True #set default to PAL + if options.pal: + lines_per_frame=625.0 + frames_per_sec=25.0 + show_width=768 + elif options.ntsc: + lines_per_frame=525.0 + frames_per_sec=29.97002997 + show_width=640 + width=int(input_rate/(lines_per_frame*frames_per_sec)) + height=int(lines_per_frame) + + if filename=="sdl": + #Here comes the tv screen, you have to build and install gr-video-sdl for this (subproject of gnuradio, only in cvs for now) + try: + video_sink = video_sdl.sink_uc ( frames_per_sec, width, height,0,show_width,height) + except: + print "gr-video-sdl is not installed" + print "realtime \"sdl\" video output window is not available" + raise SystemExit, 1 + self.dst=video_sink + else: + print "You can use the imagemagick display tool to show the resulting imagesequence" + print "use the following line to show the demodulated TV-signal:" + print "display -depth 8 -size " +str(width)+ "x" + str(height) + " gray:" +filename + print "(Use the spacebar to advance to next frames)" + file_sink=gr.file_sink(gr.sizeof_char, filename) + self.dst =file_sink + + if options.nframes is None: + self.connect(self.src, self.agc) + else: + self.head = gr.head(gr.sizeof_gr_complex, int(options.nframes*width*height)) + self.connect(self.src, self.head, self.agc) + + self.connect (self.agc,self.am_demod,self.invert_and_scale, self.set_blacklevel,self.f2uc,self.dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv.py new file mode 100755 index 00000000..20291076 --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import slider, powermate +from gnuradio.wxgui import stdgui, fftsink, form +from optparse import OptionParser +import usrp_dbid +import sys +import math +import wx + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. + + @return a subdev_spec + """ + return usrp.pick_subdev(u, (usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.BASIC_RX)) + + +class wfm_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("-f", "--freq", type="eng_float", default=100.1e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=40, + help="set gain in dB (default is midpoint)") + parser.add_option("-V", "--volume", type="eng_float", default=None, + help="set volume (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.frame = frame + self.panel = panel + + self.vol = 0 + self.state = "FREQ" + self.freq = 0 + + # build graph + + self.u = usrp.source_c() # usrp is data source + + adc_rate = self.u.adc_rate() # 64 MS/s + usrp_decim = 200 + self.u.set_decim_rate(usrp_decim) + usrp_rate = adc_rate / usrp_decim # 320 kS/s + chanfilt_decim = 1 + demod_rate = usrp_rate / chanfilt_decim + audio_decimation = 10 + audio_rate = demod_rate / audio_decimation # 32 kHz + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + + chan_filt_coeffs = optfir.low_pass (1, # gain + usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + + self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation) + + self.volume_control = gr.multiply_const_ff(self.vol) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate), + options.audio_output, + False) # ok_to_block + + # now wire it all together + self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) + + self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.volume is None: + g = self.volume_range() + options.volume = float(g[0]+g[1])/2 + + if abs(options.freq) < 1e6: + options.freq *= 1e6 + + # set initial values + + self.set_gain(options.gain) + self.set_vol(options.volume) + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + + def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + + if 1: + self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP", + fft_size=512, sample_rate=usrp_rate) + self.connect (self.u, self.src_fft) + vbox.Add (self.src_fft.win, 4, wx.EXPAND) + + if 1: + post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Demod", + fft_size=1024, sample_rate=usrp_rate, + y_per_div=10, ref_level=0) + self.connect (self.guts.fm_demod, post_filt_fft) + vbox.Add (post_filt_fft.win, 4, wx.EXPAND) + + if 0: + post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=-20) + self.connect (self.guts.deemph, post_deemph_fft) + vbox.Add (post_deemph_fft.win, 4, wx.EXPAND) + + + # control area form at bottom + self.myform = myform = form.form() + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0) + myform['freq_slider'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, + range=(87.9e6, 108.1e6, 0.1e6), + callback=self.set_freq) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['volume'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", + weight=3, range=self.volume_range(), + callback=self.set_vol) + hbox.Add((5,0), 1) + + myform['gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, range=self.subdev.gain_range(), + callback=self.set_gain) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + try: + self.knob = powermate.powermate(self.frame) + self.rot = 0 + powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button) + except: + print "FYI: No Powermate or Contour Knob found" + + + def on_rotate (self, event): + self.rot += event.delta + if (self.state == "FREQ"): + if self.rot >= 3: + self.set_freq(self.freq + .1e6) + self.rot -= 3 + elif self.rot <=-3: + self.set_freq(self.freq - .1e6) + self.rot += 3 + else: + step = self.volume_range()[2] + if self.rot >= 3: + self.set_vol(self.vol + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_vol(self.vol - step) + self.rot += 3 + + def on_button (self, event): + if event.value == 0: # button up + return + self.rot = 0 + if self.state == "FREQ": + self.state = "VOL" + else: + self.state = "FREQ" + self.update_status_bar () + + + def set_vol (self, vol): + g = self.volume_range() + self.vol = max(g[0], min(g[1], vol)) + self.volume_control.set_k(10**(self.vol/10)) + self.myform['volume'].set_value(self.vol) + self.update_status_bar () + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = usrp.tune(self.u, 0, self.subdev, target_freq) + + if r: + self.freq = target_freq + self.myform['freq'].set_value(target_freq) # update displayed value + self.myform['freq_slider'].set_value(target_freq) # update displayed value + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + def update_status_bar (self): + msg = "Volume:%r Setting:%s" % (self.vol, self.state) + self._set_status_msg(msg, 1) + self.src_fft.set_baseband_freq(self.freq) + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + +if __name__ == '__main__': + app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py new file mode 100755 index 00000000..40e7dd75 --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import usrp_dbid +import sys +import math + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. + + @return a subdev_spec + """ + return usrp.pick_subdev(u, (usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.BASIC_RX)) + + +class wfm_rx_graph (gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("", "--f1", type="eng_float", default=100.7e6, + help="set 1st station frequency to FREQ", metavar="FREQ") + parser.add_option("", "--f2", type="eng_float", default=102.5e6, + help="set 2nd station freq to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=40, + help="set gain in dB (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if abs(options.f1) < 1e6: + options.f1 *= 1e6 + + if abs(options.f2) < 1e6: + options.f2 *= 1e6 + + if abs(options.f1 - options.f2) > 5.5e6: + print "Sorry, two stations must be within 5.5MHz of each other" + raise SystemExit + + f = (options.f1, options.f2) + + self.vol = .1 + self.state = "FREQ" + + # build graph + + self.u = usrp.source_c(0, nchan=2) # usrp is data source + + adc_rate = self.u.adc_rate() # 64 MS/s + usrp_decim = 200 + self.u.set_decim_rate(usrp_decim) + usrp_rate = adc_rate / usrp_decim # 320 kS/s + chanfilt_decim = 1 + demod_rate = usrp_rate / chanfilt_decim + audio_decimation = 10 + audio_rate = demod_rate / audio_decimation # 32 kHz + + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + + mv = usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec) + mv |= (mv << 8) & 0xff00 # both DDC inputs setup same way + self.u.set_mux(mv) + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + + # deinterleave two channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + # wire up the head of the chain + self.connect(self.u, di) + + # sound card as final sink + audio_sink = audio.sink(int(audio_rate), options.audio_output) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + mid_freq = (f[0] + f[1]) / 2 + # set front end PLL to middle frequency + ok, baseband_freq = self.subdev.set_freq(mid_freq) + + for n in range(2): + chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + guts = blks.wfm_rcv (self, demod_rate, audio_decimation) + volume_control = gr.multiply_const_ff(self.vol) + self.connect((di, n), chan_filt) + self.connect(chan_filt, guts, volume_control) + self.connect(volume_control, (audio_sink, n)) + dxc_freq, inverted = usrp.calc_dxc_freq(f[n], baseband_freq, + self.u.converter_rate()) + self.u.set_rx_freq(n, dxc_freq) + + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + + # set initial values + self.set_gain(options.gain) + + + def set_vol (self, vol): + self.vol = vol + self.volume_control.set_k(self.vol) + + + def set_gain(self, gain): + self.subdev.set_gain(gain) + + +if __name__ == '__main__': + fg = wfm_rx_graph() + try: + fg.run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py new file mode 100755 index 00000000..69f810bb --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import usrp_dbid +import sys +import math + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. + + @return a subdev_spec + """ + return usrp.pick_subdev(u, (usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.BASIC_RX)) + + +class wfm_rx_graph (gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("-f", "--freq", type="eng_float", default=100.1e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.vol = .1 + self.state = "FREQ" + self.freq = 0 + + # build graph + + self.u = usrp.source_c() # usrp is data source + + adc_rate = self.u.adc_rate() # 64 MS/s + usrp_decim = 200 + self.u.set_decim_rate(usrp_decim) + usrp_rate = adc_rate / usrp_decim # 320 kS/s + chanfilt_decim = 1 + demod_rate = usrp_rate / chanfilt_decim + audio_decimation = 10 + audio_rate = demod_rate / audio_decimation # 32 kHz + + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + + chan_filt_coeffs = optfir.low_pass (1, # gain + usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + + self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation) + + self.volume_control = gr.multiply_const_ff(self.vol) + + # sound card as final sink + audio_sink = audio.sink(int(audio_rate), + options.audio_output, + False) # ok_to_block + + # now wire it all together + self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) + + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if abs(options.freq) < 1e6: + options.freq *= 1e6 + + # set initial values + + self.set_gain(options.gain) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + def set_vol (self, vol): + self.vol = vol + self.volume_control.set_k(self.vol) + self.update_status_bar () + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = self.u.tune(0, self.subdev, target_freq) + + if r: + self.freq = target_freq + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + self.subdev.set_gain(gain) + + def update_status_bar (self): + msg = "Freq: %s Volume:%f Setting:%s" % ( + eng_notation.num_to_str(self.freq), self.vol, self.state) + self._set_status_msg(msg, 1) + + def _set_status_msg(self, msg, which=0): + print msg + + +if __name__ == '__main__': + fg = wfm_rx_graph() + try: + fg.run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py b/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py new file mode 100755 index 00000000..773076ae --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py @@ -0,0 +1,311 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import slider, powermate +from gnuradio.wxgui import stdgui, fftsink, form, scopesink +from optparse import OptionParser +import usrp_dbid +import sys +import math +import wx + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. + + @return a subdev_spec + """ + return usrp.pick_subdev(u, (usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.BASIC_RX)) + +class wfm_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("-f", "--freq", type="eng_float", default=100.1e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=65, + help="set gain in dB (default is midpoint)") + parser.add_option("-s", "--squelch", type="eng_float", default=0, + help="set squelch level (default is 0)") + parser.add_option("-V", "--volume", type="eng_float", default=None, + help="set volume (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.frame = frame + self.panel = panel + + self.vol = 0 + self.state = "FREQ" + self.freq = 0 + + # build graph + + self.u = usrp.source_c() # usrp is data source + + adc_rate = self.u.adc_rate() # 64 MS/s + usrp_decim = 200 + self.u.set_decim_rate(usrp_decim) + usrp_rate = adc_rate / usrp_decim # 320 kS/s + chanfilt_decim = 1 + demod_rate = usrp_rate / chanfilt_decim + audio_decimation = 10 + audio_rate = demod_rate / audio_decimation # 32 kHz + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + + + chan_filt_coeffs = optfir.low_pass (1, # gain + usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + + + #self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation) + self.guts = blks.wfm_rcv_pll (self, demod_rate, audio_decimation) + + # FIXME rework {add,multiply}_const_* to handle multiple streams + self.volume_control_l = gr.multiply_const_ff(self.vol) + self.volume_control_r = gr.multiply_const_ff(self.vol) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate), + options.audio_output, + False) # ok_to_block + + # now wire it all together + self.connect (self.u, chan_filt, self.guts) + self.connect ((self.guts, 0), self.volume_control_l, (audio_sink, 0)) + self.connect ((self.guts, 1), self.volume_control_r, (audio_sink, 1)) + self.guts.stereo_carrier_pll_recovery.squelch_enable(True); + + self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.volume is None: + g = self.volume_range() + options.volume = float(g[0]+g[1])/2 + + if abs(options.freq) < 1e6: + options.freq *= 1e6 + + # set initial values + + self.set_gain(options.gain) + self.set_vol(options.volume) + self.guts.stereo_carrier_pll_recovery.set_lock_threshold(options.squelch); + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + + def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + + if 1: + self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP", + fft_size=512, sample_rate=usrp_rate) + self.connect (self.u, self.src_fft) + vbox.Add (self.src_fft.win, 4, wx.EXPAND) + + if 1: + post_fm_demod_fft = fftsink.fft_sink_f (self, self.panel, title="Post FM Demod", + fft_size=512, sample_rate=demod_rate, + y_per_div=10, ref_level=0) + self.connect (self.guts.fm_demod, post_fm_demod_fft) + vbox.Add (post_fm_demod_fft.win, 4, wx.EXPAND) + + if 0: + post_stereo_carrier_generator_fft = fftsink.fft_sink_c (self, self.panel, title="Post Stereo_carrier_generator", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=0) + self.connect (self.guts.stereo_carrier_generator, post_stereo_carrier_generator_fft) + vbox.Add (post_stereo_carrier_generator_fft.win, 4, wx.EXPAND) + + if 0: + post_deemphasis_left = fftsink.fft_sink_f (self, self.panel, title="Post_Deemphasis_Left", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=0) + self.connect (self.guts.deemph_Left, post_deemphasis_left) + vbox.Add (post_deemphasis_left.win, 4, wx.EXPAND) + + if 0: + post_deemphasis_right = fftsink.fft_sink_f (self, self.panel, title="Post_Deemphasis_Right", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=-20) + self.connect (self.guts.deemph_Left, post_deemphasis_right) + vbox.Add (post_deemphasis_right.win, 4, wx.EXPAND) + + + if 0: + LmR_fft = fftsink.fft_sink_f (self, self.panel, title="LmR", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=-20) + self.connect (self.guts.LmR_real,LmR_fft) + vbox.Add (LmR_fft.win, 4, wx.EXPAND) + + if 0: + self.scope = scopesink.scope_sink_f(self, self.panel, sample_rate=demod_rate) + self.connect (self.guts.fm_demod_a,self.scope) + vbox.Add (self.scope.win,4,wx.EXPAND) + + # control area form at bottom + self.myform = myform = form.form() + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0) + myform['freq_slider'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, + range=(87.9e6, 108.1e6, 0.1e6), + callback=self.set_freq) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['volume'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", + weight=3, range=self.volume_range(), + callback=self.set_vol) + hbox.Add((5,0), 1) + + myform['gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, range=self.subdev.gain_range(), + callback=self.set_gain) + hbox.Add((5,0), 0) + + myform['sqlch_thrsh'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Stereo Squelch Threshold", + weight=3, range=(0.0,1.0,0.01), + callback=self.guts.stereo_carrier_pll_recovery.set_lock_threshold) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + try: + self.knob = powermate.powermate(self.frame) + self.rot = 0 + powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button) + except: + print "FYI: No Powermate or Contour Knob found" + + + def on_rotate (self, event): + self.rot += event.delta + if (self.state == "FREQ"): + if self.rot >= 3: + self.set_freq(self.freq + .1e6) + self.rot -= 3 + elif self.rot <=-3: + self.set_freq(self.freq - .1e6) + self.rot += 3 + else: + step = self.volume_range()[2] + if self.rot >= 3: + self.set_vol(self.vol + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_vol(self.vol - step) + self.rot += 3 + + def on_button (self, event): + if event.value == 0: # button up + return + self.rot = 0 + if self.state == "FREQ": + self.state = "VOL" + else: + self.state = "FREQ" + self.update_status_bar () + + + def set_vol (self, vol): + g = self.volume_range() + self.vol = max(g[0], min(g[1], vol)) + self.volume_control_l.set_k(10**(self.vol/10)) + self.volume_control_r.set_k(10**(self.vol/10)) + self.myform['volume'].set_value(self.vol) + self.update_status_bar () + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = usrp.tune(self.u, 0, self.subdev, target_freq) + + if r: + self.freq = target_freq + self.myform['freq'].set_value(target_freq) # update displayed value + self.myform['freq_slider'].set_value(target_freq) # update displayed value + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + def update_status_bar (self): + msg = "Volume:%r Setting:%s" % (self.vol, self.state) + self._set_status_msg(msg, 1) + self.src_fft.set_baseband_freq(self.freq) + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + +if __name__ == '__main__': + app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py b/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py new file mode 100755 index 00000000..7c04c988 --- /dev/null +++ b/gnuradio-examples/python/usrp/usrp_wxapt_rcv.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import slider, powermate +from gnuradio.wxgui import stdgui, fftsink, form +from optparse import OptionParser +import usrp_dbid +import sys +import math +import wx + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. + + @return a subdev_spec + """ + return usrp.pick_subdev(u, (usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.BASIC_RX)) + + +class wxapt_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=A)") + parser.add_option("-f", "--freq", type="eng_float", default=137.5e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-V", "--volume", type="eng_float", default=None, + help="set volume (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.frame = frame + self.panel = panel + + self.vol = 0 + self.state = "FREQ" + self.freq = 0 + + # build graph + + self.u = usrp.source_c() # usrp is data source + + adc_rate = self.u.adc_rate() # 64 MS/s + usrp_decim = 200 + self.u.set_decim_rate(usrp_decim) + usrp_rate = adc_rate / usrp_decim # 320 kS/s + chanfilt_decim = 4 + demod_rate = usrp_rate / chanfilt_decim + audio_decimation = 10 + audio_rate = demod_rate / audio_decimation # 32 kHz + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + + chan_filt_coeffs = optfir.low_pass (1, # gain + usrp_rate, # sampling rate + 40e3, # passband cutoff + 60e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + + self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation) + + self.volume_control = gr.multiply_const_ff(self.vol) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate), options.audio_output) + + # now wire it all together + self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) + + self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.volume is None: + g = self.volume_range() + options.volume = float(g[0]+g[1])/2 + + if abs(options.freq) < 1e6: + options.freq *= 1e6 + + # set initial values + + self.set_gain(options.gain) + self.set_vol(options.volume) + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + + def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + + if 1: + self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP", + fft_size=512, sample_rate=usrp_rate) + self.connect (self.u, self.src_fft) + vbox.Add (self.src_fft.win, 4, wx.EXPAND) + + if 1: + post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph", + fft_size=512, sample_rate=demod_rate, + y_per_div=10, ref_level=-20) + self.connect (self.guts.deemph, post_deemph_fft) + vbox.Add (post_deemph_fft.win, 4, wx.EXPAND) + + if 1: + post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=0) + self.connect (self.guts.audio_filter, post_filt_fft) + vbox.Add (post_filt_fft.win, 4, wx.EXPAND) + + + # control area form at bottom + self.myform = myform = form.form() + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0) + myform['freq_slider'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, + range=(137.0e6, 138.0e6, 0.0005e6), + callback=self.set_freq) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['volume'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", + weight=3, range=self.volume_range(), + callback=self.set_vol) + hbox.Add((5,0), 1) + + myform['gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, range=self.subdev.gain_range(), + callback=self.set_gain) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + try: + self.knob = powermate.powermate(self.frame) + self.rot = 0 + powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button) + except: + print "FYI: No Powermate or Contour Knob found" + + + def on_rotate (self, event): + self.rot += event.delta + if (self.state == "FREQ"): + if self.rot >= 3: + self.set_freq(self.freq + .1e6) + self.rot -= 3 + elif self.rot <=-3: + self.set_freq(self.freq - .1e6) + self.rot += 3 + else: + step = self.volume_range()[2] + if self.rot >= 3: + self.set_vol(self.vol + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_vol(self.vol - step) + self.rot += 3 + + def on_button (self, event): + if event.value == 0: # button up + return + self.rot = 0 + if self.state == "FREQ": + self.state = "VOL" + else: + self.state = "FREQ" + self.update_status_bar () + + + def set_vol (self, vol): + g = self.volume_range() + self.vol = max(g[0], min(g[1], vol)) + self.volume_control.set_k(10**(self.vol/10)) + self.myform['volume'].set_value(self.vol) + self.update_status_bar () + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = usrp.tune(self.u, 0, self.subdev, target_freq) + + if r: + self.freq = target_freq + self.myform['freq'].set_value(target_freq) # update displayed value + self.myform['freq_slider'].set_value(target_freq) # update displayed value + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + def update_status_bar (self): + msg = "Volume:%r Setting:%s" % (self.vol, self.state) + self._set_status_msg(msg, 1) + self.src_fft.set_baseband_freq(self.freq) + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + +if __name__ == '__main__': + app = stdgui.stdapp (wxapt_rx_graph, "USRP WXAPT RX") + app.MainLoop () diff --git a/gnuradio-examples/python/usrp/wfm_rcv_file.py b/gnuradio-examples/python/usrp/wfm_rcv_file.py new file mode 100755 index 00000000..2c8d4f76 --- /dev/null +++ b/gnuradio-examples/python/usrp/wfm_rcv_file.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +from gnuradio import gr, eng_notation +from gnuradio import audio +# from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + + +# +# return a gr.flow_graph +# +def build_graph (input_filename, repeat): + adc_rate = 64e6 # USRP A/D sampling rate + decim = 250 # FPGA decimated by this amount + + quad_rate = adc_rate / decim # 256 kHz (the sample rate of the file) + audio_decimation = 8 + audio_rate = quad_rate / audio_decimation # 32 kHz + + fg = gr.flow_graph () + + # usrp is data source + # src = usrp.source_c (0, decim) + # src.set_rx_freq (0, -IF_freq) + + src = gr.file_source (gr.sizeof_gr_complex, input_filename, repeat) + + (head, tail) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, head) + fg.connect (tail, (audio_sink, 0)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverteed complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + TAU = 75e-6 # 75us in US, 50us in EUR + fftaps = [ 1 - math.exp(-1/TAU/quad_rate), 0] + fbtaps= [ 0 , math.exp(-1/TAU/quad_rate) ] + deemph = gr.iir_filter_ffd(fftaps,fbtaps) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, deemph) + fg.connect (deemph, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (): + usage = "usage: %prog [options] filename" + parser = OptionParser (option_class=eng_option, usage=usage) + parser.add_option ("-r", "--repeat", action="store_true", default=False) + # parser.add_option (... your stuff here...) + (options, args) = parser.parse_args () + + if len (args) != 1: + parser.print_help () + sys.exit (1) + + fg = build_graph (args[0], options.repeat) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main () + + diff --git a/gr-atsc/AUTHORS b/gr-atsc/AUTHORS new file mode 100644 index 00000000..fe4e73c3 --- /dev/null +++ b/gr-atsc/AUTHORS @@ -0,0 +1,3 @@ +Eric Blossom +Matt Ettus + diff --git a/gr-atsc/ChangeLog b/gr-atsc/ChangeLog new file mode 100644 index 00000000..e11f5202 --- /dev/null +++ b/gr-atsc/ChangeLog @@ -0,0 +1,37 @@ +2006-03-23 Eric Blossom + + * src/lib/atsc_rs_encoder.{h,cc}, src/lib/atsc_rs_decoder.{h,cc}: + ported from old ATSC code. + * src/lib/atsci_reed_solomon.{h,cc}: const correctness fix. + * src/lib/atsc_randomizer.{h,cc}, src/lib/atsc_derandomizer.{h,cc}: + ported from old ATSC code. + * src/python/qa_atsc.py: new: python based test code. + * src/lib/atsci_randomizer.{h,cc}: renamed class vars match new conventions. + +2006-03-22 Eric Blossom + + * src/lib/atsc_sliding_correlator.cc (shift_in), + src/lib/atsc_trellis_encoder.cc (encode_helper), + src/lib/atsc_viterbi_gen.cc (build_decode_structures): 64-bit + fixes. + +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-atsc/Makefile.am b/gr-atsc/Makefile.am new file mode 100644 index 00000000..4ed403a2 --- /dev/null +++ b/gr-atsc/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src +DIST_SUBDIRS = src doc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = diff --git a/gr-atsc/NEWS b/gr-atsc/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/gr-atsc/README b/gr-atsc/README new file mode 100644 index 00000000..91245716 --- /dev/null +++ b/gr-atsc/README @@ -0,0 +1,50 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This module contains the GNU Radio 2.x code for the +ATSC (HDTV) transmitter and receiver. + +See http://www.atsc.org for specifications. The most relevant ones +are XXX and YYY. + + +To build this, you must already have built and installed +gnuradio-core. Then if you're building from a tarball: + + $ ./configure + $ make + $ make check + $ sudo make install + +If you're building from CVS, you'll need to use this sequence, since +CVS doesn't contain configure or the generated Makefiles. + + $ ./bootstrap + $ ./configure + $ make + $ make check + $ sudo make install + + +The doc directory is not built by default. This is to avoid spurious +build problems on systems that don't have xmlto installed. If you +have xmlto and its dependencies installed, you can build the html +version of the howto article by cd'ing to doc and invoking make. diff --git a/gr-atsc/README.signal_flow b/gr-atsc/README.signal_flow new file mode 100644 index 00000000..879cb2c4 --- /dev/null +++ b/gr-atsc/README.signal_flow @@ -0,0 +1,41 @@ +This describes the signal flow through the gnuradio-0.9 ATSC Transmitter +and Receiver programs. + +ATSC Transmitter +================ + +module input output notes +-------------------- ---------------- ------------------- -------- +VrFileSource "MPEG transport stream" atsc_mpeg_packet +GrAtscRandomizer atsc_mpeg_packet atsc_mpeg_packet_no_sync whiten data with LFSR +GrAtscRSEncoder atsc_mpeg_packet_no_sync atsc_mpeg_packet_rs_encoded Reed-Soloman encoder +GrAtscInterleaver atsc_mpeg_packet_rs_encoded atsc_mpeg_packet_rs_encoded convolutional interleaver +GrAtscTrellisEncoder atsc_mpeg_packet_rs_encoded atsc_data_segment trellis encoder +GrAtscFieldSyncMux atsc_data_segment atsc_data_segment add in field syncs +GrAtscSymbolMapper atsc_data_segment float map [0,7] to +/- {1,3,5,7} and add pilot +GrWeaverModHead float float,float front half of Weaver VSB modulator +GrFIRfilterFFF (2x) float float low pass root raised cosine (matched filter) +GrWeaverModTail float,float short back half of Weaver VSB modulator +VrFileSink short "16-bit passband data" + + +ATSC Receiver +============= + +module input output notes +-------------------- ---------------- ------------------- ------- +VrFileSource "16-bit passband data" short +GrConvertSF short float convert short to float +GrFIRfilterFFF float float band pass root raised cosine centered at IF freq (matched filter) +GrAtscFPLL float float carrier tracking freq and phase lock loop with down converting mixer +GrFIRfilterFFF float float low pass to kill unwanted mixer image +GrRemoveDcFFF float float remove DC offset prior to symbol timing module +GrAtscBitTimingLoop3 float float,syminfo track symbol & segment timing and do fractional interpolation +GrAtscFieldSyncChecker float,syminfo float,syminfo look for field sync patterns +GrAtscEqualizer float,syminfo float,syminfo LMS equalizer +GrAtscFieldSyncDemux float,syminfo atsc_soft_data_segment remove field syncs and pack into data segments +GrAtscViterbiDecoder atsc_soft_data_segment atsc_mpeg_packet_rs_encoded Viterbi decoder (12 seg delay) +GrAtscDeinterleaver atsc_mpeg_packet_rs_encoded atsc_mpeg_packet_rs_encoded convolutional de-interleaver (52 seg delay) +GrAtscRSDecoder atsc_mpeg_packet_rs_encoded atsc_mpeg_packet_no_sync Reed-Solomon decoder +GrAtscDerandomizer atsc_mpeg_packet_no_sync atsc_mpeg_packet de-whiten with LFSR +VrFileSink atsc_mpeg_packet "MPEG transport stream" diff --git a/gr-atsc/doc/Makefile.am b/gr-atsc/doc/Makefile.am new file mode 100644 index 00000000..e69de29b diff --git a/gr-atsc/src/Makefile.am b/gr-atsc/src/Makefile.am new file mode 100644 index 00000000..122fc72c --- /dev/null +++ b/gr-atsc/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib python diff --git a/gr-atsc/src/lib/GrAtscBitTimingLoop.cc b/gr-atsc/src/lib/GrAtscBitTimingLoop.cc new file mode 100644 index 00000000..9577dad2 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscBitTimingLoop.cc @@ -0,0 +1,223 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "fpll_btloop_coupling.h" +#include +#include +#include +#include + +using std::abs; + +static const int DEC = 2; // nominal decimation factor + +/* + * I strongly suggest that you not mess with these... + */ +static const double DEFAULT_TIMING_RATE = 2.19e-4 / FPLL_BTLOOP_COUPLING_CONST; +static const double DEFAULT_LOOP_TAP = 0.05; + + +GrAtscBitTimingLoop::GrAtscBitTimingLoop () + : VrDecimatingSigProc (1, DEC), + next_input(0), w (1.0), mu (0.5), last_right(0), + debug_no_update (false) +{ + d_timing_rate = DEFAULT_TIMING_RATE; + loop.set_taps (DEFAULT_LOOP_TAP); + + history = 1500; // spare input samples in case we need them. + +#ifdef _BT_DIAG_OUTPUT_ + fp_loop = fopen ("loop.out", "w"); + if (fp_loop == 0){ + perror ("loop.out"); + exit (1); + } + + fp_ps = fopen ("ps.out", "w"); + if (fp_ps == 0){ + perror ("ps.out"); + exit (1); + } +#endif +} + +// +// We are nominally a 2x decimator, but our actual rate varies slightly +// depending on the difference between the transmitter and receiver +// sampling clocks. Hence, we need to compute our input ranges +// explictly. + +int +GrAtscBitTimingLoop::forecast(VrSampleRange output, + VrSampleRange inputs[]) { + /* dec:1 ratio with history */ + for(unsigned int i=0;i limit) + e = limit; + else if (e < -limit) + e = -limit; + + return loop.filter (e); +} + +int +GrAtscBitTimingLoop::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + iType *in = ((iType **)ai)[0]; + oType *out = ((oType **)ao)[0]; + + // Force in-order computation of output stream. + // This is required because of our slightly variable decimation factor + sync (output.index); + + + // We are tasked with producing output.size output samples. + // We will consume approximately 2 * output.size input samples. + + + unsigned int ii = 0; // input index + unsigned int k; // output index + + // We look at a window of 3 samples that we call left (oldest), + // middle, right (newest). Each time through the loop, the previous + // right becomes the new left, and the new samples are middle and + // right. + // + // The basic game plan is to drive the average difference between + // right and left to zero. Given that all transitions are + // equiprobable (the data is white) and that the composite matched + // filter is symmetric (raised cosine) it turns out that in the + // average, if we drive that difference to zero, (implying that the + // average slope at the middle point is zero), we'll be sampling + // middle at the maximum or minimum point in the pulse. + + iType left; + iType middle; + iType right = last_right; + + for (k = 0; k < output.size; k++){ + + left = right; + middle = produce_sample (in, ii); + right = produce_sample (in, ii); + + // assert (ii < inputs[0].size); + if (!(ii < inputs[0].size)){ + fprintf (stderr, "ii < inputs[0].size\n"); + fprintf (stderr, "ii = %d, inputs[0].size = %lu, k = %d, output.size = %lu\n", + ii, inputs[0].size, k, output.size); + assert (0); + } + + + out[k] = middle; // produce our output + + double timing_error = -middle * ((double) right - left); + + // update_timing_control_word + + double filtered_timing_error = filter_error (timing_error); + + if (!debug_no_update){ + mu += filtered_timing_error * d_timing_rate; + } + +#ifdef _BT_DIAG_OUTPUT_ + float iodata[8]; + iodata[0] = left; + iodata[1] = middle; + iodata[2] = right; + iodata[3] = timing_error; + iodata[4] = filtered_timing_error; + iodata[5] = mu; + iodata[6] = w; + iodata[7] = 0; + if (fwrite (iodata, sizeof (iodata), 1, fp_loop) != 1){ + perror ("fwrite: loop"); + exit (1); + } +#endif + + } + + last_right = right; + next_input += ii; // update next_input so forecast can get us what we need + return output.size; +} + +/*! + * Produce samples equally spaced in time that are referenced + * to the transmitter's sample clock, not ours. + * + * See pp 523-527 of "Digital Communication Receivers", Meyr, + * Moeneclaey and Fechtel, Wiley, 1998. + */ + +GrAtscBitTimingLoop::iType +GrAtscBitTimingLoop::produce_sample (const iType *in, unsigned int &index) +{ + // update mu and index as function of control word, w + + double sum = mu + w; + double f = floor (sum); + int incr = (int) f; // mostly 1, rarely 0 or 2 + mu = sum - f; + + assert (0 <= incr && incr <= 2); + assert (0.0 <= mu && mu <= 1.0); + + index += incr; + + iType n = intr.interpolate (&in[index], mu); + +#if defined(_BT_DIAG_OUTPUT_) && 0 + float iodata[4]; + iodata[0] = incr; + iodata[1] = mu; + iodata[2] = w; + iodata[3] = 0; + if (fwrite (iodata, sizeof (iodata), 1, fp_ps) != 1){ + perror ("fwrite: ps"); + exit (1); + } +#endif + + return n; +} diff --git a/gr-atsc/src/lib/GrAtscBitTimingLoop.h b/gr-atsc/src/lib/GrAtscBitTimingLoop.h new file mode 100644 index 00000000..3bb1adec --- /dev/null +++ b/gr-atsc/src/lib/GrAtscBitTimingLoop.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCBITTIMINGLOOP_H_ +#define _GRATSCBITTIMINGLOOP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/*! + * \brief ATSC BitTimingLoop + * + * This class accepts a single real input and produces a single real output + */ + +class GrAtscBitTimingLoop : public VrDecimatingSigProc { + + public: + + GrAtscBitTimingLoop (); + virtual ~GrAtscBitTimingLoop () { }; + + virtual const char *name () { return "GrAtscBitTimingLoop"; } + + virtual int forecast (VrSampleRange output, + VrSampleRange inputs[]); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + // debug + void set_mu (double a_mu) { mu = a_mu; } + void set_no_update (bool a_no_update) { debug_no_update = a_no_update; } + void set_loop_filter_tap (double tap) { loop.set_taps (tap); } + void set_timing_rate (double rate) { d_timing_rate = rate; } + + protected: + + typedef float iType; + typedef float oType; + + iType produce_sample (const iType *in, unsigned int &index); + double filter_error (double e); + + VrSampleIndex next_input; + gr_mmse_fir_interpolator intr; + double w; // timing control word + double mu; // fractional delay + iType last_right; // last right hand sample + gr_single_pole_iir loop; + bool debug_no_update;// debug + + double d_loop_filter_tap; + double d_timing_rate; + +#ifdef _BT_DIAG_OUTPUT_ + FILE *fp_loop; + FILE *fp_ps; +#endif +}; + +#endif // _GRATSCBITTIMINGLOOP_H_ diff --git a/gr-atsc/src/lib/GrAtscBitTimingLoop2.cc b/gr-atsc/src/lib/GrAtscBitTimingLoop2.cc new file mode 100644 index 00000000..25eadd36 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscBitTimingLoop2.cc @@ -0,0 +1,173 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + + +static const int DEC = 2; // nominal decimation factor + +static const unsigned AVG_WINDOW_LEN = 256; +static const float TIMING_RATE_CONST = 1e-5; // FIXME document interaction with AGC + + +GrAtscBitTimingLoop2::GrAtscBitTimingLoop2 () + : VrDecimatingSigProc (1, DEC), + next_input(0), dc (0.0002), mu (0.0), last_right(0), use_right_p (true) +{ + history = 100; // spare input samples in case we need them. + +#ifdef _BT_DIAG_OUTPUT_ + fp_loop = fopen ("loop.out", "w"); + if (fp_loop == 0){ + perror ("loop.out"); + exit (1); + } + + fp_ps = fopen ("ps.out", "w"); + if (fp_ps == 0){ + perror ("ps.out"); + exit (1); + } +#endif + +} + +// +// We are nominally a 2x decimator, but our actual rate varies slightly +// depending on the difference between the transmitter and receiver +// sampling clocks. Hence, we need to compute our input ranges +// explictly. + +int +GrAtscBitTimingLoop2::forecast(VrSampleRange output, + VrSampleRange inputs[]) { + /* dec:1 ratio with history */ + for(unsigned int i=0;i +#include +#include +#include +#include +#include +#include + +/*! + * \brief ATSC BitTimingLoop + * + * This class accepts a single real input and produces a single real output + */ + +class GrAtscBitTimingLoop2 : public VrDecimatingSigProc { + + public: + + GrAtscBitTimingLoop2 (); + virtual ~GrAtscBitTimingLoop2 () { }; + + virtual const char *name () { return "GrAtscBitTimingLoop2"; } + + virtual int forecast (VrSampleRange output, + VrSampleRange inputs[]); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + // debug + void set_mu (float a_mu) { + assert (0 <= a_mu && a_mu <= 1.9); + use_right_p = a_mu < 1.0; + mu = a_mu - floor (a_mu); + cerr << "BTL2: mu: " << mu << " use_right_p: " << use_right_p << endl; + } + + protected: + + typedef float iType; + typedef float oType; + + iType produce_sample (const iType *in, unsigned int &index); + float filter_error (float e); + + VrSampleIndex next_input; + gr_single_pole_iir dc; // used to estimate DC component + gr_mmse_fir_interpolator intr; + float mu; // fractional delay + iType last_right; // last right hand sample + + bool use_right_p; // ...else middle +}; + +#endif // _GRATSCBITTIMINGLOOP2_H_ diff --git a/gr-atsc/src/lib/GrAtscBitTimingLoop3.cc b/gr-atsc/src/lib/GrAtscBitTimingLoop3.cc new file mode 100644 index 00000000..2b21f2f0 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscBitTimingLoop3.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +using std::abs; + + +static const int NOUTPUTS = 2; + +GrAtscBitTimingLoop3::GrAtscBitTimingLoop3 (double ratio_of_rx_clock_to_symbol_freq) + : VrDecimatingSigProc (NOUTPUTS, (int) rint (ratio_of_rx_clock_to_symbol_freq)), + d_interp (ratio_of_rx_clock_to_symbol_freq), d_next_input(0), + d_rx_clock_to_symbol_freq (ratio_of_rx_clock_to_symbol_freq) + +{ + assert (ratio_of_rx_clock_to_symbol_freq >= 1.8); // sanity check + + history = 1500; // spare input samples in case we need them. +} + +// +// We are nominally a 2x decimator, but our actual rate varies slightly +// depending on the difference between the transmitter and receiver +// sampling clocks. Hence, we need to compute our input ranges +// explictly. + +int +GrAtscBitTimingLoop3::forecast(VrSampleRange output, + VrSampleRange inputs[]) { + assert (numberInputs == 1); + + /* dec:1 ratio with history */ + inputs[0].index = d_next_input; + inputs[0].size = + ((unsigned long) (output.size * d_rx_clock_to_symbol_freq) + history - 1); + + return 0; +} + + +int +GrAtscBitTimingLoop3::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + iType *in = ((iType **)ai)[0]; + oDataType *out_sample = ((oDataType **)ao)[0]; + oTagType *out_tag = ((oTagType **) ao)[1]; + + // Force in-order computation of output stream. + // This is required because of our slightly variable decimation factor + sync (output.index); + + // We are tasked with producing output.size output samples. + // We will consume approximately 2 * output.size input samples. + + int si = 0; // source index + unsigned int k; // output index + + float interp_sample; + int symbol_index; + double timing_adjustment = 0; + bool seg_locked; + oTagType tag; + + memset (&tag, 0, sizeof (tag)); + + for (k = 0; k < output.size; k++){ + + if (!d_interp.update (in, inputs[0].size, &si, timing_adjustment, &interp_sample)){ + fprintf (stderr, "GrAtscBitTimingLoop3: ran short on data...\n"); + break; + } + + d_sssr.update (interp_sample, &seg_locked, &symbol_index, &timing_adjustment); + out_sample[k] = interp_sample; + tag.valid = seg_locked; + tag.symbol_num = symbol_index; + out_tag[k] = tag; + } + + d_next_input += si; // update next_input so forecast can get us what we need + return k; +} diff --git a/gr-atsc/src/lib/GrAtscBitTimingLoop3.h b/gr-atsc/src/lib/GrAtscBitTimingLoop3.h new file mode 100644 index 00000000..299dc79d --- /dev/null +++ b/gr-atsc/src/lib/GrAtscBitTimingLoop3.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCBITTIMINGLOOP3_H_ +#define _GRATSCBITTIMINGLOOP3_H_ + +#include +#include +#include +#include +#include + +/*! + * \brief ATSC BitTimingLoop3 + * + * This class accepts a single real input and produces two outputs, + * the raw symbol (float) and the tag (atsc_syminfo) + */ + +class GrAtscBitTimingLoop3 : public VrDecimatingSigProc { + + public: + + GrAtscBitTimingLoop3 (double ratio_of_rx_clock_to_symbol_freq); + virtual ~GrAtscBitTimingLoop3 () { }; + + virtual const char *name () { return "GrAtscBitTimingLoop3"; } + + virtual int forecast (VrSampleRange output, + VrSampleRange inputs[]); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + // debug (NOPs) + void set_mu (double a_mu) { } + void set_no_update (bool a_no_update) { } + void set_loop_filter_tap (double tap) { } + void set_timing_rate (double rate) { } + + protected: + + typedef float iType; + typedef float oDataType; + typedef atsc::syminfo oTagType; + + atsci_sssr d_sssr; + atsci_interpolator d_interp; + VrSampleIndex d_next_input; + double d_rx_clock_to_symbol_freq; +}; + +#endif // _GRATSCBITTIMINGLOOP3_H_ diff --git a/gr-atsc/src/lib/GrAtscConvert2xTo20.cc b/gr-atsc/src/lib/GrAtscConvert2xTo20.cc new file mode 100644 index 00000000..79811df3 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscConvert2xTo20.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +static const int N_OUTPUTS = 1; +static const double DEC_RATIO = (2.0 * ATSC_SYMBOL_RATE) / 20e6; // ~ 1.076 + +GrAtscConvert2xTo20::GrAtscConvert2xTo20 () + : VrDecimatingSigProc (N_OUTPUTS, (int) rint (DEC_RATIO)) +{ + d_next_input = 0; + d_frac_part = 0; + history = 2 * d_interp.ntaps (); // some slack +} + +GrAtscConvert2xTo20::~GrAtscConvert2xTo20 () +{ + // Nop +} + +void +GrAtscConvert2xTo20::pre_initialize () +{ + fprintf (stderr, + "GrAtscConvert2xTo20: input freq = %g\n", getInputSamplingFrequencyN(0)); + fprintf (stderr, + "GrAtscConvert2xTo20: DEC_RATIO = %g\n", DEC_RATIO); + fprintf (stderr, + "GrAtscConvert2xTo20: argument to setSamplingFrequency = %g\n", + getInputSamplingFrequencyN(0) / DEC_RATIO); + + int r; + r = setSamplingFrequency (getInputSamplingFrequencyN (0) / DEC_RATIO); + + fprintf (stderr, "GrAtscConvert2xTo20: result = %d\n", r); + + fprintf (stderr, "GrAtscConvert2xTo20: getSamplingFrequency = %g\n", + getSamplingFrequency ()); +} + + +int +GrAtscConvert2xTo20::forecast (VrSampleRange output, + VrSampleRange inputs[]) +{ + assert (numberInputs == 1); // I hate these free references to + // superclass's instance variables... + + inputs[0].index = d_next_input; + inputs[0].size = + ((long unsigned int) (output.size * DEC_RATIO) + history - 1); + + return 0; +} + +int +GrAtscConvert2xTo20::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + float *in = ((float **) ai)[0]; + float *out = ((float **) ao)[0]; + + sync (output.index); + + unsigned long si = 0; // source index + unsigned long oi = 0; // output index + double frac_part = d_frac_part; + + for (oi = 0; oi < output.size; oi++){ + assert (si + d_interp.ntaps () < inputs[0].size); + out[oi] = d_interp.interpolate (&in[si], (1. - frac_part)); + + double s = frac_part + DEC_RATIO; + double float_incr = floor (s); + frac_part = s - float_incr; + int incr = (int) float_incr; + si += incr; + } + + d_next_input += si; + d_frac_part = frac_part; + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscConvert2xTo20.h b/gr-atsc/src/lib/GrAtscConvert2xTo20.h new file mode 100644 index 00000000..a8f802be --- /dev/null +++ b/gr-atsc/src/lib/GrAtscConvert2xTo20.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRATSCCONVERT2XTO20_H_ +#define _GRATSCCONVERT2XTO20_H_ + +#include +#include + +class GrAtscConvert2xTo20 : public VrDecimatingSigProc { + gr_mmse_fir_interpolator d_interp; + double d_frac_part; + VrSampleIndex d_next_input; + +public: + GrAtscConvert2xTo20 (); + ~GrAtscConvert2xTo20 (); + + virtual const char *name () { return "GrAtscConvert2xTo20"; } + + virtual int forecast (VrSampleRange output, + VrSampleRange inputs[]); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + void pre_initialize (); + int checkOutputSamplingFrequency(float) { return 0; } // bogus, but required + +}; + +#endif /* _GRATSCCONVERT2XTO20_H_ */ diff --git a/gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.cc b/gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.cc new file mode 100644 index 00000000..577330ec --- /dev/null +++ b/gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.cc @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_data_segment iType; +typedef atsc_soft_data_segment oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static void +map_to_soft_symbols (atsc_soft_data_segment &out, + const atsc_data_segment &in) +{ + for (unsigned int i = 0; i < NELEM (in.data); i++){ + out.data[i] = in.data[i] * 2 - 7; + } +} + + +GrAtscDataSegToSoftDataSeg::GrAtscDataSegToSoftDataSeg () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscDataSegToSoftDataSeg::~GrAtscDataSegToSoftDataSeg () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscDataSegToSoftDataSeg::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + map_to_soft_symbols (out[i], in[i]); + out[i].pli = in[i].pli; + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.h b/gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.h new file mode 100644 index 00000000..0cab046f --- /dev/null +++ b/gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCDATASEGTOSOFTDATASEG_H_ +#define _GRATSCDATASEGTOSOFTDATASEG_H_ + +#include +#include + +/*! + * \brief Debug glue routine (atsc_data_segment --> atsc_soft_data_segment) + */ + +class GrAtscDataSegToSoftDataSeg : public VrHistoryProc +{ + +public: + + GrAtscDataSegToSoftDataSeg (); + ~GrAtscDataSegToSoftDataSeg (); + + const char *name () { return "GrAtscDataSegToSoftDataSeg"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: +}; + +#endif /* _GRATSCDATASEGTOSOFTDATASEG_H_ */ diff --git a/gr-atsc/src/lib/GrAtscDeinterleaver.cc b/gr-atsc/src/lib/GrAtscDeinterleaver.cc new file mode 100644 index 00000000..2148e8aa --- /dev/null +++ b/gr-atsc/src/lib/GrAtscDeinterleaver.cc @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet_rs_encoded iType; +typedef atsc_mpeg_packet_rs_encoded oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscDeinterleaver::GrAtscDeinterleaver () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscDeinterleaver::~GrAtscDeinterleaver () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscDeinterleaver::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, the current contents of the LFSR in the randomizer, hence + // we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + // pipeline info is handled in the primitive + deinterleaver.deinterleave (out[i], in[i]); + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscDeinterleaver.h b/gr-atsc/src/lib/GrAtscDeinterleaver.h new file mode 100644 index 00000000..d4cb44e6 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscDeinterleaver.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCDEINTERLEAVER_H_ +#define _GRATSCDEINTERLEAVER_H_ + +#include +#include +#include + +/*! + * \brief Deinterleave RS encoded ATSC data ( atsc_mpeg_packet_rs_encoded --> atsc_mpeg_packet_rs_encoded) + */ + +class GrAtscDeinterleaver : public VrHistoryProc +{ + +public: + + GrAtscDeinterleaver (); + ~GrAtscDeinterleaver (); + + const char *name () { return "GrAtscDeinterleaver"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_data_deinterleaver deinterleaver; +}; + +#endif /* _GRATSCDEINTERLEAVER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscDerandomizer.cc b/gr-atsc/src/lib/GrAtscDerandomizer.cc new file mode 100644 index 00000000..2cd7d39d --- /dev/null +++ b/gr-atsc/src/lib/GrAtscDerandomizer.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet_no_sync iType; +typedef atsc_mpeg_packet oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscDerandomizer::GrAtscDerandomizer () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscDerandomizer::~GrAtscDerandomizer () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscDerandomizer::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, the current contents of the LFSR in the randomizer, hence + // we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + + assert (in[i].pli.regular_seg_p ()); + + if (in[i].pli.first_regular_seg_p ()) + rand.reset (); + + rand.derandomize (out[i], in[i]); + + // take a look at the transport error bit in the pipeline info + // and set bit as required + + if (in[i].pli.transport_error_p ()) + out[i].data[1] |= MPEG_TRANSPORT_ERROR_BIT; + else + out[i].data[1] &= ~MPEG_TRANSPORT_ERROR_BIT; + + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscDerandomizer.h b/gr-atsc/src/lib/GrAtscDerandomizer.h new file mode 100644 index 00000000..22888c28 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscDerandomizer.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCDERANDOMIZER_H_ +#define _GRATSCDERANDOMIZER_H_ + +#include +#include +#include + +/*! + * \brief Derandomize ATSC data (atsc_mpeg_packet_no_sync --> atsc_mpeg_packet) + */ + +class GrAtscDerandomizer : public VrHistoryProc +{ + +public: + + GrAtscDerandomizer (); + ~GrAtscDerandomizer (); + + const char *name () { return "GrAtscDerandomizer"; } + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_randomizer rand; +}; + +#endif /* _GRATSCDERANDOMIZER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscEqualizer.cc b/gr-atsc/src/lib/GrAtscEqualizer.cc new file mode 100644 index 00000000..cd930adb --- /dev/null +++ b/gr-atsc/src/lib/GrAtscEqualizer.cc @@ -0,0 +1,135 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +// typedefs for fundamental i/o types + +typedef float dataType; +typedef atsc::syminfo tagType; + +static const int NUMBER_OF_OUTPUTS = 2; // # of output streams + + +GrAtscEqualizer::GrAtscEqualizer (atsci_equalizer *equalizer) + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // due to limitation of runtime, all inputs must be the same size + assert (sizeof (dataType) == sizeof (tagType)); + + d_equalizer = equalizer; + + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // + // Set this to the answer returned by the equalizer primitive we were passed. + history = d_equalizer->ntaps (); +} + +GrAtscEqualizer::~GrAtscEqualizer () +{ + // Anything that isn't automatically cleaned up... + + delete d_equalizer; +} + + +/* + * non-standard forecast routine that handles getting the correct amount of + * history for the data input as well as ensuring correct alignment of + * the data and tags. + */ + +int +GrAtscEqualizer::forecast (VrSampleRange output, + VrSampleRange inputs[]) +{ + assert (numberInputs == 2); + + int ntaps = d_equalizer->ntaps (); + int npretaps = d_equalizer->npretaps (); + + assert (ntaps >= 1); + assert (npretaps >= 0 && npretaps < ntaps); + + inputs[0].index = output.index; // the equalizer data + inputs[0].size = output.size + ntaps - 1; // history on data + + // FIXME if there's a problem, it's probably on the next line... + int offset = ntaps - npretaps - 1; + + assert (offset >= 0 && offset < ntaps); + + inputs[1].index = output.index + offset; // align equalizer tags + inputs[1].size = output.size; // N.B., no extra history on tags + + return 0; +} + +/* + * This is the real work horse. We consume 2 input streams + * and produce 2 output streams. + */ + +int +GrAtscEqualizer::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // assert (numberInputs == 2); + + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, hence we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + dataType *input_samples = ((dataType **) ai)[0]; + tagType *input_tags = ((tagType **) ai)[1]; + dataType *output_samples = ((dataType **) ao)[0]; + tagType *output_tags = ((tagType **) ao)[1]; + + + // peform the actual equalization + + d_equalizer->filter (input_samples, input_tags, + output_samples, output.size); + + // write the output tags + + for (unsigned int i = 0; i < output.size; i++) + output_tags[i] = input_tags[i]; + + // Return the number of units we produced. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscEqualizer.h b/gr-atsc/src/lib/GrAtscEqualizer.h new file mode 100644 index 00000000..46282bad --- /dev/null +++ b/gr-atsc/src/lib/GrAtscEqualizer.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCEQUALIZER_H_ +#define _GRATSCEQUALIZER_H_ + +#include + +class atsci_equalizer; + +/*! + * \brief ATSC equalizer (float,syminfo --> float,syminfo) + * + * first inputs are data samples, second inputs are tags. + * first outputs are equalized data samples, second outputs are tags. + * + * tag values are defined in atsci_syminfo.h + */ + +class GrAtscEqualizer : public VrHistoryProc +{ + +public: + + GrAtscEqualizer (atsci_equalizer *equalizer); + ~GrAtscEqualizer (); + + const char *name () { return "GrAtscEqualizer"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + // we've got a non-standard forecast routine + int forecast (VrSampleRange output, VrSampleRange inputs[]); + +protected: + atsci_equalizer *d_equalizer; +}; + +#endif /* _GRATSCEQUALIZER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscFPLL.cc b/gr-atsc/src/lib/GrAtscFPLL.cc new file mode 100644 index 00000000..e6a7ff63 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFPLL.cc @@ -0,0 +1,150 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "fpll_btloop_coupling.h" + +/* + * I strongly suggest that you not mess with these... + * + * They are strongly coupled into the symbol timing code and + * their value also sets the level of the symbols going + * into the equalizer and viterbi decoder. + */ +static const float FPLL_AGC_REFERENCE = 2.5 * FPLL_BTLOOP_COUPLING_CONST; +static const float FPLL_AGC_RATE = 0.25e-6; + + +GrAtscFPLL::GrAtscFPLL (double a_initial_freq) + : VrSigProc (1, sizeof (iType), sizeof (oType)), + initial_phase(0), debug_no_update(false) +{ + initial_freq = a_initial_freq; + agc.set_rate (FPLL_AGC_RATE); + agc.set_reference (FPLL_AGC_REFERENCE); + + if (_FPLL_DIAG_OUTPUT_){ + fp = fopen ("fpll.out", "w"); + if (fp == 0){ + perror ("fpll.out"); + exit (1); + } + } + +} + +void +GrAtscFPLL::initialize () +{ + float Fs = getInputSamplingFrequencyN (0); + + float alpha = 1 - exp(-1.0 / Fs / 5e-6); + + afci.set_taps (alpha); + afcq.set_taps (alpha); + + nco.set_freq (initial_freq / Fs * 2 * M_PI); + nco.set_phase (initial_phase); +} + +int +GrAtscFPLL::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + iType *in = ((iType **)ai)[0]; + oType *out = ((oType **)ao)[0]; + + unsigned int k; + + for (k = 0; k < output.size; k++){ + + float a_cos, a_sin; + + float input = agc.scale (in[k]); + + nco.step (); // increment phase + nco.sincos (a_sin, a_cos); // compute cos and sin + + float I = input * a_sin; + float Q = input * a_cos; + + out[k] = I; + + float filtered_I = afci.filter (I); + float filtered_Q = afcq.filter (Q); + + // phase detector + + float x = atan2 (filtered_Q, filtered_I); + + // avoid slamming filter with big transitions + + static const float limit = M_PI / 2; + + if (x > limit) + x = limit; + else if (x < -limit) + x = -limit; + + // static const float alpha = 0.037; // Max value + // static const float alpha = 0.005; // takes about 5k samples to pull in, stddev = 323 + // static const float alpha = 0.002; // takes about 15k samples to pull in, stddev = 69 + // or about 120k samples on noisy data, + static const float alpha = 0.001; + static const float beta = alpha * alpha / 4; + + + if (!debug_no_update){ + nco.adjust_phase (alpha * x); + nco.adjust_freq (beta * x); + } + + if (_FPLL_DIAG_OUTPUT_){ +#if 0 // lots of data... + float iodata[8]; + iodata[0] = nco.get_freq () * getSamplingFrequency () * (1.0 / (2 * M_PI)); + iodata[1] = in[k]; + iodata[2] = input; + iodata[3] = I; + iodata[4] = Q; + iodata[5] = filtered_I; + iodata[6] = filtered_Q; + iodata[7] = x; + if (fwrite (iodata, sizeof (iodata), 1, fp) != 1){ + perror ("fwrite: fpll"); + exit (1); + } +#else // just the frequency + float iodata[1]; + iodata[0] = nco.get_freq () * getSamplingFrequency () * (1.0 / (2 * M_PI)); + if (fwrite (iodata, sizeof (iodata), 1, fp) != 1){ + perror ("fwrite: fpll"); + exit (1); + } +#endif + } + } + + return output.size; +} + diff --git a/gr-atsc/src/lib/GrAtscFPLL.h b/gr-atsc/src/lib/GrAtscFPLL.h new file mode 100644 index 00000000..0868f9a0 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFPLL.h @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef _GRATSCFPLL_H_ +#define _GRATSCFPLL_H_ + +#include +#include +#include +#include +#include +#include +#include + +/*! + * \brief ATSC FPLL (2nd Version) + * + * Used as follows: + * float float + * A/D --> GrFIRfilterFFF ----> GrAtscFPLL ----> + * + * We use GrFIRfilterFFF to bandpass filter the signal of interest. + * + * This class accepts a single real input and produces a single real output + */ + +class GrAtscFPLL : public VrSigProc { + protected: + + typedef float iType; + typedef float oType; + + public: + + GrAtscFPLL (double a_initial_freq); + virtual ~GrAtscFPLL () {} + + virtual const char *name () { return "GrAtscFPLL"; } + + virtual void initialize (); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + + // diagnostic routines + void set_initial_phase (double phase) { initial_phase = phase; } // radians + void set_no_update (bool a_no_update) { debug_no_update = a_no_update; } + + + protected: + + double initial_freq; + double initial_phase; + bool debug_no_update; + gr_nco nco; + gr_agc agc; // automatic gain control + gr_single_pole_iir afci; + gr_single_pole_iir afcq; + +#ifdef _FPLL_DIAG_OUTPUT_ + FILE *fp; +#endif + +}; + + +#endif // _GRATSCFPLL_H_ diff --git a/gr-atsc/src/lib/GrAtscFieldSyncChecker.cc b/gr-atsc/src/lib/GrAtscFieldSyncChecker.cc new file mode 100644 index 00000000..18b81ac2 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncChecker.cc @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +// typedefs for fundamental i/o types + +typedef float iDataType; +typedef atsc::syminfo iTagType; +typedef float oDataType; +typedef atsc::syminfo oTagType; + +static const int NUMBER_OF_OUTPUTS = 2; // # of output streams + + +GrAtscFieldSyncChecker::GrAtscFieldSyncChecker () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // tags and data must be same size due to limitation of runtime + assert (sizeof (iDataType) == sizeof (iTagType)); + assert (sizeof (oDataType) == sizeof (oTagType)); + + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + d_fsc = create_atsci_fs_checker (); +} + +GrAtscFieldSyncChecker::~GrAtscFieldSyncChecker () +{ + // Anything that isn't automatically cleaned up... + + delete d_fsc; +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscFieldSyncChecker::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, hence we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iDataType *sample_in = ((iDataType **) ai)[0]; + iTagType *tag_in = ((iTagType **) ai)[1]; + oDataType *sample_out = ((oDataType **) ao)[0]; + oTagType *tag_out = ((oTagType **) ao)[1]; + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + d_fsc->filter (sample_in[i], tag_in[i], &sample_out[i], &tag_out[i]); + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscFieldSyncChecker.h b/gr-atsc/src/lib/GrAtscFieldSyncChecker.h new file mode 100644 index 00000000..f64ebcb6 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncChecker.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCFIELDSYNCCHECKER_H_ +#define _GRATSCFIELDSYNCCHECKER_H_ + +#include + +class atsci_fs_checker; + +/*! + * \brief ATSC field sync checker (float,syminfo --> float,syminfo) + * + * first output is delayed version of input. + * second output is set of tags, one-for-one with first output. + */ + +class GrAtscFieldSyncChecker : public VrHistoryProc +{ + +public: + + GrAtscFieldSyncChecker (); + ~GrAtscFieldSyncChecker (); + + const char *name () { return "GrAtscFieldSyncChecker"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_fs_checker *d_fsc; +}; + +#endif /* _GRATSCFIELDSYNCCHECKER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscFieldSyncCorrelator.cc b/gr-atsc/src/lib/GrAtscFieldSyncCorrelator.cc new file mode 100644 index 00000000..23eabe8e --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncCorrelator.cc @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +// typedefs for fundamental i/o types + +typedef float iType; +typedef float oType; + +static const int NUMBER_OF_OUTPUTS = 2; // # of output streams + + +GrAtscFieldSyncCorrelator::GrAtscFieldSyncCorrelator () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + d_fsc = create_atsci_fs_correlator (); +} + +GrAtscFieldSyncCorrelator::~GrAtscFieldSyncCorrelator () +{ + // Anything that isn't automatically cleaned up... + + delete d_fsc; +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscFieldSyncCorrelator::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, hence we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *sample_out = ((oType **) ao)[0]; + oType *tag_out = ((oType **) ao)[1]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + d_fsc->filter (in[i], &sample_out[i], &tag_out[i]); + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscFieldSyncCorrelator.h b/gr-atsc/src/lib/GrAtscFieldSyncCorrelator.h new file mode 100644 index 00000000..78ff9c66 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncCorrelator.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCFIELDSYNCCORRELATOR_H_ +#define _GRATSCFIELDSYNCCORRELATOR_H_ + +#include + +class atsci_fs_correlator; + +/*! + * \brief ATSC field sync correlator (float --> float,float) + * + * first output is delayed version of input. + * second output is set of tags, one-for-one with first output. + * + * tag values are defined in atsci_sync_tag.h + */ + +class GrAtscFieldSyncCorrelator : public VrHistoryProc +{ + +public: + + GrAtscFieldSyncCorrelator (); + ~GrAtscFieldSyncCorrelator (); + + const char *name () { return "GrAtscFieldSyncCorrelator"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_fs_correlator *d_fsc; +}; + +#endif /* _GRATSCFIELDSYNCCORRELATOR_H_ */ diff --git a/gr-atsc/src/lib/GrAtscFieldSyncDemux.cc b/gr-atsc/src/lib/GrAtscFieldSyncDemux.cc new file mode 100644 index 00000000..04a39bd0 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncDemux.cc @@ -0,0 +1,173 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +using std::abs; + +static const int DEC = ATSC_DATA_SEGMENT_LENGTH; // nominal decimation factor + +GrAtscFieldSyncDemux::GrAtscFieldSyncDemux () + : VrDecimatingSigProc (1, DEC), + d_locked (false), d_in_field2(true), d_segment_number(0), d_next_input(0), + d_lost_index (0) +{ + history = 2 * ATSC_DATA_SEGMENT_LENGTH; // spare input samples in case we need them. +} + +GrAtscFieldSyncDemux::~GrAtscFieldSyncDemux () +{ +} + +int +GrAtscFieldSyncDemux::forecast (VrSampleRange output, + VrSampleRange inputs[]) { + /* dec:1 ratio with history */ + + assert (numberInputs == 2); + + for (unsigned int i = 0; i < numberInputs; i++) { + inputs[i].index = d_next_input; + inputs[i].size = output.size * decimation + history - 1; + } + return 0; +} + +inline static bool +tag_is_seg_sync_or_field_sync (atsc::syminfo tag) +{ + return tag.symbol_num == 0 && tag.valid; +} + +int +GrAtscFieldSyncDemux::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + float *input_samples = (float *) ai[0]; + atsc::syminfo *input_tags = (atsc::syminfo *) ai[1]; + atsc_soft_data_segment *out = ((atsc_soft_data_segment **)ao)[0]; + + sync (output.index); + + unsigned int ii = 0; // input index + + // Are we in sync? + if (!tag_is_seg_sync_or_field_sync (input_tags[0])){ // No ... + + if (d_locked){ + d_locked = false; + d_lost_index = inputs[0].index + ii; + cerr << "GrAtscFieldSyncDemux: lost sync at " + << d_lost_index << endl; + } + + // ... search for beginning of a field sync + + // cerr << "GrAtscFieldSyncDemux: searching for sync at " + // << inputs[0].index + ii << endl; + + for (ii = 1; ii < inputs[0].size; ii++){ + if (atsc::tag_is_start_field_sync (input_tags[ii])){ + // found one + d_locked = true; + + const char *str; + if (atsc::tag_is_start_field_sync_1 (input_tags[ii])) + str = "FIELD-1"; + else if (atsc::tag_is_start_field_sync_2 (input_tags[ii])) + str = "FIELD-2"; + else + str = "SEGMENT"; + + cerr << "GrAtscFieldSyncDemux: synced (" << str << ") at " + << inputs[0].index + ii + << " [delta = " << inputs[0].index + ii - d_lost_index + << "]\n"; + + d_next_input += ii; // update for forecast + return 0; // no work completed so far + } + } + // no non-NORMAL tag found + d_next_input += ii; // update for forecast + return 0; // no work completed so far + } + + // We are in sync. Produce output... + + unsigned int k = 0; // output index + + while (k < output.size){ + + if (inputs[0].size - ii < (unsigned) ATSC_DATA_SEGMENT_LENGTH){ + // We're out of input data. + cerr << "GrAtscFieldSyncDemux: ran out of input data\n"; + d_next_input += ii; // update for forecast + return k; // return amount of work completed so far + } + + if (!tag_is_seg_sync_or_field_sync (input_tags[ii])){ + // lost sync... + // cerr << "GrAtscFieldSyncDemux: lost sync at " + // << inputs[0].index + ii << endl; + + d_next_input += ii; // update for forecast + return k; // return amount of work completed so far + } + + if (atsc::tag_is_start_field_sync_1 (input_tags[ii])){ + d_in_field2 = false; + d_segment_number = 0; + ii += ATSC_DATA_SEGMENT_LENGTH; // skip over field sync + continue; + } + + if (atsc::tag_is_start_field_sync_2 (input_tags[ii])){ + d_in_field2 = true; + d_segment_number = 0; + ii += ATSC_DATA_SEGMENT_LENGTH; // skip over field sync + continue; + } + + if (d_segment_number >= ATSC_DSEGS_PER_FIELD){ + // something's wrong... + cerr << "GrAtscFieldSyncDemux: segment number overflow\n"; + d_segment_number = 0; + } + + out[k].pli.set_regular_seg (d_in_field2, d_segment_number++); + for (int jj = 0; jj < ATSC_DATA_SEGMENT_LENGTH; jj++) + out[k].data[jj] = input_samples[ii + jj]; + ii += ATSC_DATA_SEGMENT_LENGTH; + k++; + } + + d_next_input += ii; // update for forecast + return k; // return amount of work completed +} + diff --git a/gr-atsc/src/lib/GrAtscFieldSyncDemux.h b/gr-atsc/src/lib/GrAtscFieldSyncDemux.h new file mode 100644 index 00000000..2eb6084b --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncDemux.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCFIELDSYNCDEMUX_H_ +#define _GRATSCFIELDSYNCDEMUX_H_ + +#include +#include + +/*! + * \brief ATSC Field Sync Demux + * + * This class accepts 1 stream of floats (data), and 1 stream of tags (syminfo). + * It outputs one stream of atsc_soft_data_segment packets + */ + +class GrAtscFieldSyncDemux : public VrDecimatingSigProc { + + public: + + GrAtscFieldSyncDemux (); + virtual ~GrAtscFieldSyncDemux (); + + virtual const char *name () { return "GrAtscFieldSyncDemux"; } + + virtual int forecast (VrSampleRange output, + VrSampleRange inputs[]); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + protected: + + bool d_locked; + bool d_in_field2; + int d_segment_number; + VrSampleIndex d_next_input; + VrSampleIndex d_lost_index; // diagnostic fluff +}; + +#endif // _GRATSCFIELDSYNCDEMUX_H_ diff --git a/gr-atsc/src/lib/GrAtscFieldSyncMux.cc b/gr-atsc/src/lib/GrAtscFieldSyncMux.cc new file mode 100644 index 00000000..42921952 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncMux.cc @@ -0,0 +1,246 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + + +// typedefs for fundamental i/o types + +typedef atsc_data_segment iType; +typedef atsc_data_segment oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + +static const int N_SAVED_SYMBOLS = GrAtscFieldSyncMux::N_SAVED_SYMBOLS; + +static void +init_field_sync_common (unsigned char *p, int mask, + const unsigned char saved_symbols[N_SAVED_SYMBOLS]) +{ + static const unsigned char bin_map[2] = { 1, 6 }; // map binary values to 1 of 8 levels + + int i = 0; + + p[i++] = bin_map[1]; // data segment sync pulse + p[i++] = bin_map[0]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + + for (int j = 0; j < 511; j++) // PN511 + p[i++] = bin_map[atsc_pn511[j]]; + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map[atsc_pn63[j]]; + + for (int j = 0; j < 63; j++) // PN63, toggled on field 2 + p[i++] = bin_map[atsc_pn63[j] ^ mask]; + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map[atsc_pn63[j]]; + + p[i++] = bin_map[0]; // 24 bits of VSB8 mode identifiera + p[i++] = bin_map[0]; + p[i++] = bin_map[0]; + p[i++] = bin_map[0]; + + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + + p[i++] = bin_map[1]; + p[i++] = bin_map[1]; + p[i++] = bin_map[1]; + p[i++] = bin_map[1]; + + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + + + for (int j = 0; j < 92; j++) // 92 more bits + p[i++] = bin_map[atsc_pn63[j % 63]]; + + // now copy the last 12 symbols of the previous segment + + for (int j = 0; j < N_SAVED_SYMBOLS; j++) + p[i++] = saved_symbols[j]; + + assert (i == ATSC_DATA_SEGMENT_LENGTH); +} + +inline static void +init_field_sync_1 (atsc_data_segment *s, + const unsigned char saved_symbols[N_SAVED_SYMBOLS]) +{ + init_field_sync_common (&s->data[0], 0, saved_symbols); +} + +inline static void +init_field_sync_2 (atsc_data_segment *s, + const unsigned char saved_symbols[N_SAVED_SYMBOLS]) + +{ + init_field_sync_common (&s->data[0], 1, saved_symbols); +} + +static void +save_last_symbols (unsigned char saved_symbols[N_SAVED_SYMBOLS], + const atsc_data_segment &seg) +{ + for (int i = 0; i < N_SAVED_SYMBOLS; i++) + saved_symbols[i] = seg.data[i + ATSC_DATA_SEGMENT_LENGTH - N_SAVED_SYMBOLS]; +} + + +inline static bool +last_regular_seg_p (const plinfo &pli) +{ + return pli.regular_seg_p () && (pli.segno () == ATSC_DSEGS_PER_FIELD - 1); +} + + +GrAtscFieldSyncMux::GrAtscFieldSyncMux () + : VrHistoryProc (NUMBER_OF_OUTPUTS), + d_current_index (0), d_already_output_field_sync (false) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + history = 1; + + // any other init here. +} + +GrAtscFieldSyncMux::~GrAtscFieldSyncMux () +{ + // Anything that isn't automatically cleaned up... +} + +void +GrAtscFieldSyncMux::pre_initialize () +{ + // we jack our output sampling frequency up to account for inserted field syncs + setSamplingFrequency (getInputSamplingFrequencyN (0) * 313./312.); +} + +/* + * we need a non-standard version of forecast because our output isn't + * exactly 1:1 with our input. + */ + +int +GrAtscFieldSyncMux::forecast (VrSampleRange output, VrSampleRange inputs[]) +{ + for(unsigned int i = 0; i < numberInputs; i++) { + inputs[i].index = d_current_index; + inputs[i].size = output.size; + } + return 0; +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ +int +GrAtscFieldSyncMux::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, hence we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + unsigned int index = 0; + for (unsigned int outdex = 0; outdex < output.size; outdex++){ + + assert (in[index].pli.regular_seg_p ()); + + if (!in[index].pli.first_regular_seg_p ()){ + out[outdex] = in[index]; // just copy in to out + + if (last_regular_seg_p (in[index].pli)) + save_last_symbols (d_saved_symbols, in[index]); + + index++; + } + else { // first_regular_seg_p + if (!d_already_output_field_sync){ + // write out field sync... + atsc_data_segment field_sync; + + if (in[index].pli.in_field1_p ()) + init_field_sync_1 (&field_sync, d_saved_symbols); + else + init_field_sync_2 (&field_sync, d_saved_symbols); + + // note that index doesn't advance in this branch + out[outdex] = field_sync; + d_already_output_field_sync = true; + } + else { + // already output field sync, now output first regular segment + out[outdex] = in[index]; + index++; + d_already_output_field_sync = false; + } + } + } + + d_current_index += index; + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscFieldSyncMux.h b/gr-atsc/src/lib/GrAtscFieldSyncMux.h new file mode 100644 index 00000000..5235603c --- /dev/null +++ b/gr-atsc/src/lib/GrAtscFieldSyncMux.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCFIELDSYNCMUX_H_ +#define _GRATSCFIELDSYNCMUX_H_ + +#include +#include + +/*! + * \brief Insert ATSC Field Syncs as required (atsc_data_segment --> atsc_data_segment) + */ + +class GrAtscFieldSyncMux : public VrHistoryProc +{ + +public: + + GrAtscFieldSyncMux (); + ~GrAtscFieldSyncMux (); + + const char *name () { return "GrAtscFieldSyncMux"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + int forecast (VrSampleRange output, VrSampleRange inputs[]); + + void pre_initialize (); + + static const int N_SAVED_SYMBOLS = 12; + +protected: + VrSampleIndex d_current_index; + bool d_already_output_field_sync; + unsigned char d_saved_symbols[N_SAVED_SYMBOLS]; +}; + +#endif /* _GRATSCFIELDSYNCMUX_H_ */ diff --git a/gr-atsc/src/lib/GrAtscInterleaver.cc b/gr-atsc/src/lib/GrAtscInterleaver.cc new file mode 100644 index 00000000..e766dcfc --- /dev/null +++ b/gr-atsc/src/lib/GrAtscInterleaver.cc @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet_rs_encoded iType; +typedef atsc_mpeg_packet_rs_encoded oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscInterleaver::GrAtscInterleaver () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscInterleaver::~GrAtscInterleaver () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscInterleaver::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, the current contents of the FIFOs, hence + // we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + +#if 0 + cerr << "@@@ GrAtscInterleaver: output.index = " << output.index + << " output.size = " << output.size + << " sum = " << output.index + output.size + << " \t[out = " << out << "]" + << endl; +#endif + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + // pipeline info is handled in the primitive + interleaver.interleave (out[i], in[i]); + } + + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscInterleaver.h b/gr-atsc/src/lib/GrAtscInterleaver.h new file mode 100644 index 00000000..26bf6436 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscInterleaver.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCINTERLEAVER_H_ +#define _GRATSCINTERLEAVER_H_ + +#include +#include +#include + +/*! + * \brief Interleave RS encoded ATSC data ( atsc_mpeg_packet_rs_encoded --> atsc_mpeg_packet_rs_encoded) + */ + +class GrAtscInterleaver : public VrHistoryProc +{ + +public: + + GrAtscInterleaver (); + ~GrAtscInterleaver (); + + const char *name () { return "GrAtscInterleaver"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_data_interleaver interleaver; +}; + +#endif /* _GRATSCINTERLEAVER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscRSDecoder.cc b/gr-atsc/src/lib/GrAtscRSDecoder.cc new file mode 100644 index 00000000..58a69297 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscRSDecoder.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet_rs_encoded iType; +typedef atsc_mpeg_packet_no_sync oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscRSDecoder::GrAtscRSDecoder () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscRSDecoder::~GrAtscRSDecoder () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscRSDecoder::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + assert (in[i].pli.regular_seg_p ()); + out[i].pli = in[i].pli; // copy pipeline info + + int nerrors_not_corrected = rs_decoder.decode (out[i], in[i]); + out[i].pli.set_transport_error (nerrors_not_corrected == -1); + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscRSDecoder.h b/gr-atsc/src/lib/GrAtscRSDecoder.h new file mode 100644 index 00000000..78bc96d0 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscRSDecoder.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCRSDECODER_H_ +#define _GRATSCRSDECODER_H_ + +#include +#include +#include + +/*! + * \brief Pass ATSC data Reed-Solomon decoder( atsc_mpeg_packet_rs_encoded --> atsc_mpeg_rs_no_sync) + */ + +class GrAtscRSDecoder : public VrHistoryProc +{ + +public: + + GrAtscRSDecoder (); + ~GrAtscRSDecoder (); + + const char *name () { return "GrAtscRSDecoder"; } + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_reed_solomon rs_decoder; +}; + +#endif /* _GRATSCRSDECODER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscRSEncoder.cc b/gr-atsc/src/lib/GrAtscRSEncoder.cc new file mode 100644 index 00000000..7b2a7af5 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscRSEncoder.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet_no_sync iType; +typedef atsc_mpeg_packet_rs_encoded oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscRSEncoder::GrAtscRSEncoder () + : VrHistoryProc (NUMBER_OF_OUTPUTS) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscRSEncoder::~GrAtscRSEncoder () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscRSEncoder::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + + // ensure that on the way in, the error bit is clear + // [assertion is not valid, because the randomizer has already scrambled the bits] + // assert ((in[i].data[0] & MPEG_TRANSPORT_ERROR_BIT) == 0); + + assert (in[i].pli.regular_seg_p ()); + out[i].pli = in[i].pli; // copy pipeline info... + rs_encoder.encode (out[i], in[i]); + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscRSEncoder.h b/gr-atsc/src/lib/GrAtscRSEncoder.h new file mode 100644 index 00000000..f14267d1 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscRSEncoder.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCRSENCODER_H_ +#define _GRATSCRSENCODER_H_ + +#include +#include +#include + +/*! + * \brief Encode using Reed Solomon ATSC data (atsc_mpeg_packet_no_sync --> atsc_mpeg_packet_rs_encoded) + */ + +class GrAtscRSEncoder : public VrHistoryProc +{ + +public: + + GrAtscRSEncoder (); + ~GrAtscRSEncoder (); + + const char *name () { return "GrAtscRSEncoder"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_reed_solomon rs_encoder; +}; + +#endif /* _GRATSCRSENCODER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscRandomizer.cc b/gr-atsc/src/lib/GrAtscRandomizer.cc new file mode 100644 index 00000000..d2a14de4 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscRandomizer.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet iType; +typedef atsc_mpeg_packet_no_sync oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscRandomizer::GrAtscRandomizer () + : VrHistoryProc (NUMBER_OF_OUTPUTS), + field2 (false), segno (0) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // We're one-to-one input-to-output so set it to 1. + history = 1; + + // any other init here. +} + +GrAtscRandomizer::~GrAtscRandomizer () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscRandomizer::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, the current contents of the LFSR in the randomizer, hence + // we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i++){ + + // initialize plinfo for downstream + // + // We do this here because the randomizer is effectively + // the head of the tx processing chain + // + out[i].pli.set_regular_seg (field2, segno); + segno++; + if (segno == 312){ + segno = 0; + field2 = !field2; + } + + assert ((in[i].data[1] & MPEG_TRANSPORT_ERROR_BIT) == 0); + + if (out[i].pli.first_regular_seg_p ()) + rand.reset (); + + rand.randomize (out[i], in[i]); + } + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscRandomizer.h b/gr-atsc/src/lib/GrAtscRandomizer.h new file mode 100644 index 00000000..39c1b650 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscRandomizer.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCRANDOMIZER_H_ +#define _GRATSCRANDOMIZER_H_ + +#include +#include +#include + +/*! + * \brief Randomize ATSC data (atsc_mpeg_packet --> atsc_mpeg_packet_no_sync) + */ + +class GrAtscRandomizer : public VrHistoryProc +{ + +public: + + GrAtscRandomizer (); + ~GrAtscRandomizer (); + + const char *name () { return "GrAtscRandomizer"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_randomizer rand; + + // used to initialize plinfo in output + bool field2; + int segno; +}; + +#endif /* _GRATSCRANDOMIZER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscSegSymSync.cc b/gr-atsc/src/lib/GrAtscSegSymSync.cc new file mode 100644 index 00000000..ad2384b8 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscSegSymSync.cc @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +static const int DECIMATION = 2; // close enough for super class's use +static const int N_OUTPUTS = 2; + +GrAtscSegSymSync::GrAtscSegSymSync () + : VrDecimatingSigProc (N_OUTPUTS, DECIMATION) +{ + if (sizeof (float) != sizeof (atsc::syminfo)){ + cerr << "GrAtscSegSymSync: sizeof (float) != sizeof (atsc::syminfo)\n"; + assert (0); + } +} + +GrAtscSegSymSync::~GrAtscSegSymSync () +{ + // Nop +} + + +GrAtscSegSymSync * +GrAtscSegSymSync::create (double nominal_ratio_of_rx_clock_to_symbol_freq) +{ + return create_GrAtscSegSymSyncImpl (nominal_ratio_of_rx_clock_to_symbol_freq); +} diff --git a/gr-atsc/src/lib/GrAtscSegSymSync.h b/gr-atsc/src/lib/GrAtscSegSymSync.h new file mode 100644 index 00000000..1e32e169 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscSegSymSync.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCSEGSYMSYNC_H_ +#define _GRATSCSEGSYMSYNC_H_ + +#include + +/*! + * \brief ATSC SegSymSync + * + * Abstract class that establishes symbol timing and synchronizes + * with data segment boundaries. + * + * Takes a single stream of floats as the input and + * produces two streams as output. The first stream is the data samples + * and is of type float. The second stream is the tags, and is of type syminfo. + * + * The current GNU Radio interface doesn't currently support different + * types on the input ports (or output ports for that matter), but + * since they are the same size, it works. + */ + +#include + +class GrAtscSegSymSync : public VrDecimatingSigProc { + +public: + + GrAtscSegSymSync (); + ~GrAtscSegSymSync (); + + /*! + * \brief reset bit timing loop on channel change + */ + virtual void reset () = 0; + + /*! + * \brief create an instance of GrAtscSegSymSync + */ + static GrAtscSegSymSync *create (double nominal_ratio_of_rx_clock_to_symbol_freq); + +}; + +#endif // _GRATSCSEGSYMSYNC_H_ diff --git a/gr-atsc/src/lib/GrAtscSegSymSyncImpl.cc b/gr-atsc/src/lib/GrAtscSegSymSyncImpl.cc new file mode 100644 index 00000000..ce27eb35 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscSegSymSyncImpl.cc @@ -0,0 +1,103 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +GrAtscSegSymSyncImpl::GrAtscSegSymSyncImpl ( + double nominal_ratio_of_rx_clock_to_symbol_freq) + : d_interp (nominal_ratio_of_rx_clock_to_symbol_freq) +{ + // set approximate decimation rate for superclass's benefit + decimation = (int) rint (nominal_ratio_of_rx_clock_to_symbol_freq); + + history = 1500; // spare input samples in case we need them. + + d_sssr.reset (); + d_interp.reset (); + d_next_input = 0; + d_rx_clock_to_symbol_freq = nominal_ratio_of_rx_clock_to_symbol_freq; +} + +GrAtscSegSymSyncImpl::~GrAtscSegSymSyncImpl () +{ + // Nop +} + +void +GrAtscSegSymSyncImpl::pre_initialize () +{ + setSamplingFrequency ( + getInputSamplingFrequencyN (0) / d_rx_clock_to_symbol_freq); +} + +int +GrAtscSegSymSyncImpl::forecast (VrSampleRange output, + VrSampleRange inputs[]) +{ + assert (numberInputs == 1); // I hate these free references to + // superclass's instance variables... + + inputs[0].index = d_next_input; + inputs[0].size = + ((long unsigned int) (output.size * d_rx_clock_to_symbol_freq) + + history - 1); + + return 0; +} + +int +GrAtscSegSymSyncImpl::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ +#if 0 + float *input_samples = ((float **) ai)[0]; + float *output_samples = ((float **) ao)[0]; + atsc::syminfo *output_info = ((atsc::syminfo **) ao)[1]; + + // FIXME finish... +#endif + assert (0); + + return output.size; +} + +void +GrAtscSegSymSyncImpl::reset () +{ + d_sssr.reset (); + d_interp.reset (); +} + + +/* + * Exported constructor. + * Doesn't expose any of the internals or our compile time dependencies. + */ + +GrAtscSegSymSync * +create_GrAtscSegSymSyncImpl (double nominal_ratio_of_rx_clock_to_symbol_freq) +{ + return new GrAtscSegSymSyncImpl (nominal_ratio_of_rx_clock_to_symbol_freq); +} diff --git a/gr-atsc/src/lib/GrAtscSegSymSyncImpl.h b/gr-atsc/src/lib/GrAtscSegSymSyncImpl.h new file mode 100644 index 00000000..d0387408 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscSegSymSyncImpl.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRATSCSEGSYMSYNCIMPL_H_ +#define _GRATSCSEGSYMSYNCIMPL_H_ + +#include +#include + + +/*! + * \brief concrete implementation of GrAtscSegSymSync + * + * This class implements data segment sync tracking and symbol timing + * using a variation of the method described in + * "ATSC/VSB Tutorial - Receiver Technology" by Wayne E. Bretl of + * Zenith, pgs 41-45. + */ + +class GrAtscSegSymSyncImpl : public GrAtscSegSymSync { + + atsci_sssr d_sssr; + atsci_interpolator d_interp; + VrSampleIndex d_next_input; + double d_rx_clock_to_symbol_freq; // nominal ratio + +public: + + // the standard methods... + + GrAtscSegSymSyncImpl (double nominal_ratio_of_rx_clock_to_symbol_freq); + virtual ~GrAtscSegSymSyncImpl (); + + virtual const char *name () { return "GrAtscSegSymSyncImpl"; } + + virtual int forecast (VrSampleRange output, + VrSampleRange inputs[]); + + virtual int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + + void pre_initialize (); + + + // reset on channel change + + virtual void reset (); + +}; + +#endif /* _GRATSCSEGSYMSYNCIMPL_H_ */ diff --git a/gr-atsc/src/lib/GrAtscSegSymSyncImpl_export.h b/gr-atsc/src/lib/GrAtscSegSymSyncImpl_export.h new file mode 100644 index 00000000..b58dceef --- /dev/null +++ b/gr-atsc/src/lib/GrAtscSegSymSyncImpl_export.h @@ -0,0 +1,26 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class GrAtscSegSymSync; + +GrAtscSegSymSync *create_GrAtscSegSymSyncImpl ( + double nominal_ratio_of_rx_clock_to_symbol_freq); diff --git a/gr-atsc/src/lib/GrAtscSymbolMapper.h b/gr-atsc/src/lib/GrAtscSymbolMapper.h new file mode 100644 index 00000000..061f4aa7 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscSymbolMapper.h @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCSYMBOLMAPPER_H_ +#define _GRATSCSYMBOLMAPPER_H_ + + +#include +#include +#include + +/*! + * \brief take atsc_data_segments and map them to symbols. + * + * Input is a stream of atsc_data_segments. + * Output is a stream of symbols at 1x the symbol rate + * + * This module performs the signal mapping & pilot addition. + */ + +template +class GrAtscSymbolMapper + : public VrInterpolatingSigProcNoWork { + +public: + GrAtscSymbolMapper () + : VrInterpolatingSigProcNoWork(1, INTERP_FACTOR) {}; + + ~GrAtscSymbolMapper () {}; + + const char *name () { return "GrAtscSymbolMapper"; } + + int work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]); + +protected: + static const int INTERP_FACTOR = ATSC_DATA_SEGMENT_LENGTH; +}; + + +template +int +GrAtscSymbolMapper::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + atsc_data_segment *in = ((atsc_data_segment **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + assert ((output.size % INTERP_FACTOR) == 0); + + static const float pilot_add = 1.25; + static const float map[8] = { + -7 + pilot_add, + -5 + pilot_add, + -3 + pilot_add, + -1 + pilot_add, + 1 + pilot_add, + 3 + pilot_add, + 5 + pilot_add, + 7 + pilot_add + }; + + unsigned int oo = 0; + unsigned int nsegs = output.size / INTERP_FACTOR; + + for (unsigned int n = 0; n < nsegs; n++){ + unsigned char *symbol = in[n].data; + + for (int i = 0; i < ATSC_DATA_SEGMENT_LENGTH; i++){ + out[oo++] = (oType) map[symbol[i] & 0x7]; + } + } + + assert (oo == output.size); + return output.size; +} + +#endif /* _GRATSCSYMBOLMAPPER_H_ */ diff --git a/gr-atsc/src/lib/GrAtscTrellisEncoder.cc b/gr-atsc/src/lib/GrAtscTrellisEncoder.cc new file mode 100644 index 00000000..8c55e145 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscTrellisEncoder.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// typedefs for fundamental i/o types + +typedef atsc_mpeg_packet_rs_encoded iType; +typedef atsc_data_segment oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscTrellisEncoder::GrAtscTrellisEncoder () + : VrHistoryProc (NUMBER_OF_OUTPUTS), last_start(-1) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // + // We need our input to be aligned on a 12-segment boundary, + // to ensure satisfaction, ask for 11 more + history = 1 + (atsci_trellis_encoder::NCODERS - 1); + + // any other init here. + + // Let the bottom end know we must produce output in multiples of 12 segments. + setOutputSize (atsci_trellis_encoder::NCODERS); +} + +GrAtscTrellisEncoder::~GrAtscTrellisEncoder () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscTrellisEncoder::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, the current state of the encoders, hence + // we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + +#if 0 + cerr << "@@@ GrAtscTrellisEncoder: output.index = " << output.index + << " output.size = " << output.size + << " sum = " << output.index + output.size + << " \t[in = " << in << "]" + << endl; +#endif + + assert (output.size % atsci_trellis_encoder::NCODERS == 0); + + + // find the first mod 12 boundary to begin decoding + int start; + for (start = 0; start < atsci_trellis_encoder::NCODERS; start++){ + plinfo::sanity_check (in[start].pli); + assert (in[start].pli.regular_seg_p ()); + if ((in[start].pli.segno () % atsci_trellis_encoder::NCODERS) == 0) + break; + } + + if (start == atsci_trellis_encoder::NCODERS){ + // we didn't find a mod 12 boundary. There's some kind of problem + // upstream of us (not yet sync'd??) + cerr << "!!!GrAtscTrellisEncoder: no mod-12 boundary found\7\n"; + start = 0; + } + else if (start != last_start){ + cerr << "GrAtscTrellisEncoder: new starting offset = " << start + << " output.index = " << output.index << endl; + last_start = start; + } + + + // FIXME paranoid check for problem + for (unsigned int i = 0; i < output.size; i++){ + plinfo::sanity_check (in[i + start].pli); + } + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i += atsci_trellis_encoder::NCODERS){ + // primitive does 12 segments at a time. + // pipeline info is handled in the primitive. + encoder.encode (&out[i], &in[i + start]); + } + +#if 0 + // FIXME paranoid check for problem + for (unsigned int i = 0; i < output.size; i++){ + plinfo::sanity_check (out[i].pli); + assert (out[i].pli.regular_seg_p ()); + } +#endif + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscTrellisEncoder.h b/gr-atsc/src/lib/GrAtscTrellisEncoder.h new file mode 100644 index 00000000..ac17de35 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscTrellisEncoder.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCTRELLISENCODER_H_ + +#include +#include + +/*! + * \brief ATSC 12-way interleaved trellis encoder (atsc_mpeg_packet_rs_encoded --> atsc_data_segment) + */ + +class GrAtscTrellisEncoder : public VrHistoryProc +{ + +public: + + GrAtscTrellisEncoder (); + ~GrAtscTrellisEncoder (); + + const char *name () { return "GrAtscTrellisEncoder"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_trellis_encoder encoder; + int last_start; +}; + +#endif diff --git a/gr-atsc/src/lib/GrAtscViterbiDecoder.cc b/gr-atsc/src/lib/GrAtscViterbiDecoder.cc new file mode 100644 index 00000000..2b7174b8 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscViterbiDecoder.cc @@ -0,0 +1,135 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +// typedefs for fundamental i/o types + +typedef atsc_soft_data_segment iType; +typedef atsc_mpeg_packet_rs_encoded oType; + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + + +GrAtscViterbiDecoder::GrAtscViterbiDecoder () + : VrHistoryProc (NUMBER_OF_OUTPUTS), last_start(-1) +{ + // 1 + number of extra input elements at which we look. This is + // used by the superclass's forecast routine to get us the correct + // range on our inputs. + // + // We need our input to be aligned on a 12-segment boundary, + // to ensure satisfaction, ask for 11 more + history = 1 + (atsci_viterbi_decoder::NCODERS - 1); + + // any other init here. + + // Let the bottom end know we must produce output in multiples of 12 segments. + setOutputSize (atsci_viterbi_decoder::NCODERS); +} + +GrAtscViterbiDecoder::~GrAtscViterbiDecoder () +{ + // Anything that isn't automatically cleaned up... +} + +/* + * This is the real work horse. In general this interface can handle + * multiple streams of input and output, but we almost always + * use a single input and output stream. + */ + +int +GrAtscViterbiDecoder::work (VrSampleRange output, void *ao[], + VrSampleRange inputs[], void *ai[]) +{ + // If we have state that persists across invocations (e.g., we have + // instance variables that we modify), we must use the sync method + // to indicate to the scheduler that our output must be computed in + // order. This doesn't keep other things from being run in + // parallel, it just means that at any given time, there is only a + // single thread working this code, and that the scheduler will + // ensure that we are asked to produce output that is contiguous and + // that will be presented to us in order of increasing time. + + // We have state, the current state of the decoder, hence + // we must use sync. + + sync (output.index); + + // construct some nicer i/o pointers to work with. + + iType *in = ((iType **) ai)[0]; + oType *out = ((oType **) ao)[0]; + + + assert (output.size % atsci_viterbi_decoder::NCODERS == 0); + + // find the first mod 12 boundary to begin decoding + int start; + for (start = 0; start < atsci_viterbi_decoder::NCODERS; start++){ + assert (in[start].pli.regular_seg_p ()); + if ((in[start].pli.segno () % atsci_viterbi_decoder::NCODERS) == 0) + break; + } + + if (start == atsci_viterbi_decoder::NCODERS){ + // we didn't find a mod 12 boundary. There's some kind of problem + // upstream of us (not yet sync'd??) + cerr << "!!!GrAtscViterbiDecoder: no mod-12 boundary found\7\n"; + start = 0; + } + else if (start != last_start){ + cerr << "GrAtscViterbiDecoder: new starting offset = " << start + << " output.index = " << output.index << endl; + last_start = start; + } + + // We must produce output.size units of output. + + for (unsigned int i = 0; i < output.size; i += atsci_viterbi_decoder::NCODERS){ + // primitive does 12 segments at a time. + // pipeline info is handled in the primitive. + decoder.decode (&out[i], &in[i + start]); + } + +#if 0 + // FIXME paranoid check... + for (unsigned int i = 0; i < output.size; i++){ + plinfo::sanity_check (out[i].pli); + assert (out[i].pli.regular_seg_p ()); + } +#endif + +#if 0 + cerr << "@@@ GrAtscViterbiDecoder: output.index = " << output.index + << " output.size = " << output.size + << " sum = " << output.index + output.size << endl; +#endif + + // Return the number of units we produced. + // Note that for all intents and purposes, it is an error to + // produce less than you are asked for. + + return output.size; +} diff --git a/gr-atsc/src/lib/GrAtscViterbiDecoder.h b/gr-atsc/src/lib/GrAtscViterbiDecoder.h new file mode 100644 index 00000000..10e34806 --- /dev/null +++ b/gr-atsc/src/lib/GrAtscViterbiDecoder.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRATSCVITERBIDECODER_H_ + +#include +#include + +/*! + * \brief ATSC 12-way interleaved viterbi decoder (atsc_soft_data_segment --> atsc_mpeg_packet_rs_encoded) + */ + +class GrAtscViterbiDecoder : public VrHistoryProc +{ + +public: + + GrAtscViterbiDecoder (); + ~GrAtscViterbiDecoder (); + + const char *name () { return "GrAtscViterbiDecoder"; } + + int work (VrSampleRange output, void *o[], + VrSampleRange inputs[], void *i[]); + +protected: + atsci_viterbi_decoder decoder; + int last_start; +}; + +#endif diff --git a/gr-atsc/src/lib/Makefile.am b/gr-atsc/src/lib/Makefile.am new file mode 100644 index 00000000..d5ae6ed5 --- /dev/null +++ b/gr-atsc/src/lib/Makefile.am @@ -0,0 +1,268 @@ +# +# Copyright 2001,2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.atsc module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(CPPUNIT_INCLUDES) + +#LIBS += $(GNURADIO_CORE_LIBS) + +EXTRA_DIST = \ + gen_encoder.py \ + qa_atsci_trellis_encoder_t1_input.dat \ + qa_atsci_trellis_encoder_t1_output.dat \ + qa_atsci_viterbi_decoder_t1_input.dat \ + qa_atsci_viterbi_decoder_t1_output.dat + + +BUILT_SOURCES = \ + atsci_viterbi_mux.cc \ + $(swig_built_sources) + + +TESTS = \ + test_atsci + + +# We build two libtool convenience libraries + +noinst_LTLIBRARIES = libatsc.la libatsc-qa.la + +# FIXME +# atsci_exp2_lp.cc \ +# atsci_root_raised_cosine.cc \ +# atsci_root_raised_cosine_bandpass.cc \ +# atsci_vsbtx_lp.cc \ +# + +libatsc_la_SOURCES = \ + atsc_derandomizer.cc \ + atsc_randomizer.cc \ + atsc_rs_decoder.cc \ + atsc_rs_encoder.cc \ + atsc_interleaver.cc \ + atsc_deinterleaver.cc \ + atsc_trellis_encoder.cc \ + atsc_viterbi_decoder.cc \ + atsc_ds_to_softds.cc \ + atsc_field_sync_mux.cc \ + atsc_field_sync_demux.cc \ + atsc_equalizer.cc \ + atsc_fs_checker.cc \ + atsc_bit_timing_loop.cc \ + atsc_fpll.cc \ + atsc_depad.cc \ + atsci_basic_trellis_encoder.cc \ + atsci_data_interleaver.cc \ + atsci_equalizer.cc \ + atsci_equalizer_lms.cc \ + atsci_equalizer_lms2.cc \ + atsci_equalizer_nop.cc \ + atsci_fake_single_viterbi.cc \ + atsci_fs_checker.cc \ + atsci_fs_checker_naive.cc \ + atsci_fs_correlator.cc \ + atsci_fs_correlator_naive.cc \ + atsci_single_viterbi.cc \ + atsci_sssr.cc \ + atsci_pnXXX.cc \ + atsci_randomizer.cc \ + atsci_reed_solomon.cc \ + atsci_sliding_correlator.cc \ + atsci_trellis_encoder.cc \ + atsci_viterbi_decoder.cc \ + create_atsci_equalizer.cc \ + create_atsci_fs_checker.cc \ + create_atsci_fs_correlator.cc \ + plinfo.cc + +libatsc_qa_la_SOURCES = \ + qa_atsci_basic_trellis_encoder.cc \ + qa_atsci_data_interleaver.cc \ + qa_atsci_equalizer_nop.cc \ + qa_atsci_fake_single_viterbi.cc \ + qa_atsci_fs_correlator.cc \ + qa_atsci_single_viterbi.cc \ + qa_atsci_randomizer.cc \ + qa_atsci_reed_solomon.cc \ + qa_atsci_sliding_correlator.cc \ + qa_atsci_trellis_encoder.cc \ + qa_atsci_viterbi_decoder.cc \ + qa_convolutional_interleaver.cc \ + qa_atsci.cc \ + qa_interleaver_fifo.cc + + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + atsc_consts.h \ + atsc_derandomizer.h \ + atsc_randomizer.h \ + atsc_rs_decoder.h \ + atsc_rs_encoder.h \ + atsc_interleaver.h \ + atsc_deinterleaver.h \ + atsc_trellis_encoder.h \ + atsc_viterbi_decoder.h \ + atsc_ds_to_softds.h \ + atsc_field_sync_mux.h \ + atsc_field_sync_demux.h \ + atsc_equalizer.h \ + atsc_fs_checker.h \ + atsc_bit_timing_loop.h \ + atsc_fpll.h \ + atsc_depad.h \ + atsc_types.h \ + atsci_basic_trellis_encoder.h \ + atsci_data_interleaver.h \ + atsci_diag_output.h \ + atsci_equalizer.h \ + atsci_equalizer_lms.h \ + atsci_equalizer_lms2.h \ + atsci_equalizer_nop.h \ + atsci_exp2_lp.h \ + atsci_fake_single_viterbi.h \ + atsci_fs_checker.h \ + atsci_fs_checker_naive.h \ + atsci_fs_correlator.h \ + atsci_fs_correlator_naive.h \ + atsci_pnXXX.h \ + atsci_randomizer.h \ + atsci_reed_solomon.h \ + atsci_root_raised_cosine.h \ + atsci_root_raised_cosine_bandpass.h \ + atsci_single_viterbi.h \ + atsci_slicer_agc.h \ + atsci_sliding_correlator.h \ + atsci_sssr.h \ + atsci_syminfo.h \ + atsci_sync_tag.h \ + atsci_trellis_encoder.h \ + atsci_viterbi_decoder.h \ + atsci_vsbtx_lp.h \ + convolutional_interleaver.h \ + create_atsci_equalizer.h \ + create_atsci_fs_checker.h \ + create_atsci_fs_correlator.h \ + fpll_btloop_coupling.h \ + interleaver_fifo.h \ + qa_atsci.h \ + qa_atsci_basic_trellis_encoder.h \ + qa_atsci_data_interleaver.h \ + qa_atsci_equalizer_nop.h \ + qa_atsci_fake_single_viterbi.h \ + qa_atsci_fs_correlator.h \ + qa_atsci_randomizer.h \ + qa_atsci_reed_solomon.h \ + qa_atsci_single_viterbi.h \ + qa_atsci_sliding_correlator.h \ + qa_atsci_trellis_encoder.h \ + qa_atsci_viterbi_decoder.h \ + qa_convolutional_interleaver.h \ + qa_interleaver_fifo.h + + +# programs we build but don't install +# FIXME add test_atsc +noinst_PROGRAMS = \ + atsci_viterbi_gen \ + test_atsci + + +atsci_viterbi_gen_SOURCES = atsci_viterbi_gen.cc + +atsci_viterbi_mux.cc: atsci_viterbi_gen$(EXEEXT) + $(MAKE) $(AM_MAKEFLAGS) CXX="$(CXX_FOR_BUILD)" atsci_viterbi_gen$(EXEEXT) + ./atsci_viterbi_gen$(EXEEXT) -o atsci_viterbi_mux.cc + + +test_atsci_SOURCES = test_atsci.cc +test_atsci_LDADD = libatsc-qa.la libatsc.la $(GNURADIO_CORE_LIBS) $(CPPUNIT_LIBS) + + +# ------------------------------------------------------------------------ +# This is the swig-ish part of the Makefile. +# It builds the atsc module which we'll load into python +# ------------------------------------------------------------------------ + +SWIGCPPPYTHONARGS = -fvirtual -python -modern $(PYTHON_CPPFLAGS) \ + $(STD_DEFINES_AND_INCLUDES) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +LOCAL_IFILES = \ + atsc.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _atsc shared library +# and knows how to call our extensions. + +swig_built_sources = \ + atsc.cc \ + atsc.py + +# This gets atsc.py installed in the right place +ourpython_PYTHON = \ + atsc.py + +ourlib_LTLIBRARIES = _atsc.la + +# These are the source files that go into the shared library +_atsc_la_SOURCES = \ + atsc.cc + +# magic flags +_atsc_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library +_atsc_la_LIBADD = \ + $(GNURADIO_CORE_LIBS) \ + $(PYTHON_LDFLAGS) \ + libatsc.la \ + -lstdc++ + +atsc.cc atsc.py: atsc.i $(ALL_IFILES) + $(SWIG) $(SWIGCPPPYTHONARGS) -module atsc -o atsc.cc $< + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +# ------------------------------------------------------------------------ +# Cleanup +# ------------------------------------------------------------------------ + +CLEANFILES = atsci_viterbi_mux.cc +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc + diff --git a/gr-atsc/src/lib/atsc.i b/gr-atsc/src/lib/atsc.i new file mode 100644 index 00000000..026332b2 --- /dev/null +++ b/gr-atsc/src/lib/atsc.i @@ -0,0 +1,269 @@ +/* -*- c++ -*- */ + +%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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include "atsc_consts.h" + +%constant int sizeof_atsc_mpeg_packet = sizeof(atsc_mpeg_packet); +%constant int sizeof_atsc_mpeg_packet_no_sync = sizeof(atsc_mpeg_packet_no_sync); +%constant int sizeof_atsc_mpeg_packet_rs_encoded = sizeof(atsc_mpeg_packet_rs_encoded); +%constant int sizeof_atsc_data_segment = sizeof(atsc_data_segment); +%constant int sizeof_atsc_soft_data_segment = sizeof(atsc_soft_data_segment); + +%constant int sizeof_atsc_mpeg_packet_pad = atsc_mpeg_packet::NPAD; +%constant int sizeof_atsc_mpeg_packet_no_sync_pad = atsc_mpeg_packet_no_sync::NPAD; +%constant int sizeof_atsc_mpeg_packet_rs_encoded_pad = atsc_mpeg_packet_rs_encoded::NPAD; +%constant int sizeof_atsc_data_segment_pad = atsc_data_segment::NPAD; +%constant int sizeof_atsc_soft_data_segment_pad = atsc_soft_data_segment::NPAD; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,randomizer); + +atsc_randomizer_sptr atsc_make_randomizer(); + +class atsc_randomizer : public gr_sync_block +{ + atsc_randomizer(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,derandomizer); + +atsc_derandomizer_sptr atsc_make_derandomizer(); + +class atsc_derandomizer : public gr_sync_block +{ + atsc_derandomizer(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,rs_encoder); + +atsc_rs_encoder_sptr atsc_make_rs_encoder(); + +class atsc_rs_encoder : public gr_sync_block +{ + atsc_rs_encoder(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,rs_decoder); + +atsc_rs_decoder_sptr atsc_make_rs_decoder(); + +class atsc_rs_decoder : public gr_sync_block +{ + atsc_rs_decoder(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,interleaver); + +atsc_interleaver_sptr atsc_make_interleaver(); + +class atsc_interleaver : public gr_sync_block +{ + atsc_interleaver(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,deinterleaver); + +atsc_deinterleaver_sptr atsc_make_deinterleaver(); + +class atsc_deinterleaver : public gr_sync_block +{ + atsc_deinterleaver(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,trellis_encoder); + +atsc_trellis_encoder_sptr atsc_make_trellis_encoder(); + +class atsc_trellis_encoder : public gr_sync_block +{ + atsc_trellis_encoder(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,viterbi_decoder); + +atsc_viterbi_decoder_sptr atsc_make_viterbi_decoder(); + +class atsc_viterbi_decoder : public gr_sync_block +{ + atsc_viterbi_decoder(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,ds_to_softds); + +atsc_ds_to_softds_sptr atsc_make_ds_to_softds(); + +class atsc_ds_to_softds : public gr_sync_block +{ + atsc_ds_to_softds(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,field_sync_mux); + +atsc_field_sync_mux_sptr atsc_make_field_sync_mux(); + +class atsc_field_sync_mux : public gr_sync_block +{ + atsc_field_sync_mux(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,field_sync_demux); + +atsc_field_sync_demux_sptr atsc_make_field_sync_demux(); + +class atsc_field_sync_demux : public gr_sync_decimator +{ + atsc_field_sync_demux(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,equalizer); + +atsc_equalizer_sptr atsc_make_equalizer(); + +class atsc_equalizer : public gr_sync_block +{ + atsc_equalizer(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,fs_checker); + +atsc_fs_checker_sptr atsc_make_fs_checker(); + +class atsc_fs_checker : public gr_sync_block +{ + atsc_fs_checker(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,bit_timing_loop); + +atsc_bit_timing_loop_sptr atsc_make_bit_timing_loop(); + +class atsc_bit_timing_loop : public gr_block +{ + atsc_bit_timing_loop(); + +public: + void reset(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,fpll); + +atsc_fpll_sptr atsc_make_fpll(); + +class atsc_fpll : public gr_sync_block +{ + atsc_fpll(); + +public: + void reset(); + +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(atsc,depad); + +atsc_depad_sptr atsc_make_depad(); + +class atsc_depad : public gr_sync_interpolator +{ + atsc_depad(); + +public: + void reset(); + +}; + +// ---------------------------------------------------------------- diff --git a/gr-atsc/src/lib/atsc_bit_timing_loop.cc b/gr-atsc/src/lib/atsc_bit_timing_loop.cc new file mode 100644 index 00000000..432ad4c5 --- /dev/null +++ b/gr-atsc/src/lib/atsc_bit_timing_loop.cc @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +float input_rate = 20e6; +double ratio_of_rx_clock_to_symbol_freq = input_rate / ATSC_SYMBOL_RATE; + + +atsc_bit_timing_loop_sptr +atsc_make_bit_timing_loop() +{ + return atsc_bit_timing_loop_sptr(new atsc_bit_timing_loop()); +} + + +atsc_bit_timing_loop::atsc_bit_timing_loop() + : gr_block("atsc_bit_timing_loop", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(2, 2, sizeof(float))), + d_interp(ratio_of_rx_clock_to_symbol_freq), d_next_input(0), + d_rx_clock_to_symbol_freq (ratio_of_rx_clock_to_symbol_freq) +{ + reset(); +} + +void +atsc_bit_timing_loop::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items * d_rx_clock_to_symbol_freq + 1500 - 1; + + inputs0_size = noutput_items * d_rx_clock_to_symbol_freq + 1500 - 1; + inputs0_index = d_next_input; +} + +int +atsc_bit_timing_loop::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r * d_rx_clock_to_symbol_freq); + return r; +} + + +int +atsc_bit_timing_loop::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out_sample = (float *) output_items[0]; + atsc::syminfo *out_tag = (atsc::syminfo *) output_items[1]; + + assert(sizeof(float) == sizeof(atsc::syminfo)); + + // We are tasked with producing output.size output samples. + // We will consume approximately 2 * output.size input samples. + + int si = 0; // source index + unsigned int k; // output index + + float interp_sample; + int symbol_index; + double timing_adjustment = 0; + bool seg_locked; + atsc::syminfo tag; + + memset (&tag, 0, sizeof (tag)); + + + for (k = 0; k < noutput_items; k++){ + if (!d_interp.update (in, inputs0_size, &si, timing_adjustment, &interp_sample)){ + fprintf (stderr, "GrAtscBitTimingLoop3: ran short on data...\n"); + break; + } + + d_sssr.update (interp_sample, &seg_locked, &symbol_index, &timing_adjustment); + out_sample[k] = interp_sample; + tag.valid = seg_locked; + tag.symbol_num = symbol_index; + out_tag[k] = tag; + + } + + d_next_input += si; // update next_input so forecast can get us what we need + return k; +} diff --git a/gr-atsc/src/lib/atsc_bit_timing_loop.h b/gr-atsc/src/lib/atsc_bit_timing_loop.h new file mode 100644 index 00000000..58209276 --- /dev/null +++ b/gr-atsc/src/lib/atsc_bit_timing_loop.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_BIT_TIMING_LOOP_H +#define INCLUDED_ATSC_BIT_TIMING_LOOP_H + +#include +#include +#include +#include +#include + +class atsc_bit_timing_loop; +typedef boost::shared_ptr atsc_bit_timing_loop_sptr; + +atsc_bit_timing_loop_sptr atsc_make_bit_timing_loop(); + +/*! + * \brief ATSC BitTimingLoop3 + * \ingroup atsc + * + * This class accepts a single real input and produces two outputs, + * the raw symbol (float) and the tag (atsc_syminfo) + */ +class atsc_bit_timing_loop : public gr_block +{ + friend atsc_bit_timing_loop_sptr atsc_make_bit_timing_loop(); + + atsc_bit_timing_loop(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } + + ~atsc_bit_timing_loop () { }; + + 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); + + + // debug (NOPs) + void set_mu (double a_mu) { } + void set_no_update (bool a_no_update) { } + void set_loop_filter_tap (double tap) { } + void set_timing_rate (double rate) { } + + + protected: + + atsci_sssr d_sssr; + atsci_interpolator d_interp; + unsigned long long d_next_input; + double d_rx_clock_to_symbol_freq; + + unsigned long long inputs0_index; // for inputs[0].index + unsigned long inputs0_size; // for inputs[0].size + + +}; + +#endif /* INCLUDED_ATSC_BIT_TIMING_LOOP_H */ + + + diff --git a/gr-atsc/src/lib/atsc_consts.h b/gr-atsc/src/lib/atsc_consts.h new file mode 100644 index 00000000..197ec57b --- /dev/null +++ b/gr-atsc/src/lib/atsc_consts.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_CONSTS_H_ +#define _ATSC_CONSTS_H_ + +static const double ATSC_SYMBOL_RATE = 4.5e6 / 286 * 684; // ~10.76 MHz +static const double ATSC_DATA_SEGMENT_RATE = ATSC_SYMBOL_RATE / 832; // ~12.935 kHz + + +static const int ATSC_MPEG_DATA_LENGTH = 187; +static const int ATSC_MPEG_PKT_LENGTH = 188; // sync + data +static const int ATSC_MPEG_RS_ENCODED_LENGTH = 207; +static const int ATSC_DATA_SEGMENT_LENGTH = 832; // includes 4 sync symbols at beginning +static const int ATSC_DSEGS_PER_FIELD = 312; // regular data segs / field + + +static const int MPEG_SYNC_BYTE = 0x47; + +static const int MPEG_TRANSPORT_ERROR_BIT = 0x80; // top bit of byte after SYNC + + +#endif // _ATSC_CONSTS_H_ diff --git a/gr-atsc/src/lib/atsc_deinterleaver.cc b/gr-atsc/src/lib/atsc_deinterleaver.cc new file mode 100644 index 00000000..f698726c --- /dev/null +++ b/gr-atsc/src/lib/atsc_deinterleaver.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_deinterleaver_sptr +atsc_make_deinterleaver() +{ + return atsc_deinterleaver_sptr(new atsc_deinterleaver()); +} + +atsc_deinterleaver::atsc_deinterleaver() + : gr_sync_block("atsc_deinterleaver", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded))) +{ + reset(); +} + +int +atsc_deinterleaver::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet_rs_encoded *in = (const atsc_mpeg_packet_rs_encoded *) input_items[0]; + atsc_mpeg_packet_rs_encoded *out = (atsc_mpeg_packet_rs_encoded *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + d_deinterleaver.deinterleave (out[i], in[i]); + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_deinterleaver.h b/gr-atsc/src/lib/atsc_deinterleaver.h new file mode 100644 index 00000000..17527b5e --- /dev/null +++ b/gr-atsc/src/lib/atsc_deinterleaver.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_DEINTERLEAVER_H +#define INCLUDED_ATSC_DEINTERLEAVER_H + +#include +#include + +class atsc_deinterleaver; +typedef boost::shared_ptr atsc_deinterleaver_sptr; + +atsc_deinterleaver_sptr atsc_make_deinterleaver(); + +/*! + * \brief Deinterleave RS encoded ATSC data ( atsc_mpeg_packet_rs_encoded --> atsc_mpeg_packet_rs_encoded) + * \ingroup atsc + * + * input: atsc_mpeg_packet_rs_encoded; output: atsc_mpeg_packet_rs_encoded + */ +class atsc_deinterleaver : public gr_sync_block +{ + friend atsc_deinterleaver_sptr atsc_make_deinterleaver(); + + atsci_data_deinterleaver d_deinterleaver; + + atsc_deinterleaver(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_DEINTERLEAVER_H */ diff --git a/gr-atsc/src/lib/atsc_depad.cc b/gr-atsc/src/lib/atsc_depad.cc new file mode 100644 index 00000000..e63eebc3 --- /dev/null +++ b/gr-atsc/src/lib/atsc_depad.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +static const int INTR = ATSC_MPEG_PKT_LENGTH; + +atsc_depad_sptr +atsc_make_depad() +{ + return atsc_depad_sptr(new atsc_depad()); +} + +atsc_depad::atsc_depad() + : gr_sync_interpolator("atsc_depad", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet)), + gr_make_io_signature(1, 1, sizeof(unsigned char)), + INTR) +{ + reset(); +} + +void +atsc_depad::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items / ATSC_MPEG_PKT_LENGTH; +} + + +int +atsc_depad::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet *in = (const atsc_mpeg_packet *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + // size with padding (256) + unsigned int ATSC_MPEG_PKT = sizeof(atsc_mpeg_packet); + unsigned int i; + + for (i = 0; i < noutput_items/ATSC_MPEG_PKT + 1; i++){ + for (int j = 0; j < ATSC_MPEG_PKT_LENGTH; j++) + out[i * ATSC_MPEG_PKT_LENGTH + j] = in[i * ATSC_MPEG_PKT].data[j]; + + } + + return i * ATSC_MPEG_PKT_LENGTH; +} + + + + diff --git a/gr-atsc/src/lib/atsc_depad.h b/gr-atsc/src/lib/atsc_depad.h new file mode 100644 index 00000000..3db933b5 --- /dev/null +++ b/gr-atsc/src/lib/atsc_depad.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_DEPAD_H +#define INCLUDED_ATSC_DEPAD_H + +#include + +class atsc_depad; +typedef boost::shared_ptr atsc_depad_sptr; + +atsc_depad_sptr atsc_make_depad(); + +/*! + * \brief depad mpeg ts packets from 256 byte atsc_mpeg_packet + * to 188 byte char + * \ingroup atsc + * + * input: atsc_mpeg_packet; output: unsigned char + */ +class atsc_depad : public gr_sync_interpolator +{ + friend atsc_depad_sptr atsc_make_depad(); + + atsc_depad(); + +public: + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_DEPAD_H */ diff --git a/gr-atsc/src/lib/atsc_derandomizer.cc b/gr-atsc/src/lib/atsc_derandomizer.cc new file mode 100644 index 00000000..2a411271 --- /dev/null +++ b/gr-atsc/src/lib/atsc_derandomizer.cc @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_derandomizer_sptr +atsc_make_derandomizer() +{ + return atsc_derandomizer_sptr(new atsc_derandomizer()); +} + +atsc_derandomizer::atsc_derandomizer() + : gr_sync_block("atsc_derandomizer", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_no_sync)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet))) +{ + reset(); +} + +void +atsc_derandomizer::reset() +{ + d_rand.reset(); +} + +int +atsc_derandomizer::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet_no_sync *in = (const atsc_mpeg_packet_no_sync *) input_items[0]; + atsc_mpeg_packet *out = (atsc_mpeg_packet *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + + assert(in[i].pli.regular_seg_p()); + + if (in[i].pli.first_regular_seg_p()) + d_rand.reset(); + + d_rand.derandomize(out[i], in[i]); + + // Check the pipeline info for error status and and set the + // corresponding bit in transport packet header. + + if (in[i].pli.transport_error_p()) + out[i].data[1] |= MPEG_TRANSPORT_ERROR_BIT; + else + out[i].data[1] &= ~MPEG_TRANSPORT_ERROR_BIT; + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_derandomizer.h b/gr-atsc/src/lib/atsc_derandomizer.h new file mode 100644 index 00000000..97cb3a2f --- /dev/null +++ b/gr-atsc/src/lib/atsc_derandomizer.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_DERANDOMIZER_H +#define INCLUDED_ATSC_DERANDOMIZER_H + +#include +#include + +class atsc_derandomizer; +typedef boost::shared_ptr atsc_derandomizer_sptr; + +atsc_derandomizer_sptr atsc_make_derandomizer(); + +/*! + * \brief "dewhiten" incoming mpeg transport stream packets + * \ingroup atsc + * + * input: atsc_mpeg_packet_no_sync; output: atsc_mpeg_packet; + */ +class atsc_derandomizer : public gr_sync_block +{ + friend atsc_derandomizer_sptr atsc_make_derandomizer(); + + atsci_randomizer d_rand; + + atsc_derandomizer(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset(); +}; + + +#endif /* INCLUDED_ATSC_DERANDOMIZER_H */ diff --git a/gr-atsc/src/lib/atsc_ds_to_softds.cc b/gr-atsc/src/lib/atsc_ds_to_softds.cc new file mode 100644 index 00000000..682cea02 --- /dev/null +++ b/gr-atsc/src/lib/atsc_ds_to_softds.cc @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_ds_to_softds_sptr +atsc_make_ds_to_softds() +{ + return atsc_ds_to_softds_sptr(new atsc_ds_to_softds()); +} + +atsc_ds_to_softds::atsc_ds_to_softds() + : gr_sync_block("atsc_ds_to_softds", + gr_make_io_signature(1, 1, sizeof(atsc_data_segment)), + gr_make_io_signature(1, 1, sizeof(atsc_soft_data_segment))) +{ + reset(); +} + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +void +atsc_ds_to_softds::map_to_soft_symbols (atsc_soft_data_segment &out, + const atsc_data_segment &in) +{ + for (unsigned int i = 0; i < NELEM (in.data); i++){ + out.data[i] = in.data[i] * 2 - 7; + } +} + + +int +atsc_ds_to_softds::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_data_segment *in = (const atsc_data_segment *) input_items[0]; + atsc_soft_data_segment *out = (atsc_soft_data_segment *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + + out[i].pli = in[i].pli; // copy pipeline info... + map_to_soft_symbols(out[i], in[i]); + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_ds_to_softds.h b/gr-atsc/src/lib/atsc_ds_to_softds.h new file mode 100644 index 00000000..837da7db --- /dev/null +++ b/gr-atsc/src/lib/atsc_ds_to_softds.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_DS_TO_SOFTDS_H +#define INCLUDED_ATSC_DS_TO_SOFTDS_H + +#include +#include + +class atsc_ds_to_softds; +typedef boost::shared_ptr atsc_ds_to_softds_sptr; + +atsc_ds_to_softds_sptr atsc_make_ds_to_softds(); + +/*! + * \brief Debug glue routine (atsc_data_segment --> atsc_soft_data_segment) + * \ingroup atsc + * + * input: atsc_data_segment; output: atsc_soft_data_segment + */ +class atsc_ds_to_softds : public gr_sync_block +{ + friend atsc_ds_to_softds_sptr atsc_make_ds_to_softds(); + + atsc_ds_to_softds(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void map_to_soft_symbols (atsc_soft_data_segment &out, + const atsc_data_segment &in); + + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_DS_TO_SOFTDS_H */ diff --git a/gr-atsc/src/lib/atsc_equalizer.cc b/gr-atsc/src/lib/atsc_equalizer.cc new file mode 100644 index 00000000..168d6220 --- /dev/null +++ b/gr-atsc/src/lib/atsc_equalizer.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + + +atsc_equalizer_sptr +atsc_make_equalizer() +{ + return atsc_equalizer_sptr(new atsc_equalizer()); +} + +// had atsc_equalizer(atsci_equalizer *equalizer) +atsc_equalizer::atsc_equalizer() + : gr_sync_block("atsc_equalizer", + gr_make_io_signature(2, 2, sizeof(float)), + gr_make_io_signature(2, 2, sizeof(float))) +{ + d_equalizer = create_atsci_equalizer_lms(); +} + +atsc_equalizer::~atsc_equalizer () +{ + // Anything that isn't automatically cleaned up... + + delete d_equalizer; +} + + +void +atsc_equalizer::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + + int ntaps = d_equalizer->ntaps (); + int npretaps = d_equalizer->npretaps (); + + assert (ntaps >= 1); + assert (npretaps >= 0 && npretaps < ntaps); + + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items); +} + + +int +atsc_equalizer::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]; + const atsc::syminfo *in_tags = (const atsc::syminfo *) input_items[1]; + float *out = (float *) output_items[0]; + atsc::syminfo *out_tags = (atsc::syminfo *) output_items[1]; + + assert(sizeof(float) == sizeof(atsc::syminfo)); + + + // peform the actual equalization + + d_equalizer->filter (in, in_tags, + out, noutput_items); + + // write the output tags + + for (int i = 0; i < noutput_items; i++) + out_tags[i] = in_tags[i]; + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_equalizer.h b/gr-atsc/src/lib/atsc_equalizer.h new file mode 100644 index 00000000..a8f448d7 --- /dev/null +++ b/gr-atsc/src/lib/atsc_equalizer.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_EQUALIZER_H +#define INCLUDED_ATSC_EQUALIZER_H + +#include +#include + +class atsc_equalizer; +typedef boost::shared_ptr atsc_equalizer_sptr; + +atsc_equalizer_sptr atsc_make_equalizer(); + +/*! + * \brief ATSC equalizer (float,syminfo --> float,syminfo) + * \ingroup atsc + * + * first inputs are data samples, second inputs are tags. + * first outputs are equalized data samples, second outputs are tags. + */ +class atsc_equalizer : public gr_sync_block +{ + friend atsc_equalizer_sptr atsc_make_equalizer(); + + atsc_equalizer(); + +public: + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } + + ~atsc_equalizer (); + + +protected: + atsci_equalizer *d_equalizer; + +}; + + +#endif /* INCLUDED_ATSC_EQUALIZER_H */ diff --git a/gr-atsc/src/lib/atsc_field_sync_demux.cc b/gr-atsc/src/lib/atsc_field_sync_demux.cc new file mode 100644 index 00000000..d30947d5 --- /dev/null +++ b/gr-atsc/src/lib/atsc_field_sync_demux.cc @@ -0,0 +1,188 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::abs; + +static const int DEC = ATSC_DATA_SEGMENT_LENGTH; // nominal decimation factor + + +atsc_field_sync_demux_sptr +atsc_make_field_sync_demux() +{ + return atsc_field_sync_demux_sptr(new atsc_field_sync_demux()); +} + +atsc_field_sync_demux::atsc_field_sync_demux() + : gr_sync_decimator("atsc_field_sync_demux", + gr_make_io_signature(2, 2, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(atsc_soft_data_segment)),DEC), + d_locked(false), d_in_field2(true), d_segment_number(0), + d_next_input(0), d_lost_index(0) +{ + reset(); +} + +inline static bool +tag_is_seg_sync_or_field_sync (atsc::syminfo tag) +{ + return tag.symbol_num == 0 && tag.valid; +} + +void +atsc_field_sync_demux::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) { + ninput_items_required[i] = noutput_items * DEC + 2 * DEC - 1; + + inputs0_index = d_next_input; + inputs0_size = noutput_items * DEC + 2 * DEC - 1; + } +} + + +int +atsc_field_sync_demux::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + atsc::syminfo *input_tags = (atsc::syminfo *) input_items[1]; + atsc_soft_data_segment *out = (atsc_soft_data_segment *) output_items[0]; + + assert(sizeof(float) == sizeof(atsc::syminfo)); + + int ii = 0; // input index + + // Are we in sync? + if (!tag_is_seg_sync_or_field_sync (input_tags[0])){ // No ... + + if (d_locked){ + d_locked = false; + d_lost_index = inputs0_index + ii; + cerr << "atsc_field_sync_demux: lost sync at " + << d_lost_index << endl; + } + + // ... search for beginning of a field sync + + // cerr << "atsc_field_sync_demux: searching for sync at " + // << inputs0_index + ii << endl; + + for (ii = 1; ii < inputs0_size; ii++){ + if (atsc::tag_is_start_field_sync (input_tags[ii])){ + // found one + d_locked = true; + + const char *str; + if (atsc::tag_is_start_field_sync_1 (input_tags[ii])) + str = "FIELD-1"; + else if (atsc::tag_is_start_field_sync_2 (input_tags[ii])) + str = "FIELD-2"; + else + str = "SEGMENT"; + + cerr << "atsc_field_sync_demux: synced (" << str << ") at " + << inputs0_index + ii + << " [delta = " << inputs0_index + ii - d_lost_index + << "]\n"; + + d_next_input += ii; // update for forecast + return 0; // no work completed so far + } + } + // no non-NORMAL tag found + d_next_input += ii; // update for forecast + return 0; // no work completed so far + } + + // We are in sync. Produce output... + + int k = 0; // output index + + while (k < noutput_items){ + + if (inputs0_size - ii < ATSC_DATA_SEGMENT_LENGTH){ + // We're out of input data. + cerr << "atsc_field_sync_demux: ran out of input data\n"; + d_next_input += ii; // update for forecast + return k; // return amount of work completed so far + } + + if (!tag_is_seg_sync_or_field_sync (input_tags[ii])){ + // lost sync... + cerr << "atsc_field_sync_demux: lost sync at " + << inputs0_index + ii << endl; + + d_next_input += ii; // update for forecast + return k; // return amount of work completed so far + } + + if (atsc::tag_is_start_field_sync_1 (input_tags[ii])){ + d_in_field2 = false; + d_segment_number = 0; + ii += ATSC_DATA_SEGMENT_LENGTH; // skip over field sync + continue; + } + + if (atsc::tag_is_start_field_sync_2 (input_tags[ii])){ + d_in_field2 = true; + d_segment_number = 0; + ii += ATSC_DATA_SEGMENT_LENGTH; // skip over field sync + continue; + } + + if (d_segment_number >= ATSC_DSEGS_PER_FIELD){ + // something's wrong... + cerr << "atsc_field_sync_demux: segment number overflow\n"; + d_segment_number = 0; + } + + out[k].pli.set_regular_seg (d_in_field2, d_segment_number++); + for (int jj = 0; jj < ATSC_DATA_SEGMENT_LENGTH; jj++) + out[k].data[jj] = in[ii + jj]; + ii += ATSC_DATA_SEGMENT_LENGTH; + k++; + } + + d_next_input += ii; // update for forecast + return k; // return amount of work completed + +} + + + + diff --git a/gr-atsc/src/lib/atsc_field_sync_demux.h b/gr-atsc/src/lib/atsc_field_sync_demux.h new file mode 100644 index 00000000..7ce64b52 --- /dev/null +++ b/gr-atsc/src/lib/atsc_field_sync_demux.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_FIELD_SYNC_DEMUX_H +#define INCLUDED_ATSC_FIELD_SYNC_DEMUX_H + +#include +#include + +class atsc_field_sync_demux; +typedef boost::shared_ptr atsc_field_sync_demux_sptr; + +atsc_field_sync_demux_sptr atsc_make_field_sync_demux(); + +/*! + * \brief ATSC Field Sync Demux + * + * This class accepts 1 stream of floats (data), and 1 stream of tags (syminfo). * It outputs one stream of atsc_soft_data_segment packets + * \ingroup atsc + * + * input: atsc_data_segment; output: atsc_data_segment + */ +class atsc_field_sync_demux : public gr_sync_decimator +{ + friend atsc_field_sync_demux_sptr atsc_make_field_sync_demux(); + + atsc_field_sync_demux(); + +public: + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } + +protected: + bool d_locked; + bool d_in_field2; + int d_segment_number; + gr_uint64 d_next_input; + gr_uint64 d_lost_index; // diagnostic fluff + + unsigned long long inputs0_index; // for inputs[0].index + unsigned long inputs0_size; // for inputs[0].size + +}; + + +#endif /* INCLUDED_ATSC_FIELD_SYNC_DEMUX_H */ diff --git a/gr-atsc/src/lib/atsc_field_sync_mux.cc b/gr-atsc/src/lib/atsc_field_sync_mux.cc new file mode 100644 index 00000000..edaa2414 --- /dev/null +++ b/gr-atsc/src/lib/atsc_field_sync_mux.cc @@ -0,0 +1,203 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + + +atsc_field_sync_mux_sptr +atsc_make_field_sync_mux() +{ + return atsc_field_sync_mux_sptr(new atsc_field_sync_mux()); +} + +atsc_field_sync_mux::atsc_field_sync_mux() + : gr_sync_block("atsc_field_sync_mux", + gr_make_io_signature(1, 1, sizeof(atsc_data_segment)), + gr_make_io_signature(1, 1, sizeof(atsc_data_segment))) +{ + reset(); +} + +static const int NUMBER_OF_OUTPUTS = 1; // # of output streams (almost always one) + +static const int N_SAVED_SYMBOLS = atsc_field_sync_mux::N_SAVED_SYMBOLS; + +static void +init_field_sync_common (unsigned char *p, int mask, + const unsigned char saved_symbols[N_SAVED_SYMBOLS]) +{ + static const unsigned char bin_map[2] = { 1, 6 }; // map binary values to 1 of 8 levels + + int i = 0; + + p[i++] = bin_map[1]; // data segment sync pulse + p[i++] = bin_map[0]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + + for (int j = 0; j < 511; j++) // PN511 + p[i++] = bin_map[atsc_pn511[j]]; + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map[atsc_pn63[j]]; + + for (int j = 0; j < 63; j++) // PN63, toggled on field 2 + p[i++] = bin_map[atsc_pn63[j] ^ mask]; + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map[atsc_pn63[j]]; + + p[i++] = bin_map[0]; // 24 bits of VSB8 mode identifiera + p[i++] = bin_map[0]; + p[i++] = bin_map[0]; + p[i++] = bin_map[0]; + + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + + p[i++] = bin_map[1]; + p[i++] = bin_map[1]; + p[i++] = bin_map[1]; + p[i++] = bin_map[1]; + + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + p[i++] = bin_map[1]; + p[i++] = bin_map[0]; + + + for (int j = 0; j < 92; j++) // 92 more bits + p[i++] = bin_map[atsc_pn63[j % 63]]; + + // now copy the last 12 symbols of the previous segment + + for (int j = 0; j < N_SAVED_SYMBOLS; j++) + p[i++] = saved_symbols[j]; + + assert (i == ATSC_DATA_SEGMENT_LENGTH); +} +inline static void +init_field_sync_1 (atsc_data_segment *s, + const unsigned char saved_symbols[N_SAVED_SYMBOLS]) +{ + init_field_sync_common (&s->data[0], 0, saved_symbols); +} + +inline static void +init_field_sync_2 (atsc_data_segment *s, + const unsigned char saved_symbols[N_SAVED_SYMBOLS]) + +{ + init_field_sync_common (&s->data[0], 1, saved_symbols); +} + +static void +save_last_symbols (unsigned char saved_symbols[N_SAVED_SYMBOLS], + const atsc_data_segment &seg) +{ + for (int i = 0; i < N_SAVED_SYMBOLS; i++) + saved_symbols[i] = seg.data[i + ATSC_DATA_SEGMENT_LENGTH - N_SAVED_SYMBOLS];} + + +inline static bool +last_regular_seg_p (const plinfo &pli) +{ + return pli.regular_seg_p () && (pli.segno () == ATSC_DSEGS_PER_FIELD - 1); +} + +void +atsc_field_sync_mux::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items); + +} + + +int +atsc_field_sync_mux::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_data_segment *in = (const atsc_data_segment *) input_items[0]; + atsc_data_segment *out = (atsc_data_segment *) output_items[0]; + + unsigned int index = 0; + for (unsigned int outdex = 0; outdex < noutput_items; outdex++){ + + assert (in[index].pli.regular_seg_p ()); + + if (!in[index].pli.first_regular_seg_p ()){ + out[outdex] = in[index]; // just copy in to out + + if (last_regular_seg_p (in[index].pli)) + save_last_symbols (d_saved_symbols, in[index]); + + index++; + } + else { // first_regular_seg_p + if (!d_already_output_field_sync){ + // write out field sync... + atsc_data_segment field_sync; + + if (in[index].pli.in_field1_p ()) + init_field_sync_1 (&field_sync, d_saved_symbols); + else + init_field_sync_2 (&field_sync, d_saved_symbols); + + // note that index doesn't advance in this branch + out[outdex] = field_sync; + d_already_output_field_sync = true; + } + else { + // already output field sync, now output first regular segment + out[outdex] = in[index]; + index++; + d_already_output_field_sync = false; + } + } + } + + d_current_index += index; + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_field_sync_mux.h b/gr-atsc/src/lib/atsc_field_sync_mux.h new file mode 100644 index 00000000..91000e16 --- /dev/null +++ b/gr-atsc/src/lib/atsc_field_sync_mux.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_FIELD_SYNC_MUX_H +#define INCLUDED_ATSC_FIELD_SYNC_MUX_H + +#include +#include + +class atsc_field_sync_mux; +typedef boost::shared_ptr atsc_field_sync_mux_sptr; + +atsc_field_sync_mux_sptr atsc_make_field_sync_mux(); + +/*! + * \brief Insert ATSC Field Syncs as required (atsc_data_segment --> atsc_data_segment) + * \ingroup atsc + * + * input: atsc_data_segment; output: atsc_data_segment + */ +class atsc_field_sync_mux : public gr_sync_block +{ + friend atsc_field_sync_mux_sptr atsc_make_field_sync_mux(); + + atsc_field_sync_mux(); + +public: + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + + static const int N_SAVED_SYMBOLS = 12; + + void reset() { /* nop */ } + +protected: + gr_uint64 d_current_index; + bool d_already_output_field_sync; + unsigned char d_saved_symbols[N_SAVED_SYMBOLS]; +}; + + +#endif /* INCLUDED_ATSC_FIELD_SYNC_MUX_H */ diff --git a/gr-atsc/src/lib/atsc_fpll.cc b/gr-atsc/src/lib/atsc_fpll.cc new file mode 100644 index 00000000..087a8080 --- /dev/null +++ b/gr-atsc/src/lib/atsc_fpll.cc @@ -0,0 +1,136 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "fpll_btloop_coupling.h" + + +atsc_fpll_sptr +atsc_make_fpll() +{ + return atsc_fpll_sptr(new atsc_fpll()); +} + + +/* + * I strongly suggest that you not mess with these... + * + * They are strongly coupled into the symbol timing code and + * their value also sets the level of the symbols going + * into the equalizer and viterbi decoder. + */ +static const float FPLL_AGC_REFERENCE = 2.5 * FPLL_BTLOOP_COUPLING_CONST; +static const float FPLL_AGC_RATE = 0.25e-6; + + + +atsc_fpll::atsc_fpll() + : gr_sync_block("atsc_fpll", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + initial_phase(0) +{ + initial_freq = 5.75e6 - 3e6 + 0.31e6 + 5e3; // a_initial_freq; + agc.set_rate (FPLL_AGC_RATE); + agc.set_reference (FPLL_AGC_REFERENCE); + initialize(); +} + + +void +atsc_fpll::initialize () +{ + float Fs = 20e6; + + float alpha = 1 - exp(-1.0 / Fs / 5e-6); + + afci.set_taps (alpha); + afcq.set_taps (alpha); + + printf("Setting initial_freq: %f\n",initial_freq); + nco.set_freq (initial_freq / Fs * 2 * M_PI); + nco.set_phase (initial_phase); +} + + +int +atsc_fpll::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int k = 0; k < noutput_items; k++){ + + float a_cos, a_sin; + + float input = agc.scale (in[k]); + + nco.step (); // increment phase + nco.sincos (&a_sin, &a_cos); // compute cos and sin + + float I = input * a_sin; + float Q = input * a_cos; + + out[k] = I; + + float filtered_I = afci.filter (I); + float filtered_Q = afcq.filter (Q); + + // phase detector + + float x = atan2 (filtered_Q, filtered_I); + + // avoid slamming filter with big transitions + + static const float limit = M_PI / 2; + + if (x > limit) + x = limit; + else if (x < -limit) + x = -limit; + + // static const float alpha = 0.037; // Max value + // static const float alpha = 0.005; // takes about 5k samples to pull in, stddev = 323 + // static const float alpha = 0.002; // takes about 15k samples to pull in, stddev = 69 + // or about 120k samples on noisy data, + static const float alpha = 0.001; + static const float beta = alpha * alpha / 4; + + nco.adjust_phase (alpha * x); + nco.adjust_freq (beta * x); + + } + + return noutput_items; +} + + + diff --git a/gr-atsc/src/lib/atsc_fpll.h b/gr-atsc/src/lib/atsc_fpll.h new file mode 100644 index 00000000..b6213bac --- /dev/null +++ b/gr-atsc/src/lib/atsc_fpll.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_FPLL_H +#define INCLUDED_ATSC_FPLL_H + +#include +#include +#include +#include +#include +#include + +class atsc_fpll; +typedef boost::shared_ptr atsc_fpll_sptr; + +atsc_fpll_sptr atsc_make_fpll(); + +/*! + * \brief ATSC FPLL (2nd Version) + * \ingroup atsc + * + * A/D --> GrFIRfilterFFF ----> GrAtscFPLL ----> + * + * We use GrFIRfilterFFF to bandpass filter the signal of interest. + * + * This class accepts a single real input and produces a single real output + */ + +class atsc_fpll : public gr_sync_block +{ + friend atsc_fpll_sptr atsc_make_fpll(); + + atsc_fpll(); + +public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } + + void initialize () ; + + protected: + + double initial_freq; + double initial_phase; + bool debug_no_update; + gr_nco nco; + gri_agc agc; // automatic gain control + gr_single_pole_iir afci; + gr_single_pole_iir afcq; + + +}; + + +#endif /* INCLUDED_ATSC_FPLL_H */ diff --git a/gr-atsc/src/lib/atsc_fs_checker.cc b/gr-atsc/src/lib/atsc_fs_checker.cc new file mode 100644 index 00000000..10d8353e --- /dev/null +++ b/gr-atsc/src/lib/atsc_fs_checker.cc @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + + +atsc_fs_checker_sptr +atsc_make_fs_checker() +{ + return atsc_fs_checker_sptr(new atsc_fs_checker()); +} + +atsc_fs_checker::atsc_fs_checker() + : gr_sync_block("atsc_fs_checker", + gr_make_io_signature(2, 2, sizeof(float)), + gr_make_io_signature(2, 2, sizeof(float))) +{ + d_fsc = create_atsci_fs_checker(); +} + + +atsc_fs_checker::~atsc_fs_checker () +{ + // Anything that isn't automatically cleaned up... + + delete d_fsc; +} + + +int +atsc_fs_checker::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]; + const atsc::syminfo *tag_in = (const atsc::syminfo *) input_items[1]; + float *out = (float *) output_items[0]; + atsc::syminfo *tag_out = (atsc::syminfo *) output_items[1]; + + assert(sizeof(float) == sizeof(atsc::syminfo)); + + + for (int i = 0; i < noutput_items; i++) + d_fsc->filter (in[i], tag_in[i], &out[i], &tag_out[i]); + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_fs_checker.h b/gr-atsc/src/lib/atsc_fs_checker.h new file mode 100644 index 00000000..a844cd3b --- /dev/null +++ b/gr-atsc/src/lib/atsc_fs_checker.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_FS_CHECKER_H +#define INCLUDED_ATSC_FS_CHECKER_H + +#include +#include + +class atsc_fs_checker; +typedef boost::shared_ptr atsc_fs_checker_sptr; + +atsc_fs_checker_sptr atsc_make_fs_checker(); + +/*! + * \brief ATSC field sync checker (float,syminfo --> float,syminfo) + * \ingroup atsc + * + * first output is delayed version of input. + * second output is set of tags, one-for-one with first output. + */ + +class atsc_fs_checker : public gr_sync_block +{ + friend atsc_fs_checker_sptr atsc_make_fs_checker(); + + atsc_fs_checker(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } + + ~atsc_fs_checker (); + +protected: + atsci_fs_checker *d_fsc; + +}; + + +#endif /* INCLUDED_ATSC_FS_CHECKER_H */ diff --git a/gr-atsc/src/lib/atsc_interleaver.cc b/gr-atsc/src/lib/atsc_interleaver.cc new file mode 100644 index 00000000..567c1b46 --- /dev/null +++ b/gr-atsc/src/lib/atsc_interleaver.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_interleaver_sptr +atsc_make_interleaver() +{ + return atsc_interleaver_sptr(new atsc_interleaver()); +} + +atsc_interleaver::atsc_interleaver() + : gr_sync_block("atsc_interleaver", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded))) +{ + reset(); +} + +int +atsc_interleaver::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet_rs_encoded *in = (const atsc_mpeg_packet_rs_encoded *) input_items[0]; + atsc_mpeg_packet_rs_encoded *out = (atsc_mpeg_packet_rs_encoded *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + d_interleaver.interleave (out[i], in[i]); + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_interleaver.h b/gr-atsc/src/lib/atsc_interleaver.h new file mode 100644 index 00000000..18fd8e54 --- /dev/null +++ b/gr-atsc/src/lib/atsc_interleaver.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_INTERLEAVER_H +#define INCLUDED_ATSC_INTERLEAVER_H + +#include +#include + +class atsc_interleaver; +typedef boost::shared_ptr atsc_interleaver_sptr; + +atsc_interleaver_sptr atsc_make_interleaver(); + +/*! \brief Interleave RS encoded ATSC data ( atsc_mpeg_packet_rs_encoded --> atsc_mpeg_packet_rs_encoded)* + * \ingroup atsc + * + * input: atsc_mpeg_packet_rs_encoded; output: atsc_mpeg_packet_rs_encoded + */ +class atsc_interleaver : public gr_sync_block +{ + friend atsc_interleaver_sptr atsc_make_interleaver(); + + atsci_data_interleaver d_interleaver; + + atsc_interleaver(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_INTERLEAVER_H */ diff --git a/gr-atsc/src/lib/atsc_randomizer.cc b/gr-atsc/src/lib/atsc_randomizer.cc new file mode 100644 index 00000000..7b9fed0e --- /dev/null +++ b/gr-atsc/src/lib/atsc_randomizer.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_randomizer_sptr +atsc_make_randomizer() +{ + return atsc_randomizer_sptr(new atsc_randomizer()); +} + +atsc_randomizer::atsc_randomizer() + : gr_sync_block("atsc_randomizer", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_no_sync))) +{ + reset(); +} + +void +atsc_randomizer::reset() +{ + d_rand.reset(); + d_field2 = false; + d_segno = 0; +} + +int +atsc_randomizer::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet *in = (const atsc_mpeg_packet *) input_items[0]; + atsc_mpeg_packet_no_sync *out = (atsc_mpeg_packet_no_sync *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + + // sanity check incoming data. + assert((in[i].data[0] == MPEG_SYNC_BYTE)); + assert((in[i].data[1] & MPEG_TRANSPORT_ERROR_BIT) == 0); + + // initialize plinfo for downstream + // + // We do this here because the randomizer is effectively + // the head of the tx processing chain + // + out[i].pli.set_regular_seg(d_field2, d_segno); + d_segno++; + if (d_segno == 312){ + d_segno = 0; + d_field2 = !d_field2; + } + + if (out[i].pli.first_regular_seg_p()) + d_rand.reset(); + + d_rand.randomize(out[i], in[i]); + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_randomizer.h b/gr-atsc/src/lib/atsc_randomizer.h new file mode 100644 index 00000000..31f20c83 --- /dev/null +++ b/gr-atsc/src/lib/atsc_randomizer.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_RANDOMIZER_H +#define INCLUDED_ATSC_RANDOMIZER_H + +#include +#include + +class atsc_randomizer; +typedef boost::shared_ptr atsc_randomizer_sptr; + +atsc_randomizer_sptr atsc_make_randomizer(); + +/*! + * \brief "Whiten" incoming mpeg transport stream packets + * \ingroup atsc + * + * input: atsc_mpeg_packet; output: atsc_mpeg_packet_no_sync + */ +class atsc_randomizer : public gr_sync_block +{ + friend atsc_randomizer_sptr atsc_make_randomizer(); + + atsci_randomizer d_rand; + bool d_field2; // user to init plinfo in output + int d_segno; // likewise + + atsc_randomizer(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset(); +}; + + +#endif /* INCLUDED_ATSC_RANDOMIZER_H */ diff --git a/gr-atsc/src/lib/atsc_rs_decoder.cc b/gr-atsc/src/lib/atsc_rs_decoder.cc new file mode 100644 index 00000000..7885cca4 --- /dev/null +++ b/gr-atsc/src/lib/atsc_rs_decoder.cc @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_rs_decoder_sptr +atsc_make_rs_decoder() +{ + return atsc_rs_decoder_sptr(new atsc_rs_decoder()); +} + +atsc_rs_decoder::atsc_rs_decoder() + : gr_sync_block("atsc_rs_decoder", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_no_sync))) +{ + reset(); +} + +int +atsc_rs_decoder::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet_rs_encoded *in = (const atsc_mpeg_packet_rs_encoded *) input_items[0]; + atsc_mpeg_packet_no_sync *out = (atsc_mpeg_packet_no_sync *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + assert(in[i].pli.regular_seg_p()); + out[i].pli = in[i].pli; // copy pipeline info... + + int nerrors_corrrected = d_rs_decoder.decode(out[i], in[i]); + out[i].pli.set_transport_error(nerrors_corrrected == -1); + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_rs_decoder.h b/gr-atsc/src/lib/atsc_rs_decoder.h new file mode 100644 index 00000000..7c10a3db --- /dev/null +++ b/gr-atsc/src/lib/atsc_rs_decoder.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_RS_DECODER_H +#define INCLUDED_ATSC_RS_DECODER_H + +#include +#include + +class atsc_rs_decoder; +typedef boost::shared_ptr atsc_rs_decoder_sptr; + +atsc_rs_decoder_sptr atsc_make_rs_decoder(); + +/*! + * \brief Reed-Solomon decoder for ATSC + * \ingroup atsc + * + * input: atsc_mpeg_packet_rs_encoded; output: atsc_mpeg_packet_no_sync + */ +class atsc_rs_decoder : public gr_sync_block +{ + friend atsc_rs_decoder_sptr atsc_make_rs_decoder(); + + atsci_reed_solomon d_rs_decoder; + + atsc_rs_decoder(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_RS_DECODER_H */ diff --git a/gr-atsc/src/lib/atsc_rs_encoder.cc b/gr-atsc/src/lib/atsc_rs_encoder.cc new file mode 100644 index 00000000..53f45d59 --- /dev/null +++ b/gr-atsc/src/lib/atsc_rs_encoder.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_rs_encoder_sptr +atsc_make_rs_encoder() +{ + return atsc_rs_encoder_sptr(new atsc_rs_encoder()); +} + +atsc_rs_encoder::atsc_rs_encoder() + : gr_sync_block("atsc_rs_encoder", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_no_sync)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded))) +{ + reset(); +} + +int +atsc_rs_encoder::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet_no_sync *in = (const atsc_mpeg_packet_no_sync *) input_items[0]; + atsc_mpeg_packet_rs_encoded *out = (atsc_mpeg_packet_rs_encoded *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + + assert(in[i].pli.regular_seg_p()); + out[i].pli = in[i].pli; // copy pipeline info... + d_rs_encoder.encode(out[i], in[i]); + } + + return noutput_items; +} diff --git a/gr-atsc/src/lib/atsc_rs_encoder.h b/gr-atsc/src/lib/atsc_rs_encoder.h new file mode 100644 index 00000000..da1fd63e --- /dev/null +++ b/gr-atsc/src/lib/atsc_rs_encoder.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_RS_ENCODER_H +#define INCLUDED_ATSC_RS_ENCODER_H + +#include +#include + +class atsc_rs_encoder; +typedef boost::shared_ptr atsc_rs_encoder_sptr; + +atsc_rs_encoder_sptr atsc_make_rs_encoder(); + +/*! + * \brief Reed-Solomon encoder for ATSC + * \ingroup atsc + * + * input: atsc_mpeg_packet_no_sync; output: atsc_mpeg_packet_rs_encoded + */ +class atsc_rs_encoder : public gr_sync_block +{ + friend atsc_rs_encoder_sptr atsc_make_rs_encoder(); + + atsci_reed_solomon d_rs_encoder; + + atsc_rs_encoder(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_RS_ENCODER_H */ diff --git a/gr-atsc/src/lib/atsc_trellis_encoder.cc b/gr-atsc/src/lib/atsc_trellis_encoder.cc new file mode 100644 index 00000000..77cf08af --- /dev/null +++ b/gr-atsc/src/lib/atsc_trellis_encoder.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + + +atsc_trellis_encoder_sptr +atsc_make_trellis_encoder() +{ + return atsc_trellis_encoder_sptr(new atsc_trellis_encoder()); +} + +atsc_trellis_encoder::atsc_trellis_encoder() + : gr_sync_block("atsc_trellis_encoder", + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded)), + gr_make_io_signature(1, 1, sizeof(atsc_data_segment))) +{ + set_output_multiple(atsci_trellis_encoder::NCODERS); + reset(); +} + +int +atsc_trellis_encoder::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_mpeg_packet_rs_encoded *in = (const atsc_mpeg_packet_rs_encoded *) input_items[0]; + atsc_data_segment *out = (atsc_data_segment *) output_items[0]; + + for (int i = 0; i < atsci_trellis_encoder::NCODERS; i += atsci_trellis_encoder::NCODERS){ + d_trellis_encoder.encode(&out[i], &in[i]); + } + return atsci_trellis_encoder::NCODERS; +} + diff --git a/gr-atsc/src/lib/atsc_trellis_encoder.h b/gr-atsc/src/lib/atsc_trellis_encoder.h new file mode 100644 index 00000000..98b549ef --- /dev/null +++ b/gr-atsc/src/lib/atsc_trellis_encoder.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_TRELLIS_ENCODER_H +#define INCLUDED_ATSC_TRELLIS_ENCODER_H + +#include +#include + +class atsc_trellis_encoder; +typedef boost::shared_ptr atsc_trellis_encoder_sptr; + +atsc_trellis_encoder_sptr atsc_make_trellis_encoder(); + +/*! + * \brief ATSC 12-way interleaved trellis encoder (atsc_mpeg_packet_rs_encoded --> atsc_data_segment) + * \ingroup atsc + * + * input: atsc_mpeg_packet_rs_encoded; output: atsc_data_segment + */ +class atsc_trellis_encoder : public gr_sync_block +{ + friend atsc_trellis_encoder_sptr atsc_make_trellis_encoder(); + + atsci_trellis_encoder d_trellis_encoder; + + atsc_trellis_encoder(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } +}; + + +#endif /* INCLUDED_ATSC_TRELLIS_ENCODER_H */ diff --git a/gr-atsc/src/lib/atsc_types.h b/gr-atsc/src/lib/atsc_types.h new file mode 100644 index 00000000..1a7708ec --- /dev/null +++ b/gr-atsc/src/lib/atsc_types.h @@ -0,0 +1,238 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_TYPES_H_ +#define _ATSC_TYPES_H_ + +#include +#include +#include + + +/*! + * \brief pipeline info that flows with data + * + * Not all modules need all the info + */ +class plinfo { +public: + plinfo () : _flags (0), _segno (0) { } + + // accessors + + bool field_sync1_p () const { return (_flags & fl_field_sync1) != 0; } + bool field_sync2_p () const { return (_flags & fl_field_sync2) != 0; } + bool field_sync_p () const { return field_sync1_p () || field_sync2_p (); } + + bool regular_seg_p () const { return (_flags & fl_regular_seg) != 0; } + + bool in_field1_p () const { return (_flags & fl_field2) == 0; } + bool in_field2_p () const { return (_flags & fl_field2) != 0; } + + bool first_regular_seg_p () const { return (_flags & fl_first_regular_seg) != 0; } + + bool transport_error_p () const { return (_flags & fl_transport_error) != 0; } + + unsigned int segno () const { return _segno; } + unsigned int flags () const { return _flags; } + + // setters + + void set_field_sync1 () + { + _segno = 0; + _flags = fl_field_sync1; + } + + void set_field_sync2 () + { + _segno = 0; + _flags = fl_field_sync2 | fl_field2; + } + + void set_regular_seg (bool field2, int segno) + { + assert (0 <= segno && segno < ATSC_DSEGS_PER_FIELD); + _segno = segno; + _flags = fl_regular_seg; + if (segno == 0) + _flags |= fl_first_regular_seg; + if (segno >= ATSC_DSEGS_PER_FIELD) + _flags |= fl_transport_error; + if (field2) + _flags |= fl_field2; + } + + void set_transport_error (bool error){ + if (error) + _flags |= fl_transport_error; + else + _flags &= ~fl_transport_error; + } + + // overload equality operator + bool operator== (const plinfo &other) const { + return (_flags == other._flags && _segno == other._segno); + } + + bool operator!= (const plinfo &other) const { + return !(_flags == other._flags && _segno == other._segno); + } + + /*! + * Set \p OUT such that it reflects a \p NSEGS_OF_DELAY + * pipeline delay from \p IN. + */ + static void delay (plinfo &out, const plinfo &in, int nsegs_of_delay); + + /*! + * confirm that \p X is plausible + */ + static void sanity_check (const plinfo &in); + + +protected: + unsigned short _flags; // bitmask + unsigned short _segno; // segment number [0,311] + + // these three are mutually exclusive + // This is a regular data segment. + static const int fl_regular_seg = 0x0001; + // This is a field sync segment, for 1st half of a field. + static const int fl_field_sync1 = 0x0002; + // This is a field sync segment, for 2nd half of a field. + static const int fl_field_sync2 = 0x0004; + + // This bit is on ONLY when fl_regular_seg is set AND when this is + // the first regular data segment AFTER a field sync segment. This + // segment causes various processing modules to reset. + static const int fl_first_regular_seg = 0x0008; + + // which field are we in? + static const int fl_field2 = 0x0010; // else field 1 + + // This bit is set when Reed-Solomon decoding detects an error that it + // can't correct. Note that other error detection (e.g. Viterbi) do not + // set it, since Reed-Solomon will correct many of those. This bit is + // then copied into the final Transport Stream packet so that MPEG + // software can see that the 188-byte data segment has been corrupted. + static const int fl_transport_error = 0x0020; +}; + + + + +class atsc_mpeg_packet { + public: + static const int NPAD = 68; + unsigned char data[ATSC_MPEG_DATA_LENGTH + 1]; // first byte is sync + unsigned char _pad_[NPAD]; // pad to power of 2 (256) + + // overload equality operator + bool operator== (const atsc_mpeg_packet &other) const { + return std::memcmp (data, other.data, sizeof (data)) == 0; + }; + + bool operator!= (const atsc_mpeg_packet &other) const { + return !(std::memcmp (data, other.data, sizeof (data)) == 0); + }; +}; + +class atsc_mpeg_packet_no_sync { + public: + static const int NPAD = 65; + plinfo pli; + unsigned char data[ATSC_MPEG_DATA_LENGTH]; + unsigned char _pad_[NPAD]; // pad to power of 2 (256) + + // overload equality operator + bool operator== (const atsc_mpeg_packet_no_sync &other) const { + return std::memcmp (data, other.data, sizeof (data)) == 0; + } + + bool operator!= (const atsc_mpeg_packet_no_sync &other) const { + return !(std::memcmp (data, other.data, sizeof (data)) == 0); + } +}; + +class atsc_mpeg_packet_rs_encoded { + public: + static const int NPAD = 45; + plinfo pli; + unsigned char data[ATSC_MPEG_RS_ENCODED_LENGTH]; + unsigned char _pad_[NPAD]; // pad to power of 2 (256) + + // overload equality operator + bool operator== (const atsc_mpeg_packet_rs_encoded &other) const { + return std::memcmp (data, other.data, sizeof (data)) == 0; + } + + bool operator!= (const atsc_mpeg_packet_rs_encoded &other) const { + return !(std::memcmp (data, other.data, sizeof (data)) == 0); + } +}; + + +//! contains 832 3 bit symbols. The low 3 bits in the byte hold the symbol. + +class atsc_data_segment { + public: + static const int NPAD = 188; + plinfo pli; + unsigned char data[ATSC_DATA_SEGMENT_LENGTH]; + unsigned char _pad_[NPAD]; // pad to power of 2 (1024) + + // overload equality operator + bool operator== (const atsc_data_segment &other) const { + return std::memcmp (data, other.data, sizeof (data)) == 0; + } + + bool operator!= (const atsc_data_segment &other) const { + return !(std::memcmp (data, other.data, sizeof (data)) == 0); + } +}; + +/*! + * Contains 832 bipolar floating point symbols. + * Nominal values are +/- {1, 3, 5, 7}. + * This data type represents the input to the viterbi decoder. + */ + +class atsc_soft_data_segment { + public: + static const int NPAD = 764; + plinfo pli; + float data[ATSC_DATA_SEGMENT_LENGTH]; + unsigned char _pad_[NPAD]; // pad to power of 2 (4096) + + // overload equality operator + bool operator== (const atsc_data_segment &other) const { + return std::memcmp (data, other.data, sizeof (data)) == 0; + } + + bool operator!= (const atsc_data_segment &other) const { + return !(std::memcmp (data, other.data, sizeof (data)) == 0); + } +}; + + +#endif /* _ATSC_TYPES_H_ */ diff --git a/gr-atsc/src/lib/atsc_viterbi_decoder.cc b/gr-atsc/src/lib/atsc_viterbi_decoder.cc new file mode 100644 index 00000000..394ee503 --- /dev/null +++ b/gr-atsc/src/lib/atsc_viterbi_decoder.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + + +atsc_viterbi_decoder_sptr +atsc_make_viterbi_decoder() +{ + return atsc_viterbi_decoder_sptr(new atsc_viterbi_decoder()); +} + +atsc_viterbi_decoder::atsc_viterbi_decoder() + : gr_sync_block("atsc_viterbi_decoder", + gr_make_io_signature(1, 1, sizeof(atsc_soft_data_segment)), + gr_make_io_signature(1, 1, sizeof(atsc_mpeg_packet_rs_encoded))), + last_start(-1) +{ + set_output_multiple(atsci_viterbi_decoder::NCODERS); + reset(); +} + +int +atsc_viterbi_decoder::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const atsc_soft_data_segment *in = (const atsc_soft_data_segment *) input_items[0]; + atsc_mpeg_packet_rs_encoded *out = (atsc_mpeg_packet_rs_encoded *) output_items[0]; + + assert (noutput_items % atsci_viterbi_decoder::NCODERS == 0); + + // find the first mod 12 boundary to begin decoding + int start; + for (start = 0; start < atsci_viterbi_decoder::NCODERS; start++){ + assert (in[start].pli.regular_seg_p ()); + if ((in[start].pli.segno () % atsci_viterbi_decoder::NCODERS) == 0) + break; + } + + if (start == atsci_viterbi_decoder::NCODERS){ + // we didn't find a mod 12 boundary. There's some kind of problem + // upstream of us (not yet sync'd??) + cerr << "!!!atsc_viterbi_decoder: no mod-12 boundary found\7\n"; + start = 0; + } + else if (start != last_start){ + cerr << "atsc_viterbi_decoder: new starting offset = " << start + << endl; + last_start = start; + } + + for (int i = 0; i < atsci_viterbi_decoder::NCODERS; i += atsci_viterbi_decoder::NCODERS){ + d_viterbi_decoder.decode(&out[i], &in[i + start]); + } + return atsci_viterbi_decoder::NCODERS; +} + diff --git a/gr-atsc/src/lib/atsc_viterbi_decoder.h b/gr-atsc/src/lib/atsc_viterbi_decoder.h new file mode 100644 index 00000000..931397ed --- /dev/null +++ b/gr-atsc/src/lib/atsc_viterbi_decoder.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_ATSC_VITERBI_DECODER_H +#define INCLUDED_ATSC_VITERBI_DECODER_H + +#include +#include + +class atsc_viterbi_decoder; +typedef boost::shared_ptr atsc_viterbi_decoder_sptr; + +atsc_viterbi_decoder_sptr atsc_make_viterbi_decoder(); + +/*! + * \brief ATSC 12-way interleaved viterbi decoder (atsc_soft_data_segment --> atsc_mpeg_packet_rs_encoded) + * \ingroup atsc + * + * input: atsc_soft_data_segment; output: atsc_mpeg_packet_rs_encoded + */ +class atsc_viterbi_decoder : public gr_sync_block +{ + friend atsc_viterbi_decoder_sptr atsc_make_viterbi_decoder(); + + atsci_viterbi_decoder d_viterbi_decoder; + + atsc_viterbi_decoder(); + +public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { /* nop */ } + +protected: + int last_start; + +}; + + +#endif /* INCLUDED_ATSC_VITERBI_DECODER_H */ diff --git a/gr-atsc/src/lib/atsci_basic_trellis_encoder.cc b/gr-atsc/src/lib/atsci_basic_trellis_encoder.cc new file mode 100644 index 00000000..35081eb8 --- /dev/null +++ b/gr-atsc/src/lib/atsci_basic_trellis_encoder.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +const unsigned char atsci_basic_trellis_encoder::next_state[32] = { + 0,1,4,5, + 2,3,6,7, + 1,0,5,4, + 3,2,7,6, + 4,5,0,1, + 6,7,2,3, + 5,4,1,0, + 7,6,3,2 +}; + +const unsigned char atsci_basic_trellis_encoder::out_symbol[32] = { + 0,2,4,6, + 1,3,5,7, + 0,2,4,6, + 1,3,5,7, + 4,6,0,2, + 5,7,1,3, + 4,6,0,2, + 5,7,1,3 +}; + + +/*! + * Encode two bit INPUT into 3 bit return value. Domain is [0,3], + * Range is [0,7]. The mapping to bipolar levels is not done. + */ + +int +atsci_basic_trellis_encoder::encode (unsigned int input) +{ + assert (input < 4); + int index = (state << 2) + input; + state = next_state[index]; + return out_symbol[index]; +} + diff --git a/gr-atsc/src/lib/atsci_basic_trellis_encoder.h b/gr-atsc/src/lib/atsci_basic_trellis_encoder.h new file mode 100644 index 00000000..34c45e47 --- /dev/null +++ b/gr-atsc/src/lib/atsci_basic_trellis_encoder.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_BASIC_TRELLIS_ENCODER_H_ +#define _ATSC_BASIC_TRELLIS_ENCODER_H_ + +#include + +/*! + * \brief ATSC trellis encoder building block. + * + * Note this is NOT the 12x interleaved interface. + * + * This implements a single instance of the ATSC trellis encoder. + * This is a rate 2/3 encoder (really a constraint length 3, rate 1/2 + * encoder with the top bit passed through unencoded. This does not + * implement the "precoding" of the top bit, because the NTSC rejection + * filter is not supported. + */ + +class atsci_basic_trellis_encoder { + +private: + int state; // two bit state; + +public: + atsci_basic_trellis_encoder () : state (0) {} + + /*! + * Encode two bit INPUT into 3 bit return value. Domain is [0,3], + * Range is [0,7]. The mapping to bipolar levels is not done. + */ + int encode (unsigned int input); + + //! reset encoder state + void reset () { state = 0; } + + static const unsigned char next_state[32]; + static const unsigned char out_symbol[32]; +}; + +#endif /* _ATSC_BASIC_TRELLIS_ENCODER_H_ */ diff --git a/gr-atsc/src/lib/atsci_data_interleaver.cc b/gr-atsc/src/lib/atsci_data_interleaver.cc new file mode 100644 index 00000000..4826df79 --- /dev/null +++ b/gr-atsc/src/lib/atsci_data_interleaver.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +void +atsci_data_interleaver::interleave (atsc_mpeg_packet_rs_encoded &out, + const atsc_mpeg_packet_rs_encoded &in) +{ + assert (in.pli.regular_seg_p ()); + plinfo::sanity_check (in.pli); + + out.pli = in.pli; // copy pipeline info + if (in.pli.first_regular_seg_p ()) // reset commutator if required + sync (); + + transform (out.data, in.data, sizeof (in.data)); +} + + +void +atsci_data_deinterleaver::deinterleave (atsc_mpeg_packet_rs_encoded &out, + const atsc_mpeg_packet_rs_encoded &in) +{ + assert (in.pli.regular_seg_p ()); + plinfo::sanity_check (in.pli); + + // reset commutator if required using INPUT pipeline info + if (in.pli.first_regular_seg_p ()) + sync (); + + // remap OUTPUT pipeline info to reflect 52 data segment end-to-end delay + + plinfo::delay (out.pli, in.pli, 52); + + // now do the actual deinterleaving + + for (unsigned int i = 0; i < sizeof (in.data); i++){ + out.data[i] = alignment_fifo.stuff (transform (in.data[i])); + } +} + diff --git a/gr-atsc/src/lib/atsci_data_interleaver.h b/gr-atsc/src/lib/atsci_data_interleaver.h new file mode 100644 index 00000000..26286b5b --- /dev/null +++ b/gr-atsc/src/lib/atsci_data_interleaver.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_DATA_INTERLEAVER_H_ +#define _ATSC_DATA_INTERLEAVER_H_ + +#include +#include + +/*! + * \brief atsc convolutional data interleaver + */ +class atsci_data_interleaver : public convolutional_interleaver { + public: + atsci_data_interleaver () : convolutional_interleaver(true, 52, 4) {} + + void interleave (atsc_mpeg_packet_rs_encoded &out, + const atsc_mpeg_packet_rs_encoded &in); +}; + +/*! + * \brief atsc convolutional data deinterleaver + */ +class atsci_data_deinterleaver : public convolutional_interleaver { + public: + atsci_data_deinterleaver () : + convolutional_interleaver(false, 52, 4), alignment_fifo (156) {} + + void deinterleave (atsc_mpeg_packet_rs_encoded &out, + const atsc_mpeg_packet_rs_encoded &in); + +private: + /*! + * Note: The use of the alignment_fifo keeps the encoder and decoder + * aligned if both are synced to a field boundary. There may be other + * ways to implement this function. This is a best guess as to how + * this should behave, as we have no test vectors for either the + * interleaver or deinterleaver. + */ + interleaver_fifo alignment_fifo; + + static void remap_pli (plinfo &out, const plinfo &in); +}; + +#endif /* _ATSC_DATA_INTERLEAVER_H_ */ diff --git a/gr-atsc/src/lib/atsci_diag_output.h b/gr-atsc/src/lib/atsci_diag_output.h new file mode 100644 index 00000000..163a6f0a --- /dev/null +++ b/gr-atsc/src/lib/atsci_diag_output.h @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * single place to control all compile time diagnostic output options + */ + +#define _BT_DIAG_OUTPUT_ 0 +#define _FPLL_DIAG_OUTPUT_ 0 +#define _SSSR_DIAG_OUTPUT_ 0 diff --git a/gr-atsc/src/lib/atsci_equalizer.cc b/gr-atsc/src/lib/atsci_equalizer.cc new file mode 100644 index 00000000..29c248cf --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer.cc @@ -0,0 +1,248 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +using std::cerr; +using std::endl; +using std::min; + + +// total number of symbols (including field sync) / field +static const int SYMBOLS_PER_FIELD = + (ATSC_DSEGS_PER_FIELD + 1) * ATSC_DATA_SEGMENT_LENGTH; + + +atsci_equalizer::atsci_equalizer () +{ + d_locked_p = false; + d_offset_from_last_field_sync = 0; + d_current_field = 0; +} + +atsci_equalizer::~atsci_equalizer () +{ +} + +void +atsci_equalizer::reset () +{ + d_locked_p = false; + d_offset_from_last_field_sync = 0; + d_current_field = 0; +} + +/* + * Errrr.... Define to 1 if compiler handles tail recursion without pushing + * unnecessary stack frames, else define to 0 for lame compilers. + */ +#define WINNING_COMPILER 0 + + +/* + * divide and conquer... + * + * Note that this could be refactored to take advantage of the + * symbol_num that is contained in the input_tags. Then we wouldn't + * have to be counting here. + * + * Today's strategy: get it working. + */ + +void +atsci_equalizer::filter (const float *input_samples, + const atsc::syminfo *input_tags, + float *output_samples, + int nsamples) +{ + lame_compiler_kludge: + + if (!d_locked_p){ + + // look for a field sync + + int i; + for (i = 0; i < nsamples; i++){ + if (atsc::tag_is_start_field_sync (input_tags[i])) + break; + } + + // whether we found one or not, everything up to it should + // be run through the normal path + + if (i != 0) + filter_normal (input_samples, output_samples, i); + + if (i == nsamples) // no field sync found, still not locked. + return; + + // OK, we've just transitioned to the locked state. + + d_locked_p = true; + d_offset_from_last_field_sync = 0; + + // handle locked case recursively + + if (WINNING_COMPILER) + filter (&input_samples[i], &input_tags[i], + &output_samples[i], nsamples - i); + else { + input_samples += i; + input_tags += i; + output_samples += i; + nsamples -= i; + goto lame_compiler_kludge; + } + + return; + } + + // We're in the locked state. + // + // Figure out where we are with respect to a data segment boundary + // and do the right thing. Note that in the interested of performance, + // we don't scan all the tags looking for trouble. We only check + // them where we expect them to be non-NORMAL. Worst case, it'll take + // us a field to notice that something went wrong... + + if (d_offset_from_last_field_sync % SYMBOLS_PER_FIELD == 0){ // we should be looking + // at a field sync + if (atsc::tag_is_start_field_sync_1 (input_tags[0])) + d_current_field = 0; + + else if (atsc::tag_is_start_field_sync_2 (input_tags[0])) + d_current_field = 1; + + else { // we're lost... no field sync where we expected it + + cerr << "!!! atsci_equalizer: expected field sync, didn't find one\n"; + + d_locked_p = false; + d_offset_from_last_field_sync = 0; + + if (WINNING_COMPILER) + filter (input_samples, input_tags, output_samples, nsamples); + else + goto lame_compiler_kludge; + + return; + } + + // OK, everything's cool. We're looking at a field sync. + + int n = min (ATSC_DATA_SEGMENT_LENGTH, nsamples); + + filter_field_sync (input_samples, output_samples, n, 0, d_current_field); + + d_offset_from_last_field_sync = n; + nsamples -= n; + + if (nsamples > 0){ + if (WINNING_COMPILER) + filter (&input_samples[n], &input_tags[n], + &output_samples[n], nsamples); + else { + input_samples += n; + input_tags += n; + output_samples += n; + goto lame_compiler_kludge; + } + } + return; + } + + if (d_offset_from_last_field_sync < ATSC_DATA_SEGMENT_LENGTH){ // we're in the middle of a field sync + int n = min (ATSC_DATA_SEGMENT_LENGTH - d_offset_from_last_field_sync, nsamples); + + filter_field_sync (input_samples, output_samples, n, + d_offset_from_last_field_sync, d_current_field); + + d_offset_from_last_field_sync += n; + nsamples -= n; + + if (nsamples > 0){ + if (WINNING_COMPILER) + filter (&input_samples[n], &input_tags[n], + &output_samples[n], nsamples); + else { + input_samples += n; + input_tags += n; + output_samples += n; + goto lame_compiler_kludge; + } + } + return; + } + + // OK, we're not in a field sync. We're either in a data segment sync or in the clear... + + int seg_offset = d_offset_from_last_field_sync % ATSC_DATA_SEGMENT_LENGTH; + + assert (seg_offset >= 0); + + if (seg_offset < 4){ // somewhere in a data seg sync. + int n = min (4 - seg_offset, nsamples); + + filter_data_seg_sync (input_samples, output_samples, n, seg_offset); + + d_offset_from_last_field_sync += n; + nsamples -= n; + + if (nsamples > 0){ + if (WINNING_COMPILER) + filter (&input_samples[n], &input_tags[n], + &output_samples[n], nsamples); + else { + input_samples += n; + input_tags += n; + output_samples += n; + goto lame_compiler_kludge; + } + } + return; + } + + // otherwise... we're in the normal zone + + int n = min (ATSC_DATA_SEGMENT_LENGTH - seg_offset, nsamples); + + filter_normal (input_samples, output_samples, n); + + d_offset_from_last_field_sync += n; + nsamples -= n; + + if (nsamples <= 0) + return; + + if (WINNING_COMPILER) + filter (&input_samples[n], &input_tags[n], + &output_samples[n], nsamples); + else { + input_samples += n; + input_tags += n; + output_samples += n; + goto lame_compiler_kludge; + } +} diff --git a/gr-atsc/src/lib/atsci_equalizer.h b/gr-atsc/src/lib/atsci_equalizer.h new file mode 100644 index 00000000..53bc9b6a --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer.h @@ -0,0 +1,163 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_EQUALIZER_H_ +#define _ATSC_EQUALIZER_H_ + +#include + +/*! + * \brief abstract base class for ATSC equalizer + */ +class atsci_equalizer { + +private: + + /* + * have we seen a field sync since the last reset or problem? + */ + bool d_locked_p; + + /* + * sample offset from the beginning of the last field sync we saw + * to the beginning of our current input stream. When we're locked + * this will be in [0, 313*832] i.e., [0, 260416] + */ + int d_offset_from_last_field_sync; + + int d_current_field; // [0,1] + + +public: + + // CREATORS + atsci_equalizer (); + virtual ~atsci_equalizer (); + + // MANIPULATORS + + /*! + * \brief reset state (e.g., on channel change) + * + * Note, subclasses must invoke the superclass's method too! + */ + virtual void reset (); + + /*! + * \brief produce \p nsamples of output from given inputs and tags + * + * This is the main entry point. It examines the input_tags + * and local state and invokes the appropriate virtual function + * to handle each sub-segment of the input data. + * + * \p input_samples must have (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] are + * referenced to compute the output values. + * + * \p input_tags must have nsamples valid entries. + * input_tags[0] .. input_tags[nsamples - 1] are referenced to + * compute the output values. + */ + virtual void filter (const float *input_samples, + const atsc::syminfo *input_tags, + float *output_samples, + int nsamples); + + // ACCESSORS + + /*! + * \brief how much history the input data stream requires. + * + * This must return a value >= 1. Think of this as the number + * of samples you need to look at to compute a single output sample. + */ + virtual int ntaps () const = 0; + + /*! + * \brief how many taps are "in the future". + * + * This allows us to handle what the ATSC folks call "pre-ghosts". + * What it really does is allow the caller to jack with the offset + * between the tags and the data so that everything magically works out. + * + * npretaps () must return a value between 0 and ntaps() - 1. + * + * If npretaps () returns 0, this means that the equalizer will only handle + * multipath "in the past." I suspect that a good value would be something + * like 15% - 20% of ntaps (). + */ + virtual int npretaps () const = 0; + + +protected: + + /*! + * Input range is known NOT TO CONTAIN data segment syncs + * or field syncs. This should be the fast path. In the + * non decicion directed case, this just runs the input + * through the filter without adapting it. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ + virtual void filter_normal (const float *input_samples, + float *output_samples, + int nsamples) = 0; + + /*! + * Input range is known to consist of only a data segment sync or a + * portion of a data segment sync. \p nsamples will be in [1,4]. + * \p offset will be in [0,3]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ + virtual void filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset) = 0; + + /*! + * Input range is known to consist of only a field sync segment or a + * portion of a field sync segment. \p nsamples will be in [1,832]. + * \p offset will be in [0,831]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. We consider the + * 4 symbols of the immediately preceding data segment sync to be the + * first symbols of the field sync segment. \p which_field is in [0,1] + * and specifies which field (duh). + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ + virtual void filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field) = 0; +}; + + +#endif /* _ATSC_EQUALIZER_H_ */ diff --git a/gr-atsc/src/lib/atsci_equalizer_lms.cc b/gr-atsc/src/lib/atsci_equalizer_lms.cc new file mode 100644 index 00000000..2fc084b3 --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer_lms.cc @@ -0,0 +1,306 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + +using std::min; +using std::max; + +static const int NTAPS = 256; +static const int NPRETAPS = (int) (NTAPS * 0.8); // probably should be either .2 or .8 + + +// the length of the field sync pattern that we know unequivocally +static const int KNOWN_FIELD_SYNC_LENGTH = 4 + 511 + 3 * 63; + +static const float *get_data_seg_sync_training_sequence (int offset); +static int get_field_sync_training_sequence_length (int offset); +static const float *get_field_sync_training_sequence (int which_field, int offset); + + +atsci_equalizer_lms::atsci_equalizer_lms () : d_taps (NTAPS) +{ + for (int i = 0; i < NTAPS; i++) { + d_taps[i] = 0.0; + } + trainingfile=fopen("taps.txt","w"); +} + +atsci_equalizer_lms::~atsci_equalizer_lms () +{ +} + +void +atsci_equalizer_lms::reset () +{ + atsci_equalizer::reset (); // invoke superclass + + for (int i = 0; i < NTAPS; i++) { + d_taps[i] = 0.0; + } +} + +int +atsci_equalizer_lms::ntaps () const +{ + return NTAPS; +} + +int +atsci_equalizer_lms::npretaps () const +{ + return NPRETAPS; +} + +/*! + * Input range is known NOT TO CONTAIN data segment syncs + * or field syncs. This should be the fast path. In the + * non decicion directed case, this just runs the input + * through the filter without adapting it. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_lms::filter_normal (const float *input_samples, + float *output_samples, + int nsamples) +{ + // handle data + filterN (input_samples, output_samples, nsamples); +} + + +/*! + * Input range is known to consist of only a data segment sync or a + * portion of a data segment sync. \p nsamples will be in [1,4]. + * \p offset will be in [0,3]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_lms::filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset) +{ + // handle data + // adaptN (input_samples, get_data_seg_sync_training_sequence (offset), + // output_samples, nsamples); + filterN (input_samples, output_samples, nsamples); + + // cerr << "Seg Sync: offset " << offset << "\tnsamples\t" << nsamples << "\t pre, 5 -5 -5 5\t" << + // output_samples[0] << "\t" << output_samples[1] << "\t" << output_samples[2] << "\t" << output_samples[3] << endl; + +} + + +/*! + * Input range is known to consist of only a field sync segment or a + * portion of a field sync segment. \p nsamples will be in [1,832]. + * \p offset will be in [0,831]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. We consider the + * 4 symbols of the immediately preceding data segment sync to be the + * first symbols of the field sync segment. \p which_field is in [0,1] + * and specifies which field (duh). + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_lms::filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field) +{ + // Only the first 4 + 511 + 3 * 63 symbols are completely defined. + // Those after that the symbols are bilevel, so we could use decision feedback and use + // that to train, but for now, don't train on them. + + int n = min (nsamples, get_field_sync_training_sequence_length (offset)); + + // handle known training sequence + adaptN (input_samples, get_field_sync_training_sequence (which_field, offset), + output_samples, n); + + // just filter any unknown portion + if (nsamples > n) + filterN (&input_samples[n], &output_samples[n], nsamples - n); + + if (offset == 0 && nsamples > 0){ + for (int i = 0; i < NTAPS; i++) + fprintf(trainingfile,"%f ",d_taps[i]); + + fprintf (trainingfile,"\n"); + } + +} + +// ---------------------------------------------------------------- + +// +// filter a single output +// +float +atsci_equalizer_lms::filter1 (const float input[]) +{ + static const int N_UNROLL = 4; + + float acc0 = 0; + float acc1 = 0; + float acc2 = 0; + float acc3 = 0; + + + unsigned i = 0; + unsigned n = (NTAPS / N_UNROLL) * N_UNROLL; + + for (i = 0; i < n; i += N_UNROLL){ + acc0 += d_taps[i + 0] * input[i + 0]; + acc1 += d_taps[i + 1] * input[i + 1]; + acc2 += d_taps[i + 2] * input[i + 2]; + acc3 += d_taps[i + 3] * input[i + 3]; + } + + for (; i < (unsigned) NTAPS; i++) + acc0 += d_taps[i] * input[i]; + + return (acc0 + acc1 + acc2 + acc3); +} + +// +// filter and adapt a single output +// +float +atsci_equalizer_lms::adapt1 (const float input[], float ideal_output) +{ + static const double BETA = 0.00005; // FIXME figure out what this ought to be + // FIXME add gear-shifting + + double y = filter1 (input); + double e = y - ideal_output; + + // update taps... + for (int i = 0; i < NTAPS; i++){ + d_taps[i] = d_taps[i] - BETA * e * (double)(input[i]); + } + + return y; +} + +void +atsci_equalizer_lms::filterN (const float *input_samples, + float *output_samples, + int nsamples) +{ + for (int i = 0; i < nsamples; i++) + output_samples[i] = filter1 (&input_samples[i]); +} + + +void +atsci_equalizer_lms::adaptN (const float *input_samples, + const float *training_pattern, + float *output_samples, + int nsamples) +{ + for (int i = 0; i < nsamples; i++) + output_samples[i] = adapt1 (&input_samples[i], training_pattern[i]); +} + +// ---------------------------------------------------------------- + +static float +bin_map (int bit) +{ + return bit ? +5 : -5; +} + +static void +init_field_sync_common (float *p, int mask) + +{ + int i = 0; + + p[i++] = bin_map (1); // data segment sync pulse + p[i++] = bin_map (0); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + + for (int j = 0; j < 511; j++) // PN511 + p[i++] = bin_map (atsc_pn511[j]); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map (atsc_pn63[j]); + + for (int j = 0; j < 63; j++) // PN63, toggled on field 2 + p[i++] = bin_map (atsc_pn63[j] ^ mask); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map (atsc_pn63[j]); + + assert (i == KNOWN_FIELD_SYNC_LENGTH); +} + + +static const float * +get_data_seg_sync_training_sequence (int offset) +{ + static const float training_data[4] = { +5, -5, -5, +5 }; + return &training_data[offset]; +} + +static int +get_field_sync_training_sequence_length (int offset) +{ + return max (0, KNOWN_FIELD_SYNC_LENGTH - offset); +} + +static const float * +get_field_sync_training_sequence (int which_field, int offset) +{ + static float *field_1 = 0; + static float *field_2 = 0; + + if (field_1 == 0){ + field_1 = new float[KNOWN_FIELD_SYNC_LENGTH]; + field_2 = new float[KNOWN_FIELD_SYNC_LENGTH]; + init_field_sync_common (field_1, 0); + init_field_sync_common (field_2, 1); + } + + if (which_field == 0) + return &field_1[offset]; + else + return &field_2[offset]; +} diff --git a/gr-atsc/src/lib/atsci_equalizer_lms.h b/gr-atsc/src/lib/atsci_equalizer_lms.h new file mode 100644 index 00000000..8303647c --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer_lms.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_EQUALIZER_LMS_H_ +#define _ATSC_EQUALIZER_LMS_H_ + +#include +#include +#include + +class atsci_equalizer_lms : public atsci_equalizer +{ +public: + atsci_equalizer_lms (); + virtual ~atsci_equalizer_lms (); + + virtual void reset (); + virtual int ntaps () const; + virtual int npretaps () const; + +protected: + FILE *trainingfile; + virtual void filter_normal (const float *input_samples, + float *output_samples, + int nsamples); + + virtual void filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset); + + virtual void filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field); + +private: + std::vector d_taps; + + void filterN (const float *input_samples, + float *output_samples, + int nsamples); + + void adaptN (const float *input_samples, + const float *training_pattern, + float *output_samples, + int nsamples); + + float filter1 (const float input[]); + float adapt1 (const float input[], float ideal_output); + +}; + + +#endif /* _ATSC_EQUALIZER_LMS_H_ */ diff --git a/gr-atsc/src/lib/atsci_equalizer_lms2.cc b/gr-atsc/src/lib/atsci_equalizer_lms2.cc new file mode 100644 index 00000000..d461d608 --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer_lms2.cc @@ -0,0 +1,373 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::min; +using std::max; + +static const int NFFTAPS = 64; +static const int NFBTAPS = 192; + +// the length of the field sync pattern that we know unequivocally +static const int KNOWN_FIELD_SYNC_LENGTH = 4 + 511 + 3 * 63; + +static const float *get_data_seg_sync_training_sequence (int offset); +static int get_field_sync_training_sequence_length (int offset); +static const float *get_field_sync_training_sequence (int which_field, int offset); + +static inline int +wrap (int d) +{ + assert (d >= 0 && d <= (2 * NFBTAPS)); + + if(d >= NFBTAPS) + return d - NFBTAPS; + return d; +} + +static inline float +slice (float d) +{ + if (gr_isnan (d)) + return 0.0; + + if (d >= 0.0){ + if (d >= 4.0){ + if (d >= 6.0) + return 7.0; + else + return 5.0; + } + if (d >= 2.0) + return 3.0; + return 1.0; + } + else + return -slice (-d); +} + +atsci_equalizer_lms2::atsci_equalizer_lms2 () + : d_taps_ff (NFFTAPS), d_taps_fb (NFBTAPS), d_old_output (NFBTAPS) +{ + for (int i = 0; i < NFFTAPS; i++) { + d_taps_ff[i] = 0.0; + } + for (int i = 0; i < NFBTAPS; i++) { + d_taps_fb[i] = 0.0; + d_old_output[i] = 0.0; + } + d_output_ptr = 0; + trainingfile=fopen("taps.txt","w"); +} + +atsci_equalizer_lms2::~atsci_equalizer_lms2 () +{ +} + +void +atsci_equalizer_lms2::reset () +{ + atsci_equalizer::reset (); // invoke superclass + for (int i = 0; i < NFFTAPS; i++) { + d_taps_ff[i] = 0.0; + } + for (int i = 0; i < NFBTAPS; i++) { + d_taps_fb[i] = 0.0; + d_old_output[i] = 0.0; + } + d_output_ptr = 0; +} + + +int +atsci_equalizer_lms2::ntaps () const +{ + return NFFTAPS + NFBTAPS; +} + +int +atsci_equalizer_lms2::npretaps () const +{ + return NFFTAPS; +} + +/*! + * Input range is known NOT TO CONTAIN data segment syncs + * or field syncs. This should be the fast path. In the + * non decicion directed case, this just runs the input + * through the filter without adapting it. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_lms2::filter_normal (const float *input_samples, + float *output_samples, + int nsamples) +{ + // handle data + filterN (input_samples, output_samples, nsamples); +} + + +/*! + * Input range is known to consist of only a data segment sync or a + * portion of a data segment sync. \p nsamples will be in [1,4]. + * \p offset will be in [0,3]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_lms2::filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset) +{ + // handle data + // adaptN (input_samples, get_data_seg_sync_training_sequence (offset), + // output_samples, nsamples); + filterN (input_samples, output_samples, nsamples); + + // cerr << "Seg Sync: offset " << offset << "\tnsamples\t" << nsamples << "\t pre, 5 -5 -5 5\t" << + // output_samples[0] << "\t" << output_samples[1] << "\t" << output_samples[2] << "\t" << output_samples[3] << endl; + +} + + +/*! + * Input range is known to consist of only a field sync segment or a + * portion of a field sync segment. \p nsamples will be in [1,832]. + * \p offset will be in [0,831]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. We consider the + * 4 symbols of the immediately preceding data segment sync to be the + * first symbols of the field sync segment. \p which_field is in [0,1] + * and specifies which field (duh). + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_lms2::filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field) +{ + // Only the first 4 + 511 + 3 * 63 symbols are completely defined. + // Those after that the symbols are bilevel, so we could use decision feedback and use + // that to train, but for now, don't train on them. + + int n = min (nsamples, get_field_sync_training_sequence_length (offset)); + + // handle known training sequence + adaptN (input_samples, get_field_sync_training_sequence (which_field, offset), + output_samples, n); + + // just filter any unknown portion + if (nsamples > n) + filterN (&input_samples[n], &output_samples[n], nsamples - n); + + if (offset == 0 && nsamples > 0){ + for (int i = 0; i < NFFTAPS; i++) + fprintf(trainingfile,"%f ",d_taps_ff[i]); + for (int i = 0; i < NFBTAPS; i++) + fprintf(trainingfile,"%f ",d_taps_fb[i]); + fprintf (trainingfile,"\n"); + } + +} + +// ---------------------------------------------------------------- + +// +// filter a single output +// +float +atsci_equalizer_lms2::filter1 (const float input[]) +{ + static const int N_UNROLL = 4; + + float acc0 = 0; + float acc1 = 0; + float acc2 = 0; + float acc3 = 0; + float acc = 0; + + + unsigned i = 0; + unsigned n = (NFFTAPS / N_UNROLL) * N_UNROLL; + + for (i = 0; i < n; i += N_UNROLL){ + acc0 += d_taps_ff[i + 0] * input[i + 0]; + acc1 += d_taps_ff[i + 1] * input[i + 1]; + acc2 += d_taps_ff[i + 2] * input[i + 2]; + acc3 += d_taps_ff[i + 3] * input[i + 3]; + } + + for (; i < (unsigned) NFFTAPS; i++) + acc0 += d_taps_ff[i] * input[i]; + + acc = (acc0 + acc1 + acc2 + acc3); + + d_output_ptr = wrap (d_output_ptr + 1); + + for (int i = 0; i < NFBTAPS; i++) { + acc -= d_taps_fb[i] * d_old_output[wrap(i + d_output_ptr)]; + } + + if (gr_isnan (acc)){ + abort (); + } + + d_old_output[d_output_ptr] = slice (acc); + return acc; +} + +// +// filter and adapt a single output +// +float kludge () +{ + return 0.0; +} + +float +atsci_equalizer_lms2::adapt1 (const float input[], float ideal_output) +{ + static const double BETA = 0.00005; // FIXME figure out what this ought to be + // FIXME add gear-shifting + + double y = filter1 (input); + double e = y - ideal_output; + + // update taps... + for (int i = 0; i < NFFTAPS; i++){ + d_taps_ff[i] = d_taps_ff[i] - BETA * e * (double)(input[i]); + } + + for (int i = 0; i < NFBTAPS; i++){ + // d_taps_fb[i] = d_taps_fb[i] - BETA * e * (double)d_old_output[wrap(i+d_output_ptr)]; + d_taps_fb[i] = d_taps_fb[i] - kludge() * e * (double)d_old_output[wrap(i+d_output_ptr)]; + } + + return y; +} + +void +atsci_equalizer_lms2::filterN (const float *input_samples, + float *output_samples, + int nsamples) +{ + for (int i = 0; i < nsamples; i++) + output_samples[i] = filter1 (&input_samples[i]); +} + + +void +atsci_equalizer_lms2::adaptN (const float *input_samples, + const float *training_pattern, + float *output_samples, + int nsamples) +{ + for (int i = 0; i < nsamples; i++) + output_samples[i] = adapt1 (&input_samples[i], training_pattern[i]); +} + +// ---------------------------------------------------------------- + +static float +bin_map (int bit) +{ + return bit ? +5 : -5; +} + +static void +init_field_sync_common (float *p, int mask) + +{ + int i = 0; + + p[i++] = bin_map (1); // data segment sync pulse + p[i++] = bin_map (0); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + + for (int j = 0; j < 511; j++) // PN511 + p[i++] = bin_map (atsc_pn511[j]); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map (atsc_pn63[j]); + + for (int j = 0; j < 63; j++) // PN63, toggled on field 2 + p[i++] = bin_map (atsc_pn63[j] ^ mask); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map (atsc_pn63[j]); + + assert (i == KNOWN_FIELD_SYNC_LENGTH); +} + + +static const float * +get_data_seg_sync_training_sequence (int offset) +{ + static const float training_data[4] = { +5, -5, -5, +5 }; + return &training_data[offset]; +} + +static int +get_field_sync_training_sequence_length (int offset) +{ + return max (0, KNOWN_FIELD_SYNC_LENGTH - offset); +} + +static const float * +get_field_sync_training_sequence (int which_field, int offset) +{ + static float *field_1 = 0; + static float *field_2 = 0; + + if (field_1 == 0){ + field_1 = new float[KNOWN_FIELD_SYNC_LENGTH]; + field_2 = new float[KNOWN_FIELD_SYNC_LENGTH]; + init_field_sync_common (field_1, 0); + init_field_sync_common (field_2, 1); + } + + if (which_field == 0) + return &field_1[offset]; + else + return &field_2[offset]; +} diff --git a/gr-atsc/src/lib/atsci_equalizer_lms2.h b/gr-atsc/src/lib/atsci_equalizer_lms2.h new file mode 100644 index 00000000..60ac8944 --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer_lms2.h @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_EQUALIZER_LMS2_H_ +#define _ATSC_EQUALIZER_LMS2_H_ + +#include +#include +#include + +class atsci_equalizer_lms2 : public atsci_equalizer +{ +public: + atsci_equalizer_lms2 (); + virtual ~atsci_equalizer_lms2 (); + + virtual void reset (); + virtual int ntaps () const; + virtual int npretaps () const; + +protected: + FILE *trainingfile; + virtual void filter_normal (const float *input_samples, + float *output_samples, + int nsamples); + + virtual void filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset); + + virtual void filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field); + +private: + std::vector d_taps_ff; + std::vector d_taps_fb; + std::vector d_old_output; + + int d_output_ptr; + + void filterN (const float *input_samples, + float *output_samples, + int nsamples); + + void adaptN (const float *input_samples, + const float *training_pattern, + float *output_samples, + int nsamples); + + float filter1 (const float input[]); + float adapt1 (const float input[], float ideal_output); + +}; + + +#endif /* _ATSC_EQUALIZER_LMS2_H_ */ diff --git a/gr-atsc/src/lib/atsci_equalizer_nop.cc b/gr-atsc/src/lib/atsci_equalizer_nop.cc new file mode 100644 index 00000000..681a6b24 --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer_nop.cc @@ -0,0 +1,133 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +atsci_equalizer_nop::atsci_equalizer_nop () +{ +} + +atsci_equalizer_nop::~atsci_equalizer_nop () +{ +} + +void +atsci_equalizer_nop::reset () +{ + atsci_equalizer::reset (); // invoke superclass +} + +int +atsci_equalizer_nop::ntaps () const +{ + return 1; +} + +int +atsci_equalizer_nop::npretaps () const +{ + return 0; +} + +/*! + * Input range is known NOT TO CONTAIN data segment syncs + * or field syncs. This should be the fast path. In the + * non decicion directed case, this just runs the input + * through the filter without adapting it. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_nop::filter_normal (const float *input_samples, + float *output_samples, + int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + output_samples[i] = scale (input_samples[i]); + } +} + + +/*! + * Input range is known to consist of only a data segment sync or a + * portion of a data segment sync. \p nsamples will be in [1,4]. + * \p offset will be in [0,3]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_nop::filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset) +{ + for (int i = 0; i < nsamples; i++){ + output_samples[i] = scale_and_train (input_samples[i]); + } +} + + +/*! + * Input range is known to consist of only a field sync segment or a + * portion of a field sync segment. \p nsamples will be in [1,832]. + * \p offset will be in [0,831]. \p offset is the offset of the input + * from the beginning of the data segment sync pattern. We consider the + * 4 symbols of the immediately preceding data segment sync to be the + * first symbols of the field sync segment. \p which_field is in [0,1] + * and specifies which field (duh). + * + * \p input_samples has (nsamples + ntaps() - 1) valid entries. + * input_samples[0] .. input_samples[nsamples - 1 + ntaps() - 1] may be + * referenced to compute the output values. + */ +void +atsci_equalizer_nop::filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field) +{ + int i = 0; + + if (offset == 0 && nsamples > 0){ + output_samples[0] = scale_and_train (input_samples[0]); + i++; + } + + for (; i < nsamples; i++){ + output_samples[i] = scale_and_train (input_samples[i]); + } +} + + +float +atsci_equalizer_nop::scale_and_train (float input) +{ + return input; +} diff --git a/gr-atsc/src/lib/atsci_equalizer_nop.h b/gr-atsc/src/lib/atsci_equalizer_nop.h new file mode 100644 index 00000000..b5f5b0cc --- /dev/null +++ b/gr-atsc/src/lib/atsci_equalizer_nop.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_EQUALIZER_NOP_H_ +#define _ATSC_EQUALIZER_NOP_H_ + +#include + +class atsci_equalizer_nop : public atsci_equalizer +{ +private: + float scale (float input) { return input; } + + float scale_and_train (float input); + + +public: + atsci_equalizer_nop (); + virtual ~atsci_equalizer_nop (); + + virtual void reset (); + virtual int ntaps () const; + virtual int npretaps () const; + +protected: + virtual void filter_normal (const float *input_samples, + float *output_samples, + int nsamples); + + virtual void filter_data_seg_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset); + + virtual void filter_field_sync (const float *input_samples, + float *output_samples, + int nsamples, + int offset, + int which_field); +}; + + +#endif /* _ATSC_EQUALIZER_NOP_H_ */ diff --git a/gr-atsc/src/lib/atsci_exp2_lp.cc b/gr-atsc/src/lib/atsci_exp2_lp.cc new file mode 100644 index 00000000..9c7216db --- /dev/null +++ b/gr-atsc/src/lib/atsci_exp2_lp.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +using std::vector; +using std::cerr; +using std::endl; + +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:LOW PASS 1H + * PASSBAND RIPPLE IN -dB -.0100 + * STOPBAND RIPPLE IN -dB -66.0000 + * PASSBAND CUTOFF FREQUENCY 5.69000 HERTZ + * STOPBAND CUTOFF FREQUENCY 6.12000 HERTZ + * SAMPLING FREQUENCY 21.5200 HERTZ + */ +static const float atsci_exp2_lp2x[] = { +#include "atsci_exp2_lp2x.dat" +}; + +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:LOW PASS 1H + * PASSBAND RIPPLE IN -dB -.0100 + * STOPBAND RIPPLE IN -dB -66.0000 + * PASSBAND CUTOFF FREQUENCY 5.69000 HERTZ + * STOPBAND CUTOFF FREQUENCY 6.12000 HERTZ + * SAMPLING FREQUENCY 20.0000 HERTZ + */ +static const float atsci_exp2_lp20[] = { +#include "atsci_exp2_lp20.dat" +}; + + +#define NELEM(x) (sizeof (x) / sizeof ((x)[0])) + +// is A within 5% of TARGET? + +static bool +close_enough_p (double a, double target) +{ + double delta = fabs (target * 0.05); // 5 percent + + return fabs (target - a) <= delta; +} + +vector +atsci_exp2_lp::taps (double sampling_freq) +{ + if (close_enough_p (sampling_freq, 20e6)){ + return vector(&atsci_exp2_lp20[0], &atsci_exp2_lp20[NELEM(atsci_exp2_lp20)]); + } + if (close_enough_p (sampling_freq, 2 * ATSC_SYMBOL_RATE)){ + return vector(&atsci_exp2_lp2x[0], &atsci_exp2_lp2x[NELEM(atsci_exp2_lp2x)]); + } + else + throw std::out_of_range ( + "atsci_exp2_lp: no pre-designed filter close enough"); +} diff --git a/gr-atsc/src/lib/atsci_exp2_lp.h b/gr-atsc/src/lib/atsci_exp2_lp.h new file mode 100644 index 00000000..5370e40b --- /dev/null +++ b/gr-atsc/src/lib/atsci_exp2_lp.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_EXP2_LP_H_ +#define _ATSC_EXP2_LP_H_ + +#include + +class atsci_exp2_lp : public gr_fir_builder +{ +public: + virtual std::vector taps (double sampling_freq); +}; + +#endif /* _ATSC_EXP2_LP_H_ */ diff --git a/gr-atsc/src/lib/atsci_exp2_lp20.dat b/gr-atsc/src/lib/atsci_exp2_lp20.dat new file mode 100644 index 00000000..b810fac7 --- /dev/null +++ b/gr-atsc/src/lib/atsci_exp2_lp20.dat @@ -0,0 +1,178 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:LOW PASS 1H + * PASSBAND RIPPLE IN -dB -.0100 + * STOPBAND RIPPLE IN -dB -66.0000 + * PASSBAND CUTOFF FREQUENCY 5.69000 HERTZ + * STOPBAND CUTOFF FREQUENCY 6.12000 HERTZ + * SAMPLING FREQUENCY 20.0000 HERTZ + */ + -.3137849271297455e-03, + -.6755953654646874e-04, + .2326252870261669e-03, + -.1614624634385109e-03, + -.1158984377980232e-03, + .2114051021635532e-03, + .6828224286437035e-04, + -.3522797487676144e-03, + .1759170554578304e-03, + .2849949523806572e-03, + -.3568925894796848e-03, + -.1521380618214607e-03, + .5445396527647972e-03, + -.1707794144749641e-03, + -.5257474258542061e-03, + .5062967538833618e-03, + .3262492828071117e-03, + -.8037807419896126e-03, + .1136297360062599e-03, + .8607362397015095e-03, + -.6433278322219849e-03, + -.6174184381961823e-03, + .1120670232921839e-02, + .3442214801907539e-04, + -.1305819023400545e-02, + .7387576624751091e-03, + .1056550536304712e-02, + -.1477979123592377e-02, + -.3192713484168053e-03, + .1870564185082912e-02, + -.7502869702875614e-03, + -.1675266306847334e-02, + .1847642473876476e-02, + .7931739091873169e-03, + -.2555002458393574e-02, + .6227688863873482e-03, + .2505954820662737e-02, + -.2186967991292477e-02, + -.1515555195510387e-02, + .3349546808749437e-02, + -.2860687673091888e-03, + -.3578922711312771e-02, + .2438103780150414e-02, + .2555412705987692e-02, + -.4232846200466156e-02, + -.3483905456960201e-03, + .4926202818751335e-02, + -.2523601986467838e-02, + -.3997647203505039e-02, + .5173782818019390e-02, + .1395780127495527e-02, + -.6588382180780172e-02, + .2339247148483992e-02, + .5959283560514450e-02, + -.6131949834525585e-02, + -.3020572476089001e-02, + .8632841985672712e-02, + -.1736589241772890e-02, + -.8627892937511206e-02, + .7060498464852572e-02, + .5489445291459560e-02, + -.1119629153981805e-01, + .4754690453410149e-03, + .1235919492319226e-01, + -.7909852080047131e-02, + -.9316097479313612e-02, + .1459939032793045e-01, + .1910720951855183e-02, + -.1796151325106621e-01, + .8631225209683180e-02, + .1572139468044043e-01, + -.1972115319222212e-01, + -.6601144559681416e-02, + .2775513892993331e-01, + -.9181375615298748e-02, + -.2863558568060398e-01, + .2976502152159810e-01, + .1806837785989046e-01, + -.5192282795906067e-01, + .9526194538921118e-02, + .7172224065288901e-01, + -.6965141417458654e-01, + -.8541030902415514e-01, + .3052920936606824e+00, + .5900069065392017e+00, + .3052920936606824e+00, + -.8541030902415514e-01, + -.6965141417458654e-01, + .7172224065288901e-01, + .9526194538921118e-02, + -.5192282795906067e-01, + .1806837785989046e-01, + .2976502152159810e-01, + -.2863558568060398e-01, + -.9181375615298748e-02, + .2775513892993331e-01, + -.6601144559681416e-02, + -.1972115319222212e-01, + .1572139468044043e-01, + .8631225209683180e-02, + -.1796151325106621e-01, + .1910720951855183e-02, + .1459939032793045e-01, + -.9316097479313612e-02, + -.7909852080047131e-02, + .1235919492319226e-01, + .4754690453410149e-03, + -.1119629153981805e-01, + .5489445291459560e-02, + .7060498464852572e-02, + -.8627892937511206e-02, + -.1736589241772890e-02, + .8632841985672712e-02, + -.3020572476089001e-02, + -.6131949834525585e-02, + .5959283560514450e-02, + .2339247148483992e-02, + -.6588382180780172e-02, + .1395780127495527e-02, + .5173782818019390e-02, + -.3997647203505039e-02, + -.2523601986467838e-02, + .4926202818751335e-02, + -.3483905456960201e-03, + -.4232846200466156e-02, + .2555412705987692e-02, + .2438103780150414e-02, + -.3578922711312771e-02, + -.2860687673091888e-03, + .3349546808749437e-02, + -.1515555195510387e-02, + -.2186967991292477e-02, + .2505954820662737e-02, + .6227688863873482e-03, + -.2555002458393574e-02, + .7931739091873169e-03, + .1847642473876476e-02, + -.1675266306847334e-02, + -.7502869702875614e-03, + .1870564185082912e-02, + -.3192713484168053e-03, + -.1477979123592377e-02, + .1056550536304712e-02, + .7387576624751091e-03, + -.1305819023400545e-02, + .3442214801907539e-04, + .1120670232921839e-02, + -.6174184381961823e-03, + -.6433278322219849e-03, + .8607362397015095e-03, + .1136297360062599e-03, + -.8037807419896126e-03, + .3262492828071117e-03, + .5062967538833618e-03, + -.5257474258542061e-03, + -.1707794144749641e-03, + .5445396527647972e-03, + -.1521380618214607e-03, + -.3568925894796848e-03, + .2849949523806572e-03, + .1759170554578304e-03, + -.3522797487676144e-03, + .6828224286437035e-04, + .2114051021635532e-03, + -.1158984377980232e-03, + -.1614624634385109e-03, + .2326252870261669e-03, + -.6755953654646874e-04, + -.3137849271297455e-03 diff --git a/gr-atsc/src/lib/atsci_exp2_lp2x.dat b/gr-atsc/src/lib/atsci_exp2_lp2x.dat new file mode 100644 index 00000000..16b2b47d --- /dev/null +++ b/gr-atsc/src/lib/atsci_exp2_lp2x.dat @@ -0,0 +1,196 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:LOW PASS 1H + * PASSBAND RIPPLE IN -dB -.0100 + * STOPBAND RIPPLE IN -dB -66.0000 + * PASSBAND CUTOFF FREQUENCY 5.69000 HERTZ + * STOPBAND CUTOFF FREQUENCY 6.12000 HERTZ + * SAMPLING FREQUENCY 21.5200 HERTZ + */ + +/* + * probably total overkill... +*/ + -.8815620094537735E-04, + -.3356961533427239E-03, + .1227599568665028E-03, + .1281457953155041E-03, + -.1479196362197399E-03, + -.1201131381094456E-03, + .2271742559969425E-03, + .6969040259718895E-04, + -.3000237047672272E-03, + .1565506681799889E-04, + .3562141209840775E-03, + -.1368308439850807E-03, + -.3795824013650417E-03, + .2876669168472290E-03, + .3540110774338245E-03, + -.4550744779407978E-03, + -.2659554593265057E-03, + .6190738640725613E-03, + .1072990708053112E-03, + -.7539116777479649E-03, + .1217066310346127E-03, + .8306214585900307E-03, + -.4104166291654110E-03, + -.8203103207051754E-03, + .7365280762314796E-03, + .6983750499784946E-03, + -.1066216267645359E-02, + -.4491899162530899E-03, + .1356074586510658E-02, + .7050111889839172E-04, + -.1556793693453074E-02, + .4230584017932415E-03, + .1618413720279932E-02, + -.9978362359106541E-03, + -.1497142482548952E-02, + .1601643394678831E-02, + .1162088476121426E-02, + -.2165937330573797E-02, + -.6025419570505619E-03, + .2611500211060047E-02, + -.1667905598878861E-03, + -.2855417784303427E-02, + .1101639121770859E-02, + .2821092493832111E-02, + -.2127973828464747E-02, + -.2448682673275471E-02, + .3145063761621714E-02, + .1706911250948906E-02, + -.4030079115182161E-02, + -.5993186496198177E-03, + .4651836119592190E-02, + -.8259965106844902E-03, + -.4880243912339211E-02, + .2475241199135780E-02, + .4603198729455471E-02, + -.4209769889712334E-02, + -.3741886932402849E-02, + .5853117443621159E-02, + .2264967188239098E-02, + -.7202429696917534E-02, + -.2001645043492317E-03, + .8043776731938124E-02, + -.2357403747737408E-02, + -.8171265944838524E-02, + .5242727231234312E-02, + .7407441269606352E-02, + -.8224328979849815E-02, + -.5622585304081440E-02, + .1101253507658839E-01, + .2751644235104322E-02, + -.1327139046043158E-01, + .1191724557429552E-02, + .1463502133265138E-01, + -.6110311951488257E-02, + -.1471871789544821E-01, + .1182264182716608E-01, + .1312375022098422E-01, + -.1807126961648464E-01, + -.9420783724635840E-02, + .2453883877024055E-01, + .3084233496338129E-02, + -.3086851537227631E-01, + .6689148955047131E-02, + .3669126378372312E-01, + -.2150753932073712E-01, + -.4165294021368027E-01, + .4559329804033041E-01, + .4544338863343000E-01, + -.9483475470915437E-01, + -.4782041534781456E-01, + .3143207929097116E+00, + .5483355415053666E+00, + .3143207929097116E+00, + -.4782041534781456E-01, + -.9483475470915437E-01, + .4544338863343000E-01, + .4559329804033041E-01, + -.4165294021368027E-01, + -.2150753932073712E-01, + .3669126378372312E-01, + .6689148955047131E-02, + -.3086851537227631E-01, + .3084233496338129E-02, + .2453883877024055E-01, + -.9420783724635840E-02, + -.1807126961648464E-01, + .1312375022098422E-01, + .1182264182716608E-01, + -.1471871789544821E-01, + -.6110311951488257E-02, + .1463502133265138E-01, + .1191724557429552E-02, + -.1327139046043158E-01, + .2751644235104322E-02, + .1101253507658839E-01, + -.5622585304081440E-02, + -.8224328979849815E-02, + .7407441269606352E-02, + .5242727231234312E-02, + -.8171265944838524E-02, + -.2357403747737408E-02, + .8043776731938124E-02, + -.2001645043492317E-03, + -.7202429696917534E-02, + .2264967188239098E-02, + .5853117443621159E-02, + -.3741886932402849E-02, + -.4209769889712334E-02, + .4603198729455471E-02, + .2475241199135780E-02, + -.4880243912339211E-02, + -.8259965106844902E-03, + .4651836119592190E-02, + -.5993186496198177E-03, + -.4030079115182161E-02, + .1706911250948906E-02, + .3145063761621714E-02, + -.2448682673275471E-02, + -.2127973828464747E-02, + .2821092493832111E-02, + .1101639121770859E-02, + -.2855417784303427E-02, + -.1667905598878861E-03, + .2611500211060047E-02, + -.6025419570505619E-03, + -.2165937330573797E-02, + .1162088476121426E-02, + .1601643394678831E-02, + -.1497142482548952E-02, + -.9978362359106541E-03, + .1618413720279932E-02, + .4230584017932415E-03, + -.1556793693453074E-02, + .7050111889839172E-04, + .1356074586510658E-02, + -.4491899162530899E-03, + -.1066216267645359E-02, + .6983750499784946E-03, + .7365280762314796E-03, + -.8203103207051754E-03, + -.4104166291654110E-03, + .8306214585900307E-03, + .1217066310346127E-03, + -.7539116777479649E-03, + .1072990708053112E-03, + .6190738640725613E-03, + -.2659554593265057E-03, + -.4550744779407978E-03, + .3540110774338245E-03, + .2876669168472290E-03, + -.3795824013650417E-03, + -.1368308439850807E-03, + .3562141209840775E-03, + .1565506681799889E-04, + -.3000237047672272E-03, + .6969040259718895E-04, + .2271742559969425E-03, + -.1201131381094456E-03, + -.1479196362197399E-03, + .1281457953155041E-03, + .1227599568665028E-03, + -.3356961533427239E-03, + -.8815620094537735E-04 diff --git a/gr-atsc/src/lib/atsci_fake_single_viterbi.cc b/gr-atsc/src/lib/atsci_fake_single_viterbi.cc new file mode 100644 index 00000000..365350cc --- /dev/null +++ b/gr-atsc/src/lib/atsci_fake_single_viterbi.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +using std::cerr; +using std::cout; + +void +atsci_fake_single_viterbi::reset() +{ + post_coder_state = 0; +} + +atsci_fake_single_viterbi::atsci_fake_single_viterbi() +{ + reset(); +} + +/* + * implement simple slicer and post coder + */ +char +atsci_fake_single_viterbi::decode (float input) +{ + int y2, y1; + + if (input < -4){ + y2 = 0; + y1 = 0; + } + else if (input < 0){ + y2 = 0; + y1 = 1; + } + else if (input < 4){ + y2 = 1; + y1 = 0; + } + else { + y2 = 1; + y1 = 1; + } + + int x1 = y1; + int x2 = y2 ^ post_coder_state; + post_coder_state = y2; + + return (x2 << 1) | x1; +} diff --git a/gr-atsc/src/lib/atsci_fake_single_viterbi.h b/gr-atsc/src/lib/atsci_fake_single_viterbi.h new file mode 100644 index 00000000..19f67740 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fake_single_viterbi.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSCFAKESINGLEVITERBI_H_ +#define _ATSCFAKESINGLEVITERBI_H_ + +/*! + * \brief single channel viterbi decoder + */ +class atsci_fake_single_viterbi +{ + +public: + atsci_fake_single_viterbi (); + + /*! + * \p INPUT ideally takes on the values +/- 1,3,5,7 + * return is decoded dibit in the range [0, 3] + */ + char decode (float input); + + void reset (); + + //! internal delay of decoder + int delay () { return 0; } + +protected: + int post_coder_state; +}; + +#endif diff --git a/gr-atsc/src/lib/atsci_fs_checker.cc b/gr-atsc/src/lib/atsci_fs_checker.cc new file mode 100644 index 00000000..52b20f84 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_checker.cc @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// empty constructor +atsci_fs_checker::atsci_fs_checker () +{ +} + +// empty virtual destructor +atsci_fs_checker::~atsci_fs_checker () +{ +} diff --git a/gr-atsc/src/lib/atsci_fs_checker.h b/gr-atsc/src/lib/atsci_fs_checker.h new file mode 100644 index 00000000..66e65076 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_checker.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_FS_CHECKER_H_ +#define _ATSC_FS_CHECKER_H_ + +#include + +/*! + * \brief abstract base class for ATSC field sync checker + * + * Processes input samples one at a time looking for + * an occurence of either the field sync 1 or field sync 2 pattern. + * + * Note that unlike atsci_fs_correlator, this class uses the symbol_num in + * input_tag to avoid having to test each symbol position. + * + * For each sample processed, an output sample and an output tag are produced. + * The output samples are identical to the input samples but are delayed by + * a number of samples given by \p delay(). The output tag associated with + * the the given output sample indicates whether this sample is the beginning + * of one of the field syncs or is an ordinary sample. The tags are defined in + * atsci_sync_tag.h. + * + * For ease of use, the field sync patterns are defined to begin with the + * first symbol of the 4 symbol data segment sync pattern that immediately + * proceeds the actual PN 511 code. This makes it easier for downstream code + * to determine the location of data segment syncs merely by counting. They'll + * occur every 832 samples assuming everything is working. + */ + +class atsci_fs_checker { + +public: + + // CREATORS + atsci_fs_checker (); + virtual ~atsci_fs_checker () = 0; + + // MANIPULATORS + virtual void reset () = 0; + virtual void filter (float input_sample, atsc::syminfo input_tag, + float *output_sample, atsc::syminfo *output_tag) = 0; + + // ACCESSORS + + //! return delay in samples from input to output + virtual int delay () const = 0; +}; + +#endif /* _ATSC_FS_CHECKER_H_ */ diff --git a/gr-atsc/src/lib/atsci_fs_checker_naive.cc b/gr-atsc/src/lib/atsci_fs_checker_naive.cc new file mode 100644 index 00000000..aac4c821 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_checker_naive.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +using std::cerr; +using std::endl; + +static const int PN511_ERROR_LIMIT = 20; // max number of bits wrong +static const int PN63_ERROR_LIMIT = 5; + +unsigned char atsci_fs_checker_naive::s_511[LENGTH_511]; +unsigned char atsci_fs_checker_naive::s_63[LENGTH_2ND_63]; + +static void +init_s_511 (unsigned char *p) +{ + *p++ = 1; // data segment sync pattern + *p++ = 0; + *p++ = 0; + *p++ = 1; + + for (int i = 0; i < 511; i++){ + p[i] = atsc_pn511[i]; + } +} + +static void +init_s_63 (unsigned char *p) +{ + for (int i = 0; i < 63; i++){ + p[i] = atsc_pn63[i]; + } +} + +atsci_fs_checker_naive::atsci_fs_checker_naive () +{ + init_s_511 (s_511); + init_s_63 (s_63); + reset (); +} + +atsci_fs_checker_naive::~atsci_fs_checker_naive () +{ +} + +void +atsci_fs_checker_naive::reset () +{ + d_index = 0; + memset (d_sample_sr, 0, sizeof (d_sample_sr)); + memset (d_tag_sr, 0, sizeof (d_tag_sr)); + memset (d_bit_sr, 0, sizeof (d_bit_sr)); + d_field_num = 0; + d_segment_num = 0; +} + +void +atsci_fs_checker_naive::filter (float input_sample, atsc::syminfo input_tag, + float *output_sample, atsc::syminfo *output_tag) +{ + atsc::syminfo proto_tag = d_tag_sr[d_index]; // oldest tag in the queue + + if (proto_tag.symbol_num == 0){ // check for field sync pattern + + d_segment_num = (d_segment_num + 1) & atsc::SI_SEGMENT_NUM_MASK; // increment + + // check for a hit on the PN 511 pattern + int errors = 0; + int start = wrap (d_index + OFFSET_511); + + for (int i = 0; i < LENGTH_511 && errors < PN511_ERROR_LIMIT; i++) + errors += d_bit_sr[wrap (start + i)] ^ s_511[i]; + + if (errors < PN511_ERROR_LIMIT){ // 511 pattern is good. + // determine if this is field 1 or field 2 + errors = 0; + start = wrap (d_index + OFFSET_2ND_63); + for (int i = 0; i < LENGTH_2ND_63; i++) + errors += d_bit_sr[wrap (start + i)] ^ s_63[i]; + + // we should have either field 1 (== PN63) or field 2 (== ~PN63) + + if (errors <= PN63_ERROR_LIMIT){ + d_segment_num = atsc::SI_FIELD_SYNC_SEGMENT_NUM; // this is FIELD_SYNC_1 + d_field_num = 0; + } + else if (errors >= (LENGTH_2ND_63 - PN63_ERROR_LIMIT)){ + d_segment_num = atsc::SI_FIELD_SYNC_SEGMENT_NUM; // this is FIELD_SYNC_2 + d_field_num = 1; + } + else { + // should be extremely rare. + cerr << "!!! atsci_fs_checker_naive: PN63 error count = " << errors << endl; + } + } + } + + proto_tag.segment_num = d_segment_num; // fill in segment number and field number + proto_tag.field_num = d_field_num; + + // return oldest sample + *output_sample = d_sample_sr[d_index]; + *output_tag = proto_tag; + + // overwrite with newest sample; + d_sample_sr[d_index] = input_sample; + d_bit_sr[d_index] = input_sample < 0 ? 0 : 1; + d_tag_sr[d_index] = input_tag; + d_index = incr (d_index); +} + +int +atsci_fs_checker_naive::delay () const +{ + return SRSIZE; +} diff --git a/gr-atsc/src/lib/atsci_fs_checker_naive.h b/gr-atsc/src/lib/atsci_fs_checker_naive.h new file mode 100644 index 00000000..b86ab181 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_checker_naive.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_FS_CHECKER_NAIVE_H_ +#define _ATSC_FS_CHECKER_NAIVE_H_ + +#include + +/*! + * \brief Naive concrete implementation of field sync checker + */ +class atsci_fs_checker_naive : public atsci_fs_checker { + + private: + static const int SRSIZE = 1024; // must be power of two + int d_index; // points at oldest sample + float d_sample_sr[SRSIZE]; // sample shift register + atsc::syminfo d_tag_sr[SRSIZE]; // tag shift register + unsigned char d_bit_sr[SRSIZE]; // binary decision shift register + int d_field_num; + int d_segment_num; + + static const int OFFSET_511 = 0; // offset to PN 511 pattern + static const int LENGTH_511 = 511 + 4; // length of PN 511 pattern (+ 4 seg sync) + static const int OFFSET_2ND_63 = 578; // offset to second PN 63 pattern + static const int LENGTH_2ND_63 = 63; // length of PN 63 pattern + + static unsigned char s_511[LENGTH_511]; // PN 511 pattern + static unsigned char s_63[LENGTH_2ND_63]; // PN 63 pattern + + inline static int wrap (int index){ return index & (SRSIZE - 1); } + inline static int incr (int index){ return wrap (index + 1); } + inline static int decr (int index){ return wrap (index - 1); } + + public: + + // CREATORS + atsci_fs_checker_naive (); + ~atsci_fs_checker_naive (); + + // MANIPULATORS + virtual void reset (); + void filter (float input_sample, atsc::syminfo input_tag, + float *output_sample, atsc::syminfo *output_tag); + + // ACCESSORS + + //! return delay in samples from input to output + int delay () const; + +}; + + +#endif /* _ATSC_FS_CHECKER_NAIVE_H_ */ diff --git a/gr-atsc/src/lib/atsci_fs_correlator.cc b/gr-atsc/src/lib/atsci_fs_correlator.cc new file mode 100644 index 00000000..29cf2920 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_correlator.cc @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +// empty constructor +atsci_fs_correlator::atsci_fs_correlator () +{ +} + +// empty virtual destructor +atsci_fs_correlator::~atsci_fs_correlator () +{ +} diff --git a/gr-atsc/src/lib/atsci_fs_correlator.h b/gr-atsc/src/lib/atsci_fs_correlator.h new file mode 100644 index 00000000..80622d9a --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_correlator.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_FS_CORRELATOR_H_ +#define _ATSC_FS_CORRELATOR_H_ + +/*! + * \brief abstract base class for ATSC field sync correlator + * + * Processes input samples one at a time looking for + * an occurence of either the field sync 1 or field sync 2 pattern. + * + * For each sample processed, an output sample and an output tag are produced. + * The output samples are identical to the input samples but are delayed by + * a number of samples given by \p delay(). The output tag associated with + * the the given output sample indicates whether this sample is the beginning + * of one of the field syncs or is an ordinary sample. The tags are defined in + * atsci_sync_tag.h. + * + * For ease of use, the field sync patterns are defined to begin with the + * first symbol of the 4 symbol data segment sync pattern that immediately + * proceeds the actual PN 511 code. This makes it easier for downstream code + * to determine the location of data segment syncs merely by counting. They'll + * occur every 832 samples assuming everything is working. + */ + +class atsci_fs_correlator { + +public: + + // CREATORS + atsci_fs_correlator (); + virtual ~atsci_fs_correlator () = 0; + + // MANIPULATORS + virtual void reset () = 0; + virtual void filter (float input_sample, float *output_sample, float *output_tag) = 0; + + // ACCESSORS + + //! return delay in samples from input to output + virtual int delay () const = 0; +}; + +#endif /* _ATSC_FS_CORRELATOR_H_ */ diff --git a/gr-atsc/src/lib/atsci_fs_correlator_naive.cc b/gr-atsc/src/lib/atsci_fs_correlator_naive.cc new file mode 100644 index 00000000..7c4946bb --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_correlator_naive.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +using std::cerr; +using std::endl; + +static const int PN511_ERROR_LIMIT = 20; // max number of bits wrong +static const int PN63_ERROR_LIMIT = 5; + +unsigned char atsci_fs_correlator_naive::s_511[LENGTH_511]; +unsigned char atsci_fs_correlator_naive::s_63[LENGTH_2ND_63]; + +static void +init_s_511 (unsigned char *p) +{ + *p++ = 1; // data segment sync pattern + *p++ = 0; + *p++ = 0; + *p++ = 1; + + for (int i = 0; i < 511; i++){ + p[i] = atsc_pn511[i]; + } +} + +static void +init_s_63 (unsigned char *p) +{ + for (int i = 0; i < 63; i++){ + p[i] = atsc_pn63[i]; + } +} + +atsci_fs_correlator_naive::atsci_fs_correlator_naive () +{ + init_s_511 (s_511); + init_s_63 (s_63); + reset (); +} + +atsci_fs_correlator_naive::~atsci_fs_correlator_naive () +{ +} + +void +atsci_fs_correlator_naive::reset () +{ + d_index = 0; + memset (d_sample_sr, 0, sizeof (d_sample_sr)); + memset (d_bit_sr, 0, sizeof (d_bit_sr)); +} + +void +atsci_fs_correlator_naive::filter (float input_sample, + float *output_sample, float *output_tag) +{ + // check for a hit on the PN 511 pattern + int errors = 0; + int start = wrap (d_index + OFFSET_511); + + for (int i = 0; i < LENGTH_511 && errors < PN511_ERROR_LIMIT; i++) + errors += d_bit_sr[wrap (start + i)] ^ s_511[i]; + + if (errors >= PN511_ERROR_LIMIT) + *output_tag = atsc_sync_tag::NORMAL; + + else { // 511 pattern is good. determine if this is field 1 or field 2 + errors = 0; + start = wrap (d_index + OFFSET_2ND_63); + for (int i = 0; i < LENGTH_2ND_63; i++) + errors += d_bit_sr[wrap (start + i)] ^ s_63[i]; + + // we should have either field 1 (== PN63) or field 2 (== ~PN63) + if (errors <= PN63_ERROR_LIMIT) + *output_tag = atsc_sync_tag::START_FIELD_SYNC_1; + + else if (errors >= (LENGTH_2ND_63 - PN63_ERROR_LIMIT)) + *output_tag = atsc_sync_tag::START_FIELD_SYNC_2; + + else { + // should be extremely rare. + cerr << "!!! atsci_fs_correlator_naive: PN63 error count = " << errors << endl; + *output_tag = atsc_sync_tag::NORMAL; + } + } + + // return oldest sample + *output_sample = d_sample_sr[d_index]; + + // overwrite with newest sample; + d_sample_sr[d_index] = input_sample; + d_bit_sr[d_index] = input_sample < 0 ? 0 : 1; + d_index = incr (d_index); +} + +int +atsci_fs_correlator_naive::delay () const +{ + return SRSIZE; +} diff --git a/gr-atsc/src/lib/atsci_fs_correlator_naive.h b/gr-atsc/src/lib/atsci_fs_correlator_naive.h new file mode 100644 index 00000000..7f9b5627 --- /dev/null +++ b/gr-atsc/src/lib/atsci_fs_correlator_naive.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_FS_CORRELATOR_NAIVE_H_ +#define _ATSC_FS_CORRELATOR_NAIVE_H_ + +#include + +/*! + * \brief Naive concrete implementation of field sync correlator + */ +class atsci_fs_correlator_naive : public atsci_fs_correlator { + + private: + static const int SRSIZE = 1024; // must be power of two + int d_index; // points at oldest sample + float d_sample_sr[SRSIZE]; // sample shift register + unsigned char d_bit_sr[SRSIZE]; // binary decision shift register + + static const int OFFSET_511 = 0; // offset to PN 511 pattern + static const int LENGTH_511 = 511 + 4; // length of PN 511 pattern (+ 4 seg sync) + static const int OFFSET_2ND_63 = 578; // offset to second PN 63 pattern + static const int LENGTH_2ND_63 = 63; // length of PN 63 pattern + + static unsigned char s_511[LENGTH_511]; // PN 511 pattern + static unsigned char s_63[LENGTH_2ND_63]; // PN 63 pattern + + inline static int wrap (int index){ return index & (SRSIZE - 1); } + inline static int incr (int index){ return wrap (index + 1); } + inline static int decr (int index){ return wrap (index - 1); } + + public: + + // CREATORS + atsci_fs_correlator_naive (); + ~atsci_fs_correlator_naive (); + + // MANIPULATORS + virtual void reset (); + void filter (float input_sample, float *output_sample, float *output_tag); + + // ACCESSORS + + //! return delay in samples from input to output + int delay () const; + +}; + + +#endif /* _ATSC_FS_CORRELATOR_NAIVE_H_ */ diff --git a/gr-atsc/src/lib/atsci_pnXXX.cc b/gr-atsc/src/lib/atsci_pnXXX.cc new file mode 100644 index 00000000..efa61e00 --- /dev/null +++ b/gr-atsc/src/lib/atsci_pnXXX.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +const unsigned char atsc_pn511[511] = { + 0,0,0,0, 0,0,0,1, 0,1,1,1, 1,1,1,1, 1,1,0,0, 1,0,1,0, 1,0,1,0, 1,1,1,0, + 0,1,1,0, 0,1,1,0, 1,0,0,0, 1,0,0,0, 1,0,0,1, 1,1,1,0, 0,0,0,1, 1,1,0,1, + + 0,1,1,1, 1,1,0,1, 0,0,1,1, 0,1,0,1, 0,0,1,1, 1,0,1,1, 0,0,1,1, 1,0,1,0, + 0,1,0,0, 0,1,0,1, 1,0,0,0, 1,1,1,1, 0,0,1,0, 0,0,0,1, 0,1,0,0, 0,1,1,1, + + 1,1,0,0, 1,1,1,1, 0,1,0,1, 0,0,0,1, 0,1,0,0, 1,1,0,0, 0,0,1,1, 0,0,0,1, + 0,0,0,0, 0,1,0,0, 0,0,1,1, 1,1,1,1, 0,0,0,0, 0,1,0,1, 0,1,0,0, 0,0,0,0, + + 1,1,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,1,0, 1,0,0,1, 0,1,1,0, 0,1,1,0, + 0,0,1,1, 0,1,1,1, 0,1,1,1, 1,0,1,1, 0,1,0,0, 1,0,1,0, 0,1,0,0, 1,1,1,0, + + 0,1,1,1, 0,0,0,1, 0,1,1,1, 0,1,0,0, 0,0,1,1, 0,1,0,0, 1,1,1,1, 1,0,1,1, + 0,0,0,1, 0,1,0,1, 1,0,1,1, 1,1,0,0, 1,1,0,1, 1,0,1,0, 1,1,1,0, 1,1,0,1, + + 1,0,0,1, 0,1,1,0, 1,1,0,1, 1,1,0,0, 1,0,0,1, 0,0,1,0, 1,1,1,0, 0,0,1,1, + 1,0,0,1, 0,1,1,1, 1,0,1,0, 0,0,1,1, 0,1,0,1, 1,0,0,0, 0,1,0,0, 1,1,0,1, + + 1,1,1,1, 0,0,0,1, 0,0,1,0, 1,0,1,1, 1,1,0,0, 0,1,1,0, 0,1,0,1, 0,0,0,0, + 1,0,0,0, 1,1,0,0, 0,0,0,1, 1,1,1,0, 1,1,1,1, 1,1,0,1, 0,1,1,0, 1,0,1,0, + + 1,1,0,0, 1,0,0,1, 1,0,0,1, 0,0,0,1, 1,1,0,1, 1,1,0,0, 0,0,1,0, 1,1,0,1, + 0,0,0,0, 0,1,1,0, 1,1,0,0, 0,0,0,0, 1,0,0,1, 0,0,0,0, 0,0,0,1, 1,1,0 +}; + +const unsigned char atsc_pn63[63] = { + 1,1,1,0, 0,1,0,0, 1,0,1,1, 0,1,1,1, 0,1,1,0, 0,1,1,0, 1,0,1,0, 1,1,1,1, + 1,1,0,0, 0,0,0,1, 0,0,0,0, 1,1,0,0, 0,1,0,1, 0,0,1,1, 1,1,0,1, 0,0,0 +}; + diff --git a/gr-atsc/src/lib/atsci_pnXXX.h b/gr-atsc/src/lib/atsci_pnXXX.h new file mode 100644 index 00000000..1cb9b1b8 --- /dev/null +++ b/gr-atsc/src/lib/atsci_pnXXX.h @@ -0,0 +1,24 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +extern const unsigned char atsc_pn511[]; +extern const unsigned char atsc_pn63[]; diff --git a/gr-atsc/src/lib/atsci_randomizer.cc b/gr-atsc/src/lib/atsci_randomizer.cc new file mode 100644 index 00000000..5cdcaa89 --- /dev/null +++ b/gr-atsc/src/lib/atsci_randomizer.cc @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +unsigned char atsci_randomizer::s_output_map[1 << 14]; +bool atsci_randomizer::s_output_map_initialized_p = false; + +atsci_randomizer::atsci_randomizer () +{ + d_state = PRELOAD_VALUE; + + if (!s_output_map_initialized_p) + initialize_output_map (); +} + +/*! + * \brief Generate the table used in the fast_output_map function. + * + * The table has 16K byte entries, but because of how is is used, only + * 256 entries end up being resident in the cache. This seems + * like a good use of memory. We can get away with a 16K table + * because the low two bits of the state do not affect the output + * function. By shifting right those two bits we shrink the table, + * and also get better cache line utilization. + */ +void +atsci_randomizer::initialize_output_map () +{ + s_output_map_initialized_p = true; + + for (int i = 0; i < (1 << 14); i++) + s_output_map[i] = slow_output_map (i << 2); +} + + +void +atsci_randomizer::reset () +{ + d_state = PRELOAD_VALUE; +} + +void +atsci_randomizer::randomize (atsc_mpeg_packet_no_sync &out, const atsc_mpeg_packet &in) +{ + assert (in.data[0] == MPEG_SYNC_BYTE); // confirm it's there, then drop + + for (int i = 0; i < ATSC_MPEG_DATA_LENGTH; i++) + out.data[i] = in.data[i + 1] ^ output_and_clk (); +} + +void +atsci_randomizer::derandomize (atsc_mpeg_packet &out, const atsc_mpeg_packet_no_sync &in) +{ + out.data[0] = MPEG_SYNC_BYTE; // add sync byte to beginning of packet + + for (int i = 0; i < ATSC_MPEG_DATA_LENGTH; i++) + out.data[i + 1] = in.data[i] ^ output_and_clk (); +} + + +unsigned char +atsci_randomizer::slow_output_map (int st) +{ + int output = 0; + + if (st & 0x8000) + output |= 0x01; + + if (st & 0x2000) + output |= 0x02; + + if (st & 0x1000) + output |= 0x04; + + if (st & 0x0200) + output |= 0x08; + + if (st & 0x0020) + output |= 0x10; + + if (st & 0x0010) + output |= 0x20; + + if (st & 0x0008) + output |= 0x40; + + if (st & 0x0004) + output |= 0x80; + + return output; +} diff --git a/gr-atsc/src/lib/atsci_randomizer.h b/gr-atsc/src/lib/atsci_randomizer.h new file mode 100644 index 00000000..c9f3b66e --- /dev/null +++ b/gr-atsc/src/lib/atsci_randomizer.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_RANDOMIZER_H_ +#define _ATSC_RANDOMIZER_H_ + +#include + +/*! + * \brief ATSC data "whitener" + * + * The data randomizer described in ATSC standard A/53B. + * See figure D4 on page 54. + */ + +class atsci_randomizer { + friend class qa_atsci_randomizer; + + public: + atsci_randomizer(); + + /*! \brief reset randomizer LFSR + * + * must be called during the Data Segment Sync interval prior to the + * first data segment. I.e., the LFSR is reset prior to the first + * field of each VSB data frame. + */ + void reset (); + + //! randomize (whiten) mpeg packet and remove leading MPEG-2 sync byte + void randomize (atsc_mpeg_packet_no_sync &out, const atsc_mpeg_packet &in); + + //! derandomize (de-whiten) mpeg packet and add leading MPEG-2 sync byte + void derandomize (atsc_mpeg_packet &out, const atsc_mpeg_packet_no_sync &in); + + unsigned int state() const { return d_state; } + + private: + static void initialize_output_map (); + static unsigned char slow_output_map (int st); + + static unsigned char fast_output_map (int st){ + return s_output_map[(st & 0xb23c) >> 2]; // Magic const with 8 bits set improves cache + // utilization. The bits correspond to the taps + // used in output calculation. Others may be + // safely ignored. + } + + //! return current output value + unsigned char output (){ + return fast_output_map (d_state); + } + + //! clock LFSR; advance to next state. + void clk (){ + if (d_state & 0x1) + d_state = ((d_state ^ MASK) >> 1) | 0x8000; + else + d_state = d_state >> 1; + } + + //! return current output value and advance to next state + unsigned char output_and_clk (){ + unsigned char r = output (); + clk (); + return r; + } + + unsigned int d_state; + + static const unsigned int PRELOAD_VALUE = 0x018f; /* 0xf180 bit reversed */ + static const unsigned int MASK = 0xa638; + static unsigned char s_output_map[1 << 14]; + static bool s_output_map_initialized_p; +}; + +#endif /* _ATSC_RANDOMIZER_H_ */ diff --git a/gr-atsc/src/lib/atsci_reed_solomon.cc b/gr-atsc/src/lib/atsci_reed_solomon.cc new file mode 100644 index 00000000..26265d35 --- /dev/null +++ b/gr-atsc/src/lib/atsci_reed_solomon.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +extern "C" { +#include "rs.h" +} + +static const int rs_init_symsize = 8; +static const int rs_init_gfpoly = 0x11d; +static const int rs_init_fcr = 0; // first consecutive root +static const int rs_init_prim = 1; // primitive is 1 (alpha) +static const int rs_init_nroots = 20; + +static const int N = (1 << rs_init_symsize) - 1; // 255 +static const int K = N - rs_init_nroots; // 235 + +static const int amount_of_pad = N - ATSC_MPEG_RS_ENCODED_LENGTH; // 48 + +atsci_reed_solomon::atsci_reed_solomon () +{ + d_rs = init_rs_char (rs_init_symsize, rs_init_gfpoly, + rs_init_fcr, rs_init_prim, rs_init_nroots); + + assert (d_rs != 0); +} + +atsci_reed_solomon::~atsci_reed_solomon () +{ + if (d_rs) + free_rs_char (d_rs); + d_rs = 0; +} + +void +atsci_reed_solomon::encode (atsc_mpeg_packet_rs_encoded &out, const atsc_mpeg_packet_no_sync &in) +{ + unsigned char tmp[K]; + + assert ((int)(amount_of_pad + sizeof (in.data)) == K); + + // add missing prefix zero padding to message + memset (tmp, 0, amount_of_pad); + memcpy (&tmp[amount_of_pad], in.data, sizeof (in.data)); + + // copy message portion to output packet + memcpy (out.data, in.data, sizeof (in.data)); + + // now compute parity bytes and add them to tail end of output packet + encode_rs_char (d_rs, tmp, &out.data[sizeof (in.data)]); +} + +int +atsci_reed_solomon::decode (atsc_mpeg_packet_no_sync &out, const atsc_mpeg_packet_rs_encoded &in) +{ + unsigned char tmp[N]; + int ncorrections; + + assert ((int)(amount_of_pad + sizeof (in.data)) == N); + + // add missing prefix zero padding to message + memset (tmp, 0, amount_of_pad); + memcpy (&tmp[amount_of_pad], in.data, sizeof (in.data)); + + // correct message... + ncorrections = decode_rs_char (d_rs, tmp, 0, 0); + + // copy corrected message to output, skipping prefix zero padding + memcpy (out.data, &tmp[amount_of_pad], sizeof (out.data)); + + return ncorrections; +} diff --git a/gr-atsc/src/lib/atsci_reed_solomon.h b/gr-atsc/src/lib/atsci_reed_solomon.h new file mode 100644 index 00000000..882741f0 --- /dev/null +++ b/gr-atsc/src/lib/atsci_reed_solomon.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_REED_SOLOMON_H_ +#define _ATSC_REED_SOLOMON_H_ + +#include + +/*! + * \brief ATSC Reed-Solomon encoder / decoder + * + * The t=10 (207,187) code described in ATSC standard A/53B. + * See figure D5 on page 55. + */ + +class atsci_reed_solomon { + + public: + atsci_reed_solomon(); + ~atsci_reed_solomon(); + + /*! + * \brief Add RS error correction encoding + */ + void encode (atsc_mpeg_packet_rs_encoded &out, const atsc_mpeg_packet_no_sync &in); + + /*! + * Decode RS encoded packet. + * \returns a count of corrected symbols, or -1 if the block was uncorrectible. + */ + int decode (atsc_mpeg_packet_no_sync &out, const atsc_mpeg_packet_rs_encoded &in); + + private: + void *d_rs; +}; + +#endif /* _ATSC_REED_SOLOMON_H_ */ diff --git a/gr-atsc/src/lib/atsci_root_raised_cosine.cc b/gr-atsc/src/lib/atsci_root_raised_cosine.cc new file mode 100644 index 00000000..00912ad5 --- /dev/null +++ b/gr-atsc/src/lib/atsci_root_raised_cosine.cc @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +vector +atsc_root_raised_cosine::taps (double sampling_rate) +{ + static const double symbol_rate = ATSC_SYMBOL_RATE/2; // 1/2 as wide because we're designing lp filter + // static const int NTAPS = 93; // good number + // static const int NTAPS = 745; // better number + static const int NTAPS = 279; // better number + + return gr_firdes::root_raised_cosine (1.0, sampling_rate, symbol_rate, .115, NTAPS); +} diff --git a/gr-atsc/src/lib/atsci_root_raised_cosine.h b/gr-atsc/src/lib/atsci_root_raised_cosine.h new file mode 100644 index 00000000..c3f0a9ea --- /dev/null +++ b/gr-atsc/src/lib/atsci_root_raised_cosine.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_RRC_H_ +#define _ATSC_RRC_H_ + +#include + +class atsc_root_raised_cosine : public gr_fir_builder +{ +public: + virtual std::vector taps (double sampling_freq); +}; + + +#endif /* _ATSC_RRC_H_ */ diff --git a/gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.cc b/gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.cc new file mode 100644 index 00000000..fbdc4caa --- /dev/null +++ b/gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.cc @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +using std::vector; +using std::cerr; +using std::endl; + + +vector +atsc_root_raised_cosine_bandpass::taps (double sampling_freq) +{ + + vector t = atsc_root_raised_cosine::taps (sampling_freq); + + cerr << "atsc_root_raised_cosine_bandpass::taps -- " << t.size () << endl; + + // heterodyne the low pass coefficients up to the specified bandpass + // center frequency. Note that when we do this, the filter bandwidth + // is effectively twice the low pass (2.69 * 2 = 5.38) and hence + // matches the diagram in the ATSC spec. + + double arg = 2 * M_PI * _center_freq / sampling_freq; + for (unsigned int i = 0; i < t.size (); i++) + // the factor of 2 keeps the gain of the passband normalized to 1 + t[i] *= 2 * cos (arg * (double) i); + + return t; +} diff --git a/gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.h b/gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.h new file mode 100644 index 00000000..5de2475f --- /dev/null +++ b/gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_RRC_BANDPASS_H_ +#define _ATSC_RRC_BANDPASS_H_ + +#include + +class atsc_root_raised_cosine_bandpass : public atsc_root_raised_cosine +{ +public: + atsc_root_raised_cosine_bandpass (double center_freq) : _center_freq (center_freq) {} + virtual std::vector taps (double sampling_freq); + +protected: + double _center_freq; +}; + + +#endif /* _ATSC_RRC_BANDPASS_H_ */ diff --git a/gr-atsc/src/lib/atsci_single_viterbi.cc b/gr-atsc/src/lib/atsci_single_viterbi.cc new file mode 100644 index 00000000..edc2cd13 --- /dev/null +++ b/gr-atsc/src/lib/atsci_single_viterbi.cc @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +using std::cerr; +using std::cout; + +const float atsci_single_viterbi::was_sent[32] = { + -7,-3,-7,-3,-7,-3,-7,-3, + -5,-1,-5,-1,-5,-1,-5,-1, + 1,5,1,5,1,5,1,5, + 3,7,3,7,3,7,3,7 +}; + +const int atsci_single_viterbi::transition_table[32] = { + 0,2,4,6, + 2,0,6,4, + 1,3,5,7, + 3,1,7,5, + 4,6,0,2, + 6,4,2,0, + 5,7,1,3, + 7,5,3,1 +}; + +void +atsci_single_viterbi::reset() +{ + for (unsigned int i = 0; i<2; i++) + for (unsigned int j = 0; j<8; j++) { + path_metrics[i][j] = 0; + traceback[i][j] = 0; + } + phase = 0; +} + +atsci_single_viterbi::atsci_single_viterbi() +{ + reset(); +} + +char +atsci_single_viterbi::decode(float input) +{ + for (unsigned int next_state = 0; next_state < 8; next_state++) { + unsigned int index = next_state << 2; + int min_metric_symb = 0; + float min_metric = fabs(input - was_sent[index + 0]) + + path_metrics[phase][transition_table[index + 0]]; + + for (unsigned int symbol_sent = 1; symbol_sent < 4; symbol_sent++) + if( (fabs(input-was_sent[index+symbol_sent]) + + path_metrics[phase][transition_table[index+symbol_sent]]) + < min_metric) { + min_metric = fabs(input-was_sent[index+symbol_sent]) + + path_metrics[phase][transition_table[index+symbol_sent]]; + min_metric_symb = symbol_sent; + } + + path_metrics[phase^1][next_state] = min_metric; + traceback[phase^1][next_state] = (((unsigned long long)min_metric_symb) << 62) | + (traceback[phase][transition_table[index+min_metric_symb]] >> 2); + } + unsigned int best_state = 0; + float best_state_metric = path_metrics[phase^1][0]; + for (unsigned int state = 1; state < 8; state++) + if(path_metrics[phase^1][state] < best_state_metric) { + best_state = state; + best_state_metric = path_metrics[phase^1][state]; + } + if(best_state_metric > 10000) { + for(unsigned int state = 0; state < 8; state++) + path_metrics[phase^1][state] -= best_state_metric; + // cerr << "Resetting Path Metrics from " << best_state_metric << " to 0\n"; + } + phase ^= 1; + return (0x3 & traceback[phase][best_state]); +} diff --git a/gr-atsc/src/lib/atsci_single_viterbi.h b/gr-atsc/src/lib/atsci_single_viterbi.h new file mode 100644 index 00000000..907b41c9 --- /dev/null +++ b/gr-atsc/src/lib/atsci_single_viterbi.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSCSINGLEVITERBI_H_ +#define _ATSCSINGLEVITERBI_H_ + +/*! + * \brief single channel viterbi decoder + */ +class atsci_single_viterbi +{ + +public: + atsci_single_viterbi (); + + static const unsigned int TB_LEN = 32; + + /*! + * \p INPUT ideally takes on the values +/- 1,3,5,7 + * return is decoded dibit in the range [0, 3] + */ + char decode (float input); + + void reset (); + + //! internal delay of decoder + int delay () { return TB_LEN - 1; } + +protected: + static const int transition_table[32]; + static const float was_sent[32]; + float path_metrics [2][8]; + unsigned long long traceback [2][8]; + unsigned char phase; +}; + +#endif diff --git a/gr-atsc/src/lib/atsci_slicer_agc.h b/gr-atsc/src/lib/atsci_slicer_agc.h new file mode 100644 index 00000000..f1244bd0 --- /dev/null +++ b/gr-atsc/src/lib/atsci_slicer_agc.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_SLICER_AGC_H_ +#define _ATSC_SLICER_AGC_H_ + +#include +#include + +/*! + * \brief Automatic Gain Control class for atsc slicer + * + * Given perfect data, output values will be +/- {7, 5, 3, 1} + */ + +class atsci_slicer_agc { + + public: + atsci_slicer_agc () : _gain(1), dc(0.0025) {}; + + + float gain () { return _gain; } + +#if 1 + float scale (float input){ + float t = input * _gain; + float output = t - REFERENCE; + float error = REFERENCE - dc.filter (t); + _gain += error * RATE; + return output; + } +#else + float scale(float input){ + float avg = dc.filter(input); + if(fabs(avg)<.1)avg=.1; + _gain += _gain*.99 + .01* REFERENCE/avg; + return input*_gain - REFERENCE; + } +#endif + + protected: + + static const float REFERENCE = 1.25; // pilot reference value + static const float RATE = 1.0e-5; // adjustment rate + float _gain; // current gain + gr_single_pole_iir dc; +}; + +#endif /* _ATSC_SLICER_AGC_H_ */ diff --git a/gr-atsc/src/lib/atsci_sliding_correlator.cc b/gr-atsc/src/lib/atsci_sliding_correlator.cc new file mode 100644 index 00000000..dc821db5 --- /dev/null +++ b/gr-atsc/src/lib/atsci_sliding_correlator.cc @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +// #define TRY_BACKWARDS + +/* + * Return the number of 1's in v. + * This magic code is explained wonderfully in the AMD Athlon + * optimization guide, pg 136. + */ +static inline int popcount32 (unsigned long v) +{ + unsigned long w = v - ((v >> 1) & 0x55555555); + unsigned long x = (w & 0x33333333) + ((w >> 2) & 0x33333333); + unsigned long y = (x + (x >> 4)) & 0x0f0f0f0f; + unsigned long z = (y * 0x01010101) >> 24; + + return z; +} + +atsci_sliding_correlator::atsci_sliding_correlator () +{ +#if defined(TRY_BACKWARDS) + for (int i = 511 - 1; i >= 0; i--) + mask.shift_in (atsc_pn511[i]); +#else + for (unsigned i = 0; i < 511; i++) + mask.shift_in (atsc_pn511[i]); +#endif + + and_mask.shift_in (0); + for (int i = 0; i < 511; i++) + and_mask.shift_in (1); +} + +/* + * we shift in from the top of the register towards the bottom + * + * +-- bits enter here... + * | + * v + * block 0 | block 1 | block 2 ... | block N-1 + * | + * +--> ... and drop out here + * + */ +inline void +atsci_sliding_correlator::shift_reg::shift_in (int bit) +{ + for (int i = NSRBLOCKS - 1; i > 0; i--) + d[i] = ((d[i-1] & 0x1) << (srblock_bitsize - 1)) | (d[i] >> 1); + + d[0] = (((srblock) bit) << (srblock_bitsize - 1)) | (d[0] >> 1); +} + +int +atsci_sliding_correlator::input_bit (int bit) +{ + input.shift_in (bit); + + // can probably get a win by unrolling the loop, if we need to. + int count = 0; + for (int i = 0; i < NSRBLOCKS; i++) + count += popcount32 ((input.d[i] ^ mask.d[i]) & and_mask.d[i]); + + return count; +} + diff --git a/gr-atsc/src/lib/atsci_sliding_correlator.h b/gr-atsc/src/lib/atsci_sliding_correlator.h new file mode 100644 index 00000000..9bb14db9 --- /dev/null +++ b/gr-atsc/src/lib/atsci_sliding_correlator.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_SLIDING_CORRELATOR_H_ +#define _ATSC_SLIDING_CORRELATOR_H_ + +#include + +extern const unsigned char atsc_pn511[511]; +extern const unsigned char atsc_pn63[63]; + +/*! + * \brief look for the PN 511 field sync pattern + */ +class atsci_sliding_correlator { + public: + + atsci_sliding_correlator (); + ~atsci_sliding_correlator (){}; + + //! input hard decision bit, return correlation (0,511) + // Result is the number of wrong bits. + // E.g., 0 -> perfect match; 511 -> all bits are wrong + + int input_bit (int bit); + + //! input sample, return correlation (0,511) + // Result is the number of wrong bits. + // E.g., 0 -> perfect match; 511 -> all bits are wrong + + int input_int (int sample){ + return input_bit (sample < 0 ? 0 : 1); + } + + //! input sample, return correlation (0,511) + // Result is the number of wrong bits. + // E.g., 0 -> perfect match; 511 -> all bits are wrong + + int input_float (float sample){ + return input_bit (sample < 0 ? 0 : 1); + } + + void reset () { input.reset (); } + + private: + + typedef unsigned long srblock; + static const int bits_per_char = 8; + static const int srblock_bitsize = sizeof (srblock) * bits_per_char; + static const int NSRBLOCKS = (511 + srblock_bitsize - 1) / srblock_bitsize; + + class shift_reg { + public: + shift_reg () { reset (); } + void reset () { memset (d, 0, sizeof (d)); } + void shift_in (int bit); + srblock d[NSRBLOCKS]; + }; + + shift_reg mask; // pattern we're looking for + shift_reg input; // current input window + shift_reg and_mask; // bits to consider +}; + +#endif /* _ATSC_SLIDING_CORRELATOR_H_ */ diff --git a/gr-atsc/src/lib/atsci_sssr.cc b/gr-atsc/src/lib/atsci_sssr.cc new file mode 100644 index 00000000..7790c656 --- /dev/null +++ b/gr-atsc/src/lib/atsci_sssr.cc @@ -0,0 +1,286 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * ---------------------------------------------------------------- + * Segment Integrator Pre-Processor + * + * Compute weight passed to integrator based on + * correlation result and ncorr_gain2 + */ + +inline static int +sipp (bool digcorr_output) +{ + if (digcorr_output) + return +2; // positive correlation + else + return -1; // no correlation +} + +/* + * ---------------------------------------------------------------- + * Segment Sync Integrator... + */ + +static const int SSI_MIN = -16; +static const int SSI_MAX = 15; + +void +sssr::seg_sync_integrator::reset () +{ + for (int i = 0; i < ATSC_DATA_SEGMENT_LENGTH; i++) + d_integrator[i] = SSI_MIN; +} + +int +sssr::seg_sync_integrator::update (int weight, int index) +{ + int t = d_integrator[index] + weight; + t = std::max (t, SSI_MIN); + t = std::min (t, SSI_MAX); + d_integrator[index] = t; + + return t; +} + +int +sssr::seg_sync_integrator::find_max (int *v) +{ + int best_value = d_integrator[0]; + int best_index = 0; + + for (int i = 1; i < ATSC_DATA_SEGMENT_LENGTH; i++) + if (d_integrator[i] > best_value){ + best_value = d_integrator[i]; + best_index = i; + } + + *v = best_value; + return best_index; +} + +/* + * ---------------------------------------------------------------- + * Segment Sync and Symbol recovery + */ + +static const int SYMBOL_INDEX_OFFSET = 3; +static const int MIN_SEG_LOCK_CORRELATION_VALUE = 5; + +atsci_sssr::atsci_sssr () +{ + reset (); + + if (_SSSR_DIAG_OUTPUT_){ + const char *file = "sssr.ssout"; + if ((d_debug_fp = fopen (file, "wb")) == 0){ + perror (file); + exit (1); + } + } +} + +atsci_sssr::~atsci_sssr () +{ + if (d_debug_fp) + fclose (d_debug_fp); +} + +void +atsci_sssr::reset () +{ + d_correlator.reset (); + d_integrator.reset (); + d_quad_filter.reset (); + + for (int i = 0; i < ATSC_DATA_SEGMENT_LENGTH; i++) + d_quad_output[i] = 0; + + d_timing_adjust = 0; + d_counter = 0; + d_symbol_index = 0; + d_seg_locked = false; +} + +void +atsci_sssr::update (sssr::sample_t sample_in, // input + bool *seg_locked, // are we seeing segment syncs? + int *symbol_index, // 0..831 + double *timing_adjust) // how much to adjust timing +{ + double qo = d_quad_filter.update (sample_in); + d_quad_output[d_counter] = qo; + + int bit = gr_signbit (sample_in) ^ 1; // slice on sign: + => 1, - => 0 + int corr_out = d_correlator.update (bit); + int weight = sipp (corr_out); + int corr_value = d_integrator.update (weight, d_counter); + int best_correlation_index = -1; + + incr_symbol_index (); + if (incr_counter ()){ // counter just wrapped... + int best_correlation_value; + best_correlation_index = d_integrator.find_max (&best_correlation_value); + d_seg_locked = best_correlation_value >= MIN_SEG_LOCK_CORRELATION_VALUE; + d_timing_adjust = d_quad_output[best_correlation_index]; + + d_symbol_index = SYMBOL_INDEX_OFFSET - 1 - best_correlation_index; + if (d_symbol_index < 0) + d_symbol_index += ATSC_DATA_SEGMENT_LENGTH; + } + + *seg_locked = d_seg_locked; + *symbol_index = d_symbol_index; + *timing_adjust = d_timing_adjust; + + if (_SSSR_DIAG_OUTPUT_){ + float iodata[7]; + iodata[0] = bit; + iodata[1] = corr_value; + iodata[2] = qo; + iodata[3] = d_counter; + iodata[4] = d_symbol_index; + iodata[5] = best_correlation_index; + iodata[6] = d_timing_adjust; + + if (fwrite (iodata, sizeof (iodata), 1, d_debug_fp) != 1){ + perror ("fwrite: sssr"); + exit (1); + } + } + +} + +/* + * ---------------------------------------------------------------- + * Interpolator control for Seg & Symbol Sync Recovery + */ + +static const double LOOP_FILTER_TAP = 0.00025; // 0.0005 works +static const double ADJUSTMENT_GAIN = 1.0e-5 / (10 * ATSC_DATA_SEGMENT_LENGTH); + +atsci_interpolator::atsci_interpolator (double nominal_ratio_of_rx_clock_to_symbol_freq) +{ + assert (nominal_ratio_of_rx_clock_to_symbol_freq >= 1.8); + d_nominal_ratio_of_rx_clock_to_symbol_freq = + nominal_ratio_of_rx_clock_to_symbol_freq; + + d_loop.set_taps (LOOP_FILTER_TAP); + + reset (); + + if (_SSSR_DIAG_OUTPUT_){ + const char *file = "interp.ssout"; + if ((d_debug_fp = fopen (file, "wb")) == 0){ + perror (file); + exit (1); + } + } + +} + +atsci_interpolator::~atsci_interpolator () +{ + if (d_debug_fp) + fclose (d_debug_fp); +} + +void +atsci_interpolator::reset () +{ + d_w = d_nominal_ratio_of_rx_clock_to_symbol_freq; + d_mu = 0.5; + d_incr = 0; + d_loop.reset (); +} + +bool +atsci_interpolator::update ( + const sssr::sample_t input_samples[], // I: vector of samples + int nsamples, // I: total number of samples + int *index, // I/O: current input index + double timing_adjustment, // I: how much to bump timing + sssr::sample_t *output_sample) +{ + if (*index + (int) ntaps () > nsamples) + return false; + + // FIXME Confirm that this is right. I think it is. It was (1-d_mu) + *output_sample = d_interp.interpolate (&input_samples[*index], d_mu); + + double filter_out = 0; + +#if 0 + + filter_out = d_loop.filter (timing_adjustment); + d_w = d_w + ADJUSTMENT_GAIN * filter_out * 1e-3; + +#elif 1 + + filter_out = d_loop.filter (timing_adjustment); + d_mu = d_mu + ADJUSTMENT_GAIN * 10e3 * filter_out; + +#else + + static const double alpha = 0.01; + static const double beta = alpha * alpha / 16; + + double x = ADJUSTMENT_GAIN * 10e3 * timing_adjustment; + + d_mu = d_mu + alpha * x; // conceptually "phase" + d_w = d_w + beta * x; // conceptually "frequency" + +#endif + + double s = d_mu + d_w; + double float_incr = floor (s); + d_mu = s - float_incr; + d_incr = (int) float_incr; + + assert (d_incr >= 1 && d_incr <= 3); + *index += d_incr; + + if (_SSSR_DIAG_OUTPUT_){ + float iodata[6]; + iodata[0] = timing_adjustment; + iodata[1] = filter_out; + iodata[2] = d_w; + iodata[3] = d_mu; + iodata[4] = d_incr; + iodata[5] = *output_sample; + if (fwrite (iodata, sizeof (iodata), 1, d_debug_fp) != 1){ + perror ("fwrite: interpolate"); + exit (1); + } + } + + return true; +} diff --git a/gr-atsc/src/lib/atsci_sssr.h b/gr-atsc/src/lib/atsci_sssr.h new file mode 100644 index 00000000..0d575cd8 --- /dev/null +++ b/gr-atsc/src/lib/atsci_sssr.h @@ -0,0 +1,240 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * --- ATSC Segment and Symbol Sync Recovery --- + */ + +#ifndef _ATSC_SSSR_H_ +#define _ATSC_SSSR_H_ + +#include +#include +#include +#include + +/* + * --- support classes for atsci_sssr --- + */ + +namespace sssr { + + typedef float sample_t; + + // ---------------------------------------------------------------- + //! digital correlator for 1001 and 0110 patterns + + class digital_correlator { + int d_sr; // 4 bit shift register + + public: + + // Constructor + digital_correlator () { reset (); } + + // Manipulators + + //! called on channel change + void reset () { d_sr = 0; } + + //! clock bit in and return true if we've seen 1001 + + bool update (int bit) { + d_sr = ((bit & 1) << 3) | (d_sr >> 1); + + return (d_sr == 0x9); // 1001 + } + + }; + + + // ---------------------------------------------------------------- + //! segment sync integrator + + class seg_sync_integrator { + signed char d_integrator[ATSC_DATA_SEGMENT_LENGTH]; + + public: + + // Constructor + seg_sync_integrator () { reset (); } + + // Manipulators + + //! called on channel change + void reset (); + + //! update current tap with weight and return integrated correlation value + int update (int weight, int index); + + //! return index of maximum correlation value + int find_max (int *value); + + }; + + // ---------------------------------------------------------------- + //! quad filter (used to compute timing error) + + class quad_filter { + sample_t d_delay[4]; + + public: + // Constructor + quad_filter () { reset (); } + + // Manipulators + + //! called on channel change + void reset () { d_delay[0] = d_delay[1] = d_delay[2] = d_delay[3] = 0; } + + double update (sample_t sample){ + d_delay[3] = d_delay[2]; + d_delay[2] = d_delay[1]; + d_delay[1] = d_delay[0]; + d_delay[0] = sample; + + // the coefficients are -1,-1,+1,+1 + return d_delay[3] + d_delay[2] - d_delay[1] - d_delay[0]; + } + }; +} + +// ---------------------------------------------------------------- + +/*! + * \brief ATSC Segment and Symbol Sync Recovery + * + * This class implements data segment sync tracking and symbol timing + * using the method described in "ATSC/VSB Tutorial - Receiver Technology" + * by Wayne E. Bretl of Zenith, pgs 41-45. + */ + +class atsci_sssr { + sssr::digital_correlator d_correlator; + sssr::seg_sync_integrator d_integrator; + sssr::quad_filter d_quad_filter; + double d_quad_output[ATSC_DATA_SEGMENT_LENGTH]; + double d_timing_adjust; + int d_counter; // free running mod 832 counter + int d_symbol_index; + bool d_seg_locked; + FILE *d_debug_fp; + + + bool incr_counter () { + d_counter++; + if (d_counter >= ATSC_DATA_SEGMENT_LENGTH){ + d_counter = 0; + return true; + } + return false; + } + + void incr_symbol_index () { + d_symbol_index++; + if (d_symbol_index >= ATSC_DATA_SEGMENT_LENGTH) + d_symbol_index = 0; + } + +public: + + // Constructor + atsci_sssr (); + ~atsci_sssr (); + + // Manipulators + + //! call on channel change + void reset (); + + + /*! + * \brief process a single sample at the ATSC symbol rate (~10.76 MSPS) + * + * This block computes an indication of our timing error and keeps + * track of where the segment sync's occur. \p timing_adjust is + * returned to indicate how the interpolator timing needs to be + * adjusted to track the transmitter's symbol timing. If \p seg_locked + * is true, then \p symbol_index is the index of this sample in + * the current segment. The symbols are numbered from 0 to 831, where + * symbols 0, 1, 2 and 3 correspond to the data segment sync pattern, + * nominally +5, -5, -5, +5. + */ + + void update (sssr::sample_t sample_in, // input + bool *seg_locked, // are we seeing segment syncs? + int *symbol_index, // 0..831 + double *timing_adjust); // how much to adjust timing + +}; + +// ---------------------------------------------------------------- + +/*! + * \brief interpolator control for segment and symbol sync recovery + */ + +class atsci_interpolator { + gri_mmse_fir_interpolator d_interp; + gr_single_pole_iir d_loop; // ``VCO'' loop filter + double d_nominal_ratio_of_rx_clock_to_symbol_freq; // FREQ + double d_w; // ratio of PERIOD of Tx to Rx clocks + double d_mu; // fractional delay [0,1] + int d_incr; // diagnostic only + FILE *d_debug_fp; // diagnostic only + +public: + //! \p nominal_ratio_of_rx_clock_to_symbol_freq must be >= 1.8 + atsci_interpolator (double nominal_ratio_of_rx_clock_to_symbol_freq); + ~atsci_interpolator (); + + // Manipulators + + //! call on channel change + void reset (); + + /*! + * \brief produce next sample referenced to Tx clock + * + * If there aren't enough input_samples left to produce + * an output, return false, else true. + */ + + bool update (const sssr::sample_t input_samples[], // I: vector of samples + int nsamples, // I: total number of samples + int *index, // I/O: current input index + double timing_adjustment, // I: how much to bump timing + sssr::sample_t *output_sample); // O: the output sample + + // Accessors + + // how much history we require on our input + unsigned ntaps () const { return d_interp.ntaps (); } + + // diagnostic accessors + double mu () const { return d_mu; } + double w () const { return d_w; } + int incr () const { return d_incr; } + +}; + +#endif /* _ATSC_SSSR_H_ */ diff --git a/gr-atsc/src/lib/atsci_syminfo.h b/gr-atsc/src/lib/atsci_syminfo.h new file mode 100644 index 00000000..8d421181 --- /dev/null +++ b/gr-atsc/src/lib/atsci_syminfo.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_SYMINFO_H_ +#define _ATSC_SYMINFO_H_ + +namespace atsc { + + static const unsigned int SI_SEGMENT_NUM_MASK = 0x1ff; + static const unsigned int SI_FIELD_SYNC_SEGMENT_NUM = SI_SEGMENT_NUM_MASK; // conceptually -1 + + struct syminfo { + unsigned int symbol_num : 10; // 0..831 + unsigned int segment_num : 9; // 0..311 and SI_FIELD_SYNC_SEGMENT_NUM + unsigned int field_num : 1; // 0..1 + unsigned int valid : 1; // contents are valid + }; + + + static inline bool + tag_is_start_field_sync (syminfo tag) + { + return tag.symbol_num == 0 && tag.segment_num == SI_FIELD_SYNC_SEGMENT_NUM && tag.valid; + } + + static inline bool + tag_is_start_field_sync_1 (syminfo tag) + { + return tag_is_start_field_sync (tag) && tag.field_num == 0; + } + + static inline bool + tag_is_start_field_sync_2 (syminfo tag) + { + return tag_is_start_field_sync (tag) && tag.field_num == 1; + } + +} + +#endif /* _ATSC_SYMINFO_H_ */ diff --git a/gr-atsc/src/lib/atsci_sync_tag.h b/gr-atsc/src/lib/atsci_sync_tag.h new file mode 100644 index 00000000..bca8b864 --- /dev/null +++ b/gr-atsc/src/lib/atsci_sync_tag.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _ATSC_SYNC_TAG_H_ +#define _ATSC_SYNC_TAG_H_ + +/* + * Constants used to communicate in the second stream passed between + * GrAtscFSCorrelator, GrAtscEqualizer and GrAtscFieldSyncMux. The + * second stream is sample-for-sample parallel with the streaming + * floating point in the first stream. The second stream provides + * information about alignment boundaries. + * + * These are in floating point because the current implementation + * requires that for a given module, all input streams share the same + * type and all output streams share the same type. We'd use unsigned + * char otherwise. + */ + +namespace atsc_sync_tag { + + // Nothing special + static const float NORMAL = 0.0; + + // The corresponding symbol is the first symbol of the + // data segment sync sequence { +5, -5, -5, +5 } + static const float START_SEG_SYNC = 1.0; + + // The corresponding symbol is the first symbol of the + // field sync 1 PN511 pattern. + static const float START_FIELD_SYNC_1 = 2.0; + + // The corresponding symbol is the first symbol of the + // field sync 2 PN511 pattern. + static const float START_FIELD_SYNC_2 = 3.0; +}; + +#endif /* _ATSC_SYNC_TAG_H_ */ diff --git a/gr-atsc/src/lib/atsci_trellis_encoder.cc b/gr-atsc/src/lib/atsci_trellis_encoder.cc new file mode 100644 index 00000000..8e09739f --- /dev/null +++ b/gr-atsc/src/lib/atsci_trellis_encoder.cc @@ -0,0 +1,207 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +static const int DIBITS_PER_BYTE = 4; + +#define SEGOF(x) ( (x) / ((SEGMENT_SIZE+1) * DIBITS_PER_BYTE)) +#define SYMOF(x) (((x) % ((SEGMENT_SIZE+1) * DIBITS_PER_BYTE))-4) + +/* How many separate Trellis encoders / Viterbi decoders run in parallel */ +static const int NCODERS = 12; + +#define ENCODER_SEG_BUMP 4 + +/* A Segment sync symbol is an 8VSB +5,-5,-5,+5 sequence that occurs at + the start of each 207-byte segment (including field sync segments). */ +#define DSEG_SYNC_SYM1 0x06 /* +5 */ +#define DSEG_SYNC_SYM2 0x01 /* -5 */ +#define DSEG_SYNC_SYM3 0x01 /* -5 */ +#define DSEG_SYNC_SYM4 0x06 /* +5 */ + + +/* Shift counts to bit numbers (high order, low order); 9x entries unused */ +static const int bit1[8] = {1, 99, 3, 98, 5, 97, 7, 96}; +static const int bit2[8] = {0, 99, 2, 98, 4, 97, 6, 96}; + + +atsci_trellis_encoder::atsci_trellis_encoder () +{ + debug = false; + reset (); +} + +atsci_trellis_encoder::~atsci_trellis_encoder () +{ +} + +void +atsci_trellis_encoder::reset () +{ + for (int i = 0; i < NCODERS; i++) + enc[i].reset (); +} + +void +atsci_trellis_encoder::encode (atsc_data_segment out[NCODERS], + const atsc_mpeg_packet_rs_encoded in[NCODERS]) +{ + unsigned char out_copy[OUTPUT_SIZE]; + unsigned char in_copy[INPUT_SIZE]; + + assert (sizeof (in_copy) == sizeof (in[0].data) * NCODERS); + assert (sizeof (out_copy) == sizeof (out[0].data) * NCODERS); + + // copy input into continguous temporary buffer + for (int i = 0; i < NCODERS; i++){ + assert (in[i].pli.regular_seg_p ()); + plinfo::sanity_check (in[i].pli); + memcpy (&in_copy[i * INPUT_SIZE/NCODERS], + &in[i].data[0], + ATSC_MPEG_RS_ENCODED_LENGTH * sizeof (in_copy[0])); + } + + memset (out_copy, 0, sizeof (out_copy)); // FIXME, sanity check + + // do the deed... + encode_helper (out_copy, in_copy); + + // copy output from contiguous temp buffer into final output + for (int i = 0; i < NCODERS; i++){ + memcpy (&out[i].data[0], + &out_copy[i * OUTPUT_SIZE/NCODERS], + ATSC_DATA_SEGMENT_LENGTH * sizeof (out_copy[0])); + + // copy pipeline info + out[i].pli = in[i].pli; + + plinfo::sanity_check (out[i].pli); + assert (out[i].pli.regular_seg_p ()); + } +} + +/* + * This code expects contiguous arrrays. Use it as is, it computes + * the correct answer. Maybe someday, when we've run out of better + * things to do, rework to avoid the copying in encode. + */ +void +atsci_trellis_encoder::encode_helper (unsigned char output[OUTPUT_SIZE], + const unsigned char input[INPUT_SIZE]) +{ + int i; + int encoder; + unsigned char trellis_buffer[NCODERS]; + int trellis_wherefrom[NCODERS]; + unsigned char *out, *next_out_seg; + int chunk; + int shift; + unsigned char dibit; + unsigned char symbol; + int skip_encoder_bump; + + /* FIXME, we may want special processing here + for a flag byte to keep track of which part of the field we're in? */ + + encoder = NCODERS - ENCODER_SEG_BUMP; + skip_encoder_bump = 0; + out = output; + next_out_seg = out; + + for (chunk = 0; + chunk < INPUT_SIZE; + chunk += NCODERS) { + /* Load a new chunk of bytes into the Trellis encoder buffers. + They get loaded in an order that depends on where we are in the + segment sync progress (sigh). + GRR! When the chunk reload happens at the same time as the + segment boundary, we should bump the encoder NOW for the reload, + rather than LATER during the bitshift transition!!! */ + if (out >= next_out_seg) { + encoder = (encoder + ENCODER_SEG_BUMP) % NCODERS; + skip_encoder_bump = 1; + } + + for (i = 0; i < NCODERS; i++) { + /* for debug */ trellis_wherefrom[encoder] = chunk+i; + trellis_buffer[encoder] = input [chunk+i]; + encoder++; + if (encoder >= NCODERS) encoder = 0; + } + + for (shift = 6; shift >= 0; shift -= 2) { + + /* Segment boundaries happen to occur on some bitshift transitions. */ + if (out >= next_out_seg) { + /* Segment transition. Output a data segment sync symbol, and + mess with the trellis encoder mux. */ + *out++ = DSEG_SYNC_SYM1; + *out++ = DSEG_SYNC_SYM2; + *out++ = DSEG_SYNC_SYM3; + *out++ = DSEG_SYNC_SYM4; + if (debug) printf ("SYNC SYNC SYNC SYNC\n"); + next_out_seg = out + (SEGMENT_SIZE * DIBITS_PER_BYTE); + + if (!skip_encoder_bump) + encoder = (encoder + ENCODER_SEG_BUMP) % NCODERS; + skip_encoder_bump = 0; + } + + /* Now run each of the 12 Trellis encoders to spit out 12 symbols. + Each encoder takes input from the same byte of the chunk, but the + outputs of the encoders come out in various orders. + NOPE -- this is false. The encoders take input from various + bytes of the chunk (which changes at segment sync time), AND + they also come out in various orders. You really do have to + keep separate track of: the input bytes, the encoders, and + the output bytes -- because they're all moving with respect to + each other!!! */ + for (i = 0; i < NCODERS; i++) { + dibit = 0x03 & (trellis_buffer[encoder] >> shift); + if (debug) + printf ("Seg %ld Symb %3ld Trell %2d Byte %6d Bits %d-%d = dibit %d ", + (long) SEGOF(out-output), (long) SYMOF(out-output), + encoder, trellis_wherefrom[encoder], + bit1[shift], bit2[shift], dibit); + symbol = enc[encoder].encode (dibit); + *out++ = symbol; + encoder++; if (encoder >= NCODERS) encoder = 0; + if (debug) printf ("sym %d\n", symbol); + } /* Encoders */ + } /* Bit shifts */ + } /* Chunks */ + + /* Check up on ourselves */ +#if 0 + assertIntsEqual (0, (INPUT_SIZE * DIBITS_PER_BYTE) % NCODERS, "not %"); + assertIntsEqual (OUTPUT_SIZE, out - output, "outptr"); + assertIntsEqual (NCODERS - ENCODER_SEG_BUMP, encoder, "mux sync"); +#else + assert (0 == (INPUT_SIZE * DIBITS_PER_BYTE) % NCODERS); + assert (OUTPUT_SIZE == out - output); + assert (NCODERS - ENCODER_SEG_BUMP == encoder); +#endif +} + diff --git a/gr-atsc/src/lib/atsci_trellis_encoder.h b/gr-atsc/src/lib/atsci_trellis_encoder.h new file mode 100644 index 00000000..429d3d10 --- /dev/null +++ b/gr-atsc/src/lib/atsci_trellis_encoder.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_TRELLIS_ENCODER_H_ +#define _ATSC_TRELLIS_ENCODER_H_ + +#include +#include + +/*! + * \brief fancy, schmancy 12-way interleaved trellis encoder for ATSC + */ + +class atsci_trellis_encoder { + public: + static const int NCODERS = 12; + + atsci_trellis_encoder (); + ~atsci_trellis_encoder (); + + //! reset all encoder states + void reset (); + + /*! + * Take 12 RS encoded, convolutionally interleaved segments and + * produce 12 trellis coded data segments. We work in groups of 12 + * because that's the smallest number of segments that composes a + * single full cycle of the encoder mux. + */ + void encode (atsc_data_segment out[NCODERS], + const atsc_mpeg_packet_rs_encoded in[NCODERS]); + + + protected: + static const int SEGMENT_SIZE = ATSC_MPEG_RS_ENCODED_LENGTH; // 207 + static const int INPUT_SIZE = (SEGMENT_SIZE * 12); + static const int OUTPUT_SIZE = (ATSC_DATA_SEGMENT_LENGTH * 12); + + void encode_helper (unsigned char out[OUTPUT_SIZE], + const unsigned char in[INPUT_SIZE]); + + atsci_basic_trellis_encoder enc[NCODERS]; + bool debug; +}; + + +#endif /* _ATSC_TRELLIS_ENCODER_H_ */ diff --git a/gr-atsc/src/lib/atsci_viterbi_decoder.cc b/gr-atsc/src/lib/atsci_viterbi_decoder.cc new file mode 100644 index 00000000..4e017a98 --- /dev/null +++ b/gr-atsc/src/lib/atsci_viterbi_decoder.cc @@ -0,0 +1,175 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include "atsci_viterbi_mux.cc" + + +/* How many separate Trellis encoders / Viterbi decoders run in parallel */ +static const int NCODERS = 12; + +static const float DSEG_SYNC_SYM1 = 5; +static const float DSEG_SYNC_SYM2 = -5; +static const float DSEG_SYNC_SYM3 = -5; +static const float DSEG_SYNC_SYM4 = 5; + +atsci_viterbi_decoder::atsci_viterbi_decoder () +{ + debug = true; + + /* + * These fifo's handle the alignment problem caused by the + * inherent decoding delay of the individual viterbi decoders. + * The net result is that this entire block has a pipeline latency + * of 12 complete segments. + * + * If anybody cares, it is possible to do it with less delay, but + * this approach is at least somewhat understandable... + */ + + // the -4 is for the 4 sync symbols + int fifo_size = ATSC_DATA_SEGMENT_LENGTH - 4 - viterbi[0].delay (); + for (int i = 0; i < NCODERS; i++) + fifo[i] = new fifo_t(fifo_size); + + reset (); +} + +atsci_viterbi_decoder::~atsci_viterbi_decoder () +{ + for (int i = 0; i < NCODERS; i++) + delete fifo[i]; +} + +void +atsci_viterbi_decoder::reset () +{ + for (int i = 0; i < NCODERS; i++){ + viterbi[i].reset (); + fifo[i]->reset (); + } +} + + +void +atsci_viterbi_decoder::decode (atsc_mpeg_packet_rs_encoded out[NCODERS], + const atsc_soft_data_segment in[NCODERS]) +{ + unsigned char out_copy[OUTPUT_SIZE]; + float in_copy[INPUT_SIZE]; + + // copy input into continguous temporary buffer + for (int i = 0; i < NCODERS; i++){ + assert (in[i].pli.regular_seg_p ()); + memcpy (&in_copy[i * INPUT_SIZE/NCODERS], + &in[i].data[0], + ATSC_DATA_SEGMENT_LENGTH * sizeof (in_copy[0])); + } + + memset (out_copy, 0, sizeof (out_copy)); // sanity check + + // do the deed... + decode_helper (out_copy, in_copy); + + // copy output from contiguous temp buffer into final output + for (int i = 0; i < NCODERS; i++){ + memcpy (&out[i].data[0], + &out_copy[i * OUTPUT_SIZE/NCODERS], + ATSC_MPEG_RS_ENCODED_LENGTH * sizeof (out_copy[0])); + + + // adjust pipeline info to reflect 12 segment delay + plinfo::delay (out[i].pli, in[i].pli, NCODERS); + } +} + +void +atsci_viterbi_decoder::decode_helper (unsigned char out[OUTPUT_SIZE], + const float symbols_in[INPUT_SIZE]) +{ + int encoder; + unsigned int i; + int dbi; + int dbwhere; + int dbindex; + int shift; + unsigned char dibit; + float symbol; + + /* Memset is not necessary if it's all working... */ + memset (out, 0, OUTPUT_SIZE); + +#define VERBOSE 0 + +#if 1 + /* Check for sync symbols in the incoming data stream */ + /* For now, all we do is complain to stdout. FIXME, pass it back to + caller as an error/quality signal. */ + for (i = 0; i < sync_symbol_indices_max; i++) { + int j = sync_symbol_indices[i]; + if (fabsf (symbols_in[j] - DSEG_SYNC_SYM1) > 1.0) + if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 1 at %d, expect %g, got %g.\n", + j, DSEG_SYNC_SYM1, symbols_in[j]); + j++; + if (fabsf (symbols_in[j] - DSEG_SYNC_SYM2) > 1.0) + if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 2 at %d, expect %g, got %g.\n", + j, DSEG_SYNC_SYM2, symbols_in[j]); + j++; + if (fabsf (symbols_in[j] - DSEG_SYNC_SYM3) > 1.0) + if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 3 at %d, expect %g, got %g.\n", + j, DSEG_SYNC_SYM3, symbols_in[j]); + j++; + if (fabsf (symbols_in[j] - DSEG_SYNC_SYM4) > 1.0) + if (VERBOSE) fprintf (stderr, "** Missing dataseg sync 4 at %d, expect %g, got %g.\n", + j, DSEG_SYNC_SYM4, symbols_in[j]); + } +#endif +#undef VERBOSE + + // printf ("@@@ DIBITS @@@\n"); + + /* Now run each of the 12 Trellis encoders over their subset of + the input symbols */ + for (encoder = 0; encoder < NCODERS; encoder++) { + dbi = 0; /* Reinitialize dibit index for new encoder */ + fifo_t *dibit_fifo = fifo[encoder]; + + /* Feed all the incoming symbols into one encoder; + pump them into the relevant dibits. */ + for (i = 0; i < enco_which_max; i++) { + symbol = symbols_in[enco_which_syms[encoder][i]]; + dibit = dibit_fifo->stuff (viterbi[encoder].decode (symbol)); + // printf ("%d\n", dibit); + /* Store the dibit into the output data segment */ + dbwhere = enco_which_dibits[encoder][dbi++]; + dbindex = dbwhere >> 3; + shift = dbwhere & 0x7; + out[dbindex] = + (out[dbindex] & ~(0x03 << shift)) | (dibit << shift); + } /* Symbols fed into one encoder */ + } /* Encoders */ + + // fflush (stdout); +} diff --git a/gr-atsc/src/lib/atsci_viterbi_decoder.h b/gr-atsc/src/lib/atsci_viterbi_decoder.h new file mode 100644 index 00000000..a804b666 --- /dev/null +++ b/gr-atsc/src/lib/atsci_viterbi_decoder.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_VITERBI_DECODER_H_ +#define _ATSC_VITERBI_DECODER_H_ + +#define USE_SIMPLE_SLICER 0 + +#include +#include + +#if (USE_SIMPLE_SLICER) +#include +typedef atsci_fake_single_viterbi single_viterbi_t; +#else +#include +typedef atsci_single_viterbi single_viterbi_t; +#endif + +/*! + * \brief fancy, schmancy 12-way interleaved viterbi decoder for ATSC + */ + +class atsci_viterbi_decoder { +public: + static const int NCODERS = 12; + + atsci_viterbi_decoder (); + ~atsci_viterbi_decoder (); + + //! reset all decoder states + void reset (); + + /*! + * Take 12 data segments of soft decisions (floats) and + * produce 12 RS encoded data segments. We work in groups of 12 + * because that's the smallest number of segments that composes a + * single full cycle of the decoder mux. + */ + void decode (atsc_mpeg_packet_rs_encoded out[NCODERS], + const atsc_soft_data_segment in[NCODERS]); + + + + protected: + typedef interleaver_fifo fifo_t; + + static const int SEGMENT_SIZE = ATSC_MPEG_RS_ENCODED_LENGTH; // 207 + static const int OUTPUT_SIZE = (SEGMENT_SIZE * 12); + static const int INPUT_SIZE = (ATSC_DATA_SEGMENT_LENGTH * 12); + + void decode_helper (unsigned char out[OUTPUT_SIZE], + const float in[INPUT_SIZE]); + + + single_viterbi_t viterbi[NCODERS]; + fifo_t *fifo[NCODERS]; + bool debug; + +}; + + + +#endif /* _ATSC_VITERBI_DECODER_H_ */ diff --git a/gr-atsc/src/lib/atsci_viterbi_gen.cc b/gr-atsc/src/lib/atsci_viterbi_gen.cc new file mode 100644 index 00000000..2004dbbc --- /dev/null +++ b/gr-atsc/src/lib/atsci_viterbi_gen.cc @@ -0,0 +1,267 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +using std::cerr; + +/* + * Trellis-encode a whole pile of 12 data segments for ATSC. + * This also includes scrambling the data among twelve Trellis encoders. + * + * Input is twelve 207-byte blocks of raw data (Reed-Solomon output that's + * been scrambled up by interleaving with other blocks). + * + * Output is 12 x 208 x 4 bytes, each byte containing a 3-bit symbol. + * The first 4 bytes are the segment sync symbol. + * + Got the first version of Trellis encoder coded. Compiles, but I + didn't realize that each data segment contains an odd number of BITS! + The second data segment in a field starts by pulling bits out of the + middles of the bytes it's encoding. You actually have to read all the + entries in that table on page 59 AND 60 to get it. + + There's a 4-segment asymmetric pattern of bit accesses. + There's a 3-segment asymmetric pattern of muxing encoders. + + The result is there's a 12-segment pattern that repeats throughout + the encoding of a field. So this routine now encodes 12 segments at once. + + This encoding system was either designed by a complete idiot or by + a complete genius. It's highly complex when it could have been very + simple. Now the question is whether + this incredible complexity buys us anything subtle and important. + */ + +#define SEGMENT_SIZE 207 +#define INPUT_SIZE (SEGMENT_SIZE * 12) +#define DIBITS_PER_BYTE 4 +#define EXTRAS (4 * 12) /* FIXME, sync symbols and such */ +#define SYMBOLS_OUT ((INPUT_SIZE * DIBITS_PER_BYTE) + EXTRAS) +#define SEGOF(x) ( (x) / ((SEGMENT_SIZE+1) * DIBITS_PER_BYTE)) +#define SYMOF(x) (((x) % ((SEGMENT_SIZE+1) * DIBITS_PER_BYTE))-4) +#define ENCODERS 12 +#define ENCODER_SEG_BUMP 4 + + +/* Shift counts to bit numbers (high order, low order); 9x entries unused */ +static const int bit1[8] = {1, 99, 3, 98, 5, 97, 7, 96}; +static const int bit2[8] = {0, 99, 2, 98, 4, 97, 6, 96}; + +/* Detailed Debugging */ +int debug_dec = 0; + +/* + * Build indirect data structures to say which symbols go into which + * encoder, and then where the resulting dibits from the encoders go. + */ +int +build_decode_structures (char *fileout) +{ + int retval = 0; + int i; + int encoder; + int trellis_wheredata[ENCODERS]; + unsigned char *symp, *next_sym_seg; + unsigned char symbols[SYMBOLS_OUT]; + int chunk; + int shift; + int skip_encoder_bump; + int *enco_syms[ENCODERS]; + int *enco_dibits[ENCODERS]; + int j; + /* The data structures we'll build and then spit out... */ + int sync_symbol_indices[1000]; + int sync_symbol_indices_max; + int enco_which_syms[ENCODERS][INPUT_SIZE]; + int enco_which_dibits[ENCODERS][INPUT_SIZE]; + int enco_which_max; + #define BIT_PTR(int,shif) (((int) << 3) | ((shif) & 0x7)) + /* Running indices into them as we build 'em... */ + int *syncsyms = sync_symbol_indices; + + /* Start our running pointers at the start of our per-encoder subarrays */ + for (i = 0; i < ENCODERS; i++) { + enco_dibits[i] = enco_which_dibits[i]; + enco_syms[i] = enco_which_syms[i]; + } + + encoder = ENCODERS - ENCODER_SEG_BUMP; + skip_encoder_bump = 0; + symp = symbols; + next_sym_seg = symp; + + for (chunk = 0; + chunk < INPUT_SIZE; + chunk += ENCODERS) { + /* Associate data bytes with the Trellis encoders. + They get loaded or stored in an order that depends on where we are in the + segment sync progress (sigh). + GRR! When the chunk reload happens at the same time as the + segment boundary, we should bump the encoder NOW for the reload, + rather than LATER during the bitshift transition!!! */ + if (symp >= next_sym_seg) { + encoder = (encoder + ENCODER_SEG_BUMP) % ENCODERS; + skip_encoder_bump = 1; + } + + /* Remember where the data bytes are going to go, once we've + accumulated them from the 12 interleaved decoders */ + for (i = 0; i < ENCODERS; i++) { + trellis_wheredata[encoder] = chunk+i; + encoder++; + if (encoder >= ENCODERS) encoder = 0; + } + + for (shift = 6; shift >= 0; shift -= 2) { + + /* Segment boundaries happen to occur on some bitshift transitions. */ + if (symp >= next_sym_seg) { + /* Segment transition. Output a data segment sync symbol, and + mess with the trellis encoder mux. */ + *syncsyms++ = symp - symbols; + symp += 4; + next_sym_seg = symp + (SEGMENT_SIZE * DIBITS_PER_BYTE); + + if (!skip_encoder_bump) + encoder = (encoder + ENCODER_SEG_BUMP) % ENCODERS; + skip_encoder_bump = 0; + } + + /* Now run each of the 12 Trellis encoders to spit out 12 symbols. + Each encoder takes input from the same byte of the chunk, but the + outputs of the encoders come out in various orders. + NOPE -- this is false. The encoders take input from various + bytes of the chunk (which changes at segment sync time), AND + they also come out in various orders. You really do have to + keep separate track of: the datasegs bytes, the encoders, and + the symbol bytes -- because they're all moving with respect to + each other!!! */ + for (i = 0; i < ENCODERS; i++) { + if (debug_dec) + printf ("Seg %ld Symb %3ld Trell %2d Byte %6d Bits %d-%d = ", + (long) SEGOF(symp-symbols), (long) SYMOF(symp-symbols), + encoder, trellis_wheredata[encoder], + bit1[shift], bit2[shift]); + + /* Decoding: Grab symbol, run through decoder, slice dibit into + buffer. */ + /* This symbol goes into this encoder next */ + *(enco_syms[encoder]++) = symp - symbols; + symp++; + /* The next output from this encoder goes into these dibits */ + *(enco_dibits[encoder]++) = BIT_PTR(trellis_wheredata[encoder], shift); + + encoder++; if (encoder >= ENCODERS) encoder = 0; + } /* Encoders */ + } /* Bit shifts */ + +#if 0 + /* Now dump out the chunk of 12 data bytes that the twelve decoders have + accumulated. */ + unsigned char trellis_buffer[ENCODERS]; + unsigned char dibit; + unsigned char symbol; + int save_state; + for (i = 0; i < ENCODERS; i++) { + datasegs [trellis_wheredata[encoder]] = trellis_buffer[encoder]; + encoder++; + if (encoder >= ENCODERS) encoder = 0; + } /* Dumping encoder bytes */ +#endif + } /* Chunks */ + + /* Now print the resulting data structures in C++ */ + + if (!freopen(fileout, "w", stdout)) + return 2; + + printf ("/*\n\ + * atsc_viterbi_mux.cc\n\ + *\n\ + * Data structures for knowing which symbols are fed to which\n\ + * Viterbi decoders, and then where to put the resulting output dibits.\n\ + *\n\ + * Generated by 'atsc_viterbi_gen.cc'.\n\ + */\n\n"); + sync_symbol_indices_max = syncsyms - sync_symbol_indices; + printf ("const unsigned int sync_symbol_indices_max = %d;\n", + sync_symbol_indices_max); + printf ("const unsigned int sync_symbol_indices[%d] = {\n ", + sync_symbol_indices_max); + for (i = 0; i < sync_symbol_indices_max; i++) { + printf ("%d,%s", sync_symbol_indices[i], (7 == i%8)? "\n ": " "); + } + printf ("};\n\n"); + + enco_which_max = enco_dibits[0] - enco_which_dibits[0]; + for (i = 0; i < ENCODERS; i++) + if (enco_which_max != enco_dibits[i] - enco_which_dibits[i]) { + cerr << "Encoder " << i << " has different max_dibits " << + enco_dibits[i] - enco_which_dibits[i] << " than " << enco_which_max; + retval = 3; + } + + printf ("const unsigned int enco_which_max = %d;\n" , enco_which_max); + + printf ("const unsigned int enco_which_syms[%d][%d] = {\n", + ENCODERS, enco_which_max); + for (i = 0; i < ENCODERS; i++) { + printf (" /* %d */\n {", i); + for (j = 0; j < enco_which_max; j++) + printf ("%d,%s", enco_which_syms[i][j], (7 == j%8)? "\n ": " "); + printf ("},\n"); + } + printf ("};\n\n"); + + printf ("const unsigned int enco_which_dibits[%d][%d] = {\n", + ENCODERS, enco_which_max); + for (i = 0; i < ENCODERS; i++) { + printf (" /* %d */\n {", i); + for (j = 0; j < enco_which_max; j++) + printf ("%d,%s", enco_which_dibits[i][j], (7 == j%8)? "\n ": " "); + printf ("},\n"); + } + printf ("};\n\n"); + return retval; +} + +int +usage() +{ + cerr << "atsc_viterbi_gen: Usage:\n"; + cerr << " ./atsc_viterbi_gen -o atsc_viterbi_mux.cc\n"; + cerr << "That's all, folks!\n"; + return 1; +} + + +int +main(int argc, char **argv) +{ + if (argc != 3) return usage(); + if (argv[1][0] != '-' + || argv[1][1] != 'o' + || argv[1][2] != 0 ) return usage(); + return build_decode_structures(argv[2]); +} diff --git a/gr-atsc/src/lib/atsci_vsbtx_lp.cc b/gr-atsc/src/lib/atsci_vsbtx_lp.cc new file mode 100644 index 00000000..d0878dcc --- /dev/null +++ b/gr-atsc/src/lib/atsci_vsbtx_lp.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +using std::vector; +using std::cerr; +using std::endl; + +// atsc root raised cosine filter, sampling rate = 21.52 MHz +static const float atsc_vsbtx_lp2x[] = { +#include "atsc_vsbtx_lp.dat" +}; + +#define NELEM(x) (sizeof (x) / sizeof ((x)[0])) + +// is a within 5% of target? + +static bool +close_enough_p (double a, double target) +{ + double delta = fabs (target * 0.05); // 5 percent + + return fabs (target - a) <= delta; +} + +vector +atsc_vsbtx_lp::taps (double sampling_freq) +{ + if (close_enough_p (sampling_freq, 2 * ATSC_SYMBOL_RATE)){ + return vector(&atsc_vsbtx_lp2x[0], &atsc_vsbtx_lp2x[NELEM(atsc_vsbtx_lp2x)]); + } + else + throw std::out_of_range ( + "atsc_vsbtx_lp: no pre-designed filter close enough"); +} diff --git a/gr-atsc/src/lib/atsci_vsbtx_lp.dat b/gr-atsc/src/lib/atsci_vsbtx_lp.dat new file mode 100644 index 00000000..448fda7a --- /dev/null +++ b/gr-atsc/src/lib/atsci_vsbtx_lp.dat @@ -0,0 +1,49 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:LOW PASS 1H + * PASSBAND RIPPLE IN -dB -.0100 + * STOPBAND RIPPLE IN -dB -76.0000 + * PASSBAND CUTOFF FREQUENCY .250000 HERTZ + * STOPBAND CUTOFF FREQUENCY .360000 HERTZ + * SAMPLING FREQUENCY 1.00000 HERTZ + */ +/* + * gain of 2 + */ + 9.23312269151211e-04, + 8.75200144946575e-04, + -2.89211887866259e-03, + 1.31580047309399e-04, + 6.72745611518621e-03, + -5.82943391054869e-03, + -8.86140950024128e-03, + 1.84674616903067e-02, + 1.27039104700089e-03, + -3.39064113795757e-02, + 2.52537783235312e-02, + 3.74889532104135e-02, + -7.35438484698534e-02, + -3.70154529809952e-03, + 1.33745657280087e-01, + -1.12098718993366e-01, + -1.84760546311736e-01, + 5.98605459555984e-01, + 1.20420956425369e+00, + 5.98605459555984e-01, + -1.84760546311736e-01, + -1.12098718993366e-01, + 1.33745657280087e-01, + -3.70154529809952e-03, + -7.35438484698534e-02, + 3.74889532104135e-02, + 2.52537783235312e-02, + -3.39064113795757e-02, + 1.27039104700089e-03, + 1.84674616903067e-02, + -8.86140950024128e-03, + -5.82943391054869e-03, + 6.72745611518621e-03, + 1.31580047309399e-04, + -2.89211887866259e-03, + 8.75200144946575e-04, + 9.23312269151211e-04 diff --git a/gr-atsc/src/lib/atsci_vsbtx_lp.h b/gr-atsc/src/lib/atsci_vsbtx_lp.h new file mode 100644 index 00000000..112a4bb4 --- /dev/null +++ b/gr-atsc/src/lib/atsci_vsbtx_lp.h @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ATSC_VSBTX_LP_H_ +#define _ATSC_VSBTX_LP_H_ + +#include + +class atsc_vsbtx_lp : public gr_fir_builder +{ +public: + virtual std::vector taps (double sampling_freq); +}; + + + +#endif /* _ATSC_VSBTX_LP_H_ */ diff --git a/gr-atsc/src/lib/convolutional_interleaver.h b/gr-atsc/src/lib/convolutional_interleaver.h new file mode 100644 index 00000000..bb336252 --- /dev/null +++ b/gr-atsc/src/lib/convolutional_interleaver.h @@ -0,0 +1,126 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CONVOLUTIONAL_INTERLEAVER_H_ +#define _CONVOLUTIONAL_INTERLEAVER_H_ + +#include +#include +#include + +/*! + * \brief template class for generic convolutional interleaver + */ + +template +class convolutional_interleaver { + public: + + convolutional_interleaver (bool interleave_p, int nbanks, int fifo_size_incr); + virtual ~convolutional_interleaver (); + + //! reset interleaver (flushes contents and resets commutator) + void reset (); + + //! sync interleaver (resets commutator, but doesn't flush fifos) + void sync () { m_commutator = 0; } + + //! return end to end delay in symbols (delay through concatenated interleaver / deinterleaver) + int end_to_end_delay (); + + //! transform a single symbol + symbol_type transform (symbol_type input){ + symbol_type retval = m_fifo[m_commutator]->stuff (input); + m_commutator++; + if (m_commutator >= m_nbanks) + m_commutator = 0; + return retval; + } + + //! transform a bunch of symbols + void transform (symbol_type *out, const symbol_type *in, int nsymbols); + +protected: + int m_commutator; + int m_nbanks; + int m_fifo_size_incr; + std::vector *> m_fifo; +}; + +template +convolutional_interleaver::convolutional_interleaver ( + bool interleave_p, + int nbanks, + int fifo_size_incr) +{ + assert (nbanks >= 1); + assert (fifo_size_incr >= 1); + + m_nbanks = nbanks; + m_fifo_size_incr = fifo_size_incr; + + m_fifo.resize (nbanks); + + if (interleave_p){ // configure as interleaver + for (int i = 0; i < nbanks; i++) + m_fifo[i] = new interleaver_fifo(i * fifo_size_incr); + } + else { // configure as de-interleaver + for (int i = 0; i < nbanks; i++) + m_fifo[nbanks - 1 - i] = new interleaver_fifo(i * fifo_size_incr); + } + sync (); +} + +template +convolutional_interleaver::~convolutional_interleaver () +{ + for (int i = 0; i < m_nbanks; i++) + delete m_fifo[i]; +} + +template void +convolutional_interleaver::reset () +{ + sync (); + for (int i = 0; i < m_nbanks; i++) + m_fifo[i]->reset (); +} + +template int +convolutional_interleaver::end_to_end_delay () +{ + int m = m_nbanks * m_fifo_size_incr; + return m * (m_nbanks - 1); +} + +template void +convolutional_interleaver::transform (symbol_type *out, + const symbol_type *in, + int nsymbols) +{ + // we may want to unroll this a couple of times... + for (int i = 0; i < nsymbols; i++) + out[i] = transform (in[i]); +} + +#endif /* _CONVOLUTIONAL_INTERLEAVER_H_ */ diff --git a/gr-atsc/src/lib/create_atsci_equalizer.cc b/gr-atsc/src/lib/create_atsci_equalizer.cc new file mode 100644 index 00000000..0f3bdbcb --- /dev/null +++ b/gr-atsc/src/lib/create_atsci_equalizer.cc @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +atsci_equalizer * +create_atsci_equalizer_nop () +{ + return new atsci_equalizer_nop (); +} + +atsci_equalizer * +create_atsci_equalizer_lms () +{ + return new atsci_equalizer_lms (); +} + +atsci_equalizer * +create_atsci_equalizer_lms2 () +{ + return new atsci_equalizer_lms2 (); +} diff --git a/gr-atsc/src/lib/create_atsci_equalizer.h b/gr-atsc/src/lib/create_atsci_equalizer.h new file mode 100644 index 00000000..5e1023de --- /dev/null +++ b/gr-atsc/src/lib/create_atsci_equalizer.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _CREATE_ATSC_EQUALIZER_H_ +#define _CREATE_ATSC_EQUALIZER_H_ + +class atsci_equalizer; + +atsci_equalizer *create_atsci_equalizer_nop (); +atsci_equalizer *create_atsci_equalizer_lms (); +atsci_equalizer *create_atsci_equalizer_lms2 (); + +#endif /* _CREATE_ATSC_EQUALIZER_H_ */ diff --git a/gr-atsc/src/lib/create_atsci_fs_checker.cc b/gr-atsc/src/lib/create_atsci_fs_checker.cc new file mode 100644 index 00000000..a0a0f3d1 --- /dev/null +++ b/gr-atsc/src/lib/create_atsci_fs_checker.cc @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +atsci_fs_checker * +create_atsci_fs_checker () +{ + return new atsci_fs_checker_naive (); +} diff --git a/gr-atsc/src/lib/create_atsci_fs_checker.h b/gr-atsc/src/lib/create_atsci_fs_checker.h new file mode 100644 index 00000000..6b258bcf --- /dev/null +++ b/gr-atsc/src/lib/create_atsci_fs_checker.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CREATE_ATSC_FS_CHECKER_H_ +#define _CREATE_ATSC_FS_CHECKER_H_ + +class atsci_fs_checker; + +/*! + * Factory that creates appropriate atsci_fs_checker + */ +atsci_fs_checker *create_atsci_fs_checker (); + + +#endif /* _CREATE_ATSC_FS_CHECKER_H_ */ diff --git a/gr-atsc/src/lib/create_atsci_fs_correlator.cc b/gr-atsc/src/lib/create_atsci_fs_correlator.cc new file mode 100644 index 00000000..6664003e --- /dev/null +++ b/gr-atsc/src/lib/create_atsci_fs_correlator.cc @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +atsci_fs_correlator * +create_atsci_fs_correlator () +{ + return new atsci_fs_correlator_naive (); +} diff --git a/gr-atsc/src/lib/create_atsci_fs_correlator.h b/gr-atsc/src/lib/create_atsci_fs_correlator.h new file mode 100644 index 00000000..511bce99 --- /dev/null +++ b/gr-atsc/src/lib/create_atsci_fs_correlator.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CREATE_ATSC_FS_CORRELATOR_H_ +#define _CREATE_ATSC_FS_CORRELATOR_H_ + +class atsci_fs_correlator; + +/*! + * Factory that creates appropriate atsci_fs_correlator + */ +atsci_fs_correlator *create_atsci_fs_correlator (); + + +#endif /* _CREATE_ATSC_FS_CORRELATOR_H_ */ diff --git a/gr-atsc/src/lib/fpll_btloop_coupling.h b/gr-atsc/src/lib/fpll_btloop_coupling.h new file mode 100644 index 00000000..f5c90f94 --- /dev/null +++ b/gr-atsc/src/lib/fpll_btloop_coupling.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _FPLL_BTLOOP_COUPLING_H_ +#define _FPLL_BTLOOP_COUPLING_H_ + +/*! + * Magic coupling constant between GrAtscFPLL and GrAtscBitTimingLoop. + * Trust me, you don't want to mess with this. + * + * The agc block buried in the FPLL indirectly sets the level of the input + * to the bit timing loop. The bit timing loop's convergence properties + * depend on the the mean amplitude of it's input. This constant ties + * them together such that you can tweak the input level of the bit timing loop + * (somewhat) without screwing everything. + */ + +static const float FPLL_BTLOOP_COUPLING_CONST = 3.125; + +#endif /* _FPLL_BTLOOP_COUPLING_H_ */ diff --git a/gr-atsc/src/lib/gen_encoder.py b/gr-atsc/src/lib/gen_encoder.py new file mode 100755 index 00000000..0a2a5080 --- /dev/null +++ b/gr-atsc/src/lib/gen_encoder.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def output(input, state): + x2 = (input >> 1) & 0x1 + x1 = (input >> 0) & 0x1 + s = (state >> 2) & 0x1 + t = (state >> 1) & 0x1 + u = (state >> 0) & 0x1 + + z0 = u + z1 = x1 + z2 = x2 ^ s + return (z2 << 2) | (z1 << 1) | z0 + + +def next_state(input, state): + x2 = (input >> 1) & 0x1 + x1 = (input >> 0) & 0x1 + s0 = (state >> 2) & 0x1 + t0 = (state >> 1) & 0x1 + u0 = (state >> 0) & 0x1 + + s1 = x2 ^ s0 + t1 = u0 + u1 = t0 ^ x1 + + return (s1 << 2) | (t1 << 1) | u1 + +print "@@@ NEXT @@@" + +for i in range (32): + state = (i >> 2) & 0x7 + input = i & 0x3 + print next_state (input, state) + + +print "@@@ OUTPUT @@@" + +for i in range (32): + state = (i >> 2) & 0x7 + input = i & 0x3 + print output (input, state) + diff --git a/gr-atsc/src/lib/interleaver_fifo.h b/gr-atsc/src/lib/interleaver_fifo.h new file mode 100644 index 00000000..e20b968f --- /dev/null +++ b/gr-atsc/src/lib/interleaver_fifo.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _INTERLEAVER_FIFO_H_ +#define _INTERLEAVER_FIFO_H_ + + +#include +#include + +/*! + * \brief template class for interleaver fifo + */ + +template +class interleaver_fifo { + public: + + interleaver_fifo (unsigned int size); + ~interleaver_fifo (); + + //! reset interleaver (flushes contents and resets commutator) + void reset (); + + //! stuff a symbol into the fifo and return the oldest + symbol_type stuff (symbol_type input){ + if (m_size == 0) + return input; + + symbol_type retval = m_fifo[m_position]; + m_fifo[m_position] = input; + m_position++; + if (m_position >= m_size) + m_position = 0; + + return retval; + } + +protected: + unsigned int m_size; + unsigned int m_position; + symbol_type *m_fifo; +}; + +template +interleaver_fifo::interleaver_fifo (unsigned int size) +{ + m_size = size; + m_position = 0; + m_fifo = new symbol_type[size]; + memset (m_fifo, 0, m_size * sizeof (symbol_type)); +} + +template +interleaver_fifo::~interleaver_fifo () +{ + delete [] m_fifo; +} + +template void +interleaver_fifo::reset () +{ + m_position = 0; + memset (m_fifo, 0, m_size * sizeof (symbol_type)); +} + +#endif /* _INTERLEAVER_FIFO_H_ */ diff --git a/gr-atsc/src/lib/plinfo.cc b/gr-atsc/src/lib/plinfo.cc new file mode 100644 index 00000000..b28a13d5 --- /dev/null +++ b/gr-atsc/src/lib/plinfo.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +void +plinfo::delay (plinfo &out, const plinfo &in, int nsegs_of_delay) +{ + assert (in.regular_seg_p ()); + assert (nsegs_of_delay >= 0); + + int s = in.segno (); + if (in.in_field2_p ()) + s += ATSC_DSEGS_PER_FIELD; + + s -= nsegs_of_delay; + if (s < 0) + s += 2 * ATSC_DSEGS_PER_FIELD; + + assert (0 <= s && s < 2 * ATSC_DSEGS_PER_FIELD); + + if (s < ATSC_DSEGS_PER_FIELD) + out.set_regular_seg (false, s); // field 1 + else + out.set_regular_seg (true, s - ATSC_DSEGS_PER_FIELD); // field 2 +} + +void +plinfo::sanity_check (const plinfo &x) +{ + // basic sanity checks... + assert (x.segno () >= 0); + assert (x.segno () < (unsigned) ATSC_DSEGS_PER_FIELD); + assert ((x.flags () & ~0x3f) == 0); + + assert (x.regular_seg_p () ^ x.field_sync_p ()); + assert ((x.segno () != 0) ^ x.first_regular_seg_p ()); +} + diff --git a/gr-atsc/src/lib/qa_atsci.cc b/gr-atsc/src/lib/qa_atsci.cc new file mode 100644 index 00000000..bc7fba3a --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci.cc @@ -0,0 +1,63 @@ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This class gathers together all the test cases for the atsc + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CppUnit::TestSuite * +qa_atsc::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("atsc"); + + s->addTest (qa_atsci_randomizer::suite ()); + s->addTest (qa_atsci_reed_solomon::suite ()); + s->addTest (qa_interleaver_fifo::suite ()); + s->addTest (qa_convolutional_interleaver::suite ()); + s->addTest (qa_atsci_data_interleaver::suite ()); + s->addTest (qa_atsci_basic_trellis_encoder::suite ()); + s->addTest (qa_atsci_sliding_correlator::suite ()); + s->addTest (qa_atsci_fake_single_viterbi::suite ()); + s->addTest (qa_atsci_single_viterbi::suite ()); + s->addTest (qa_atsci_trellis_encoder::suite ()); + s->addTest (qa_atsci_viterbi_decoder::suite ()); + s->addTest (qa_atsci_fs_correlator::suite ()); + s->addTest (qa_atsci_equalizer_nop::suite ()); + + return s; +} diff --git a/gr-atsc/src/lib/qa_atsci.h b/gr-atsc/src/lib/qa_atsci.h new file mode 100644 index 00000000..cf861a8b --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_H_ +#define _QA_ATSC_H_ + +#include + +//! collect all the tests for the dtv directory + +class qa_atsc { + public: + //! return suite of tests for all of dtv directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_ATSC_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.cc b/gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.cc new file mode 100644 index 00000000..c6212f30 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +void +qa_atsci_basic_trellis_encoder::t0 () +{ + const static unsigned char in[14] = { + 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 2, 3 + }; + + const static unsigned char expected_out[14] = { + 0, 2, 3, 1, 1, 3, 0, 1, 2, 0, 0, 2, 5, 2 + }; + + for (unsigned i = 0; i < sizeof (in); i++) + CPPUNIT_ASSERT_EQUAL ((int) expected_out[i], enc.encode (in[i])); + + // reset encoder and test again. + + enc.reset (); + for (unsigned i = 0; i < sizeof (in); i++) + CPPUNIT_ASSERT_EQUAL ((int) expected_out[i], enc.encode (in[i])); +} + + +void +qa_atsci_basic_trellis_encoder::t1 () +{ + // Print data to externally check distribution. + // looks OK. +#if 0 + srandom (27); + + for (int i = 0; i < 8192; i++){ + int t = (random () >> 10) & 0x3; // 2 random bits + printf ("%d %d\n", t, enc.encode (t)); + } +#endif +} diff --git a/gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.h b/gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.h new file mode 100644 index 00000000..5d76f5ea --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_ATSC_BASIC_TRELLIS_ENCODER_H_ +#define _QA_ATSC_BASIC_TRELLIS_ENCODER_H_ + +#include +#include + +#include + +class qa_atsci_basic_trellis_encoder : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_atsci_basic_trellis_encoder); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + atsci_basic_trellis_encoder enc; + + void t0 (); + void t1 (); +}; + +#endif /* _QA_ATSC_BASIC_TRELLIS_ENCODER_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_data_interleaver.cc b/gr-atsc/src/lib/qa_atsci_data_interleaver.cc new file mode 100644 index 00000000..c09d1231 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_data_interleaver.cc @@ -0,0 +1,196 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + + +/*! + * write an easy to identify pattern into the packet + */ +void +qa_atsci_data_interleaver::init_test_packet (int counter, + atsc_mpeg_packet_rs_encoded &out) +{ + out.data[0] = 0xf0; + out.data[1] = 0xff; + out.data[2] = (counter >> 8) & 0xff; + out.data[3] = counter & 0xff; + + for (int i = 4; i < 205; i++) + out.data[i] = i; + + out.data[205] = 0xa0; + out.data[206] = 0xaf; +} + +void +qa_atsci_data_interleaver::print_packet (FILE *fp, + int frame_number, + int field_number, + int segment_number, + const atsc_mpeg_packet_rs_encoded &in) +{ + fprintf (fp, "%04d:%d:%03d ", frame_number, field_number, segment_number); + + const unsigned char *p = &in.data[0]; + for (int i = 0; i < 8; i++) + fprintf (fp, "%02X", p[i]); + + fprintf (fp, " "); + p = &in.data[8]; + for (int i = 0; i < 8; i++) + fprintf (fp, "%02X", p[i]); + + + fprintf (fp, " ... "); + p = &in.data[191]; + for (int i = 0; i < 8; i++) + fprintf (fp, "%02X", p[i]); + + fprintf (fp, " "); + p = &in.data[199]; + for (int i = 0; i < 8; i++) + fprintf (fp, "%02X", p[i]); + + fprintf (fp, "\n"); +} + +void +qa_atsci_data_interleaver::chk_assert (const atsc_mpeg_packet_rs_encoded &expected, + const atsc_mpeg_packet_rs_encoded &actual) +{ + if (expected == actual) + return; + + FILE *fp = stderr; + + fprintf (fp, "Expected: "); + print_packet (fp, 0, 0, 0, expected); + + fprintf (fp, "Actual: "); + print_packet (fp, 0, 0, 0, actual); + + CPPUNIT_ASSERT (expected == actual); +} + +void +qa_atsci_data_interleaver::t0 () +{ + int counter = 0; + atsc_mpeg_packet_rs_encoded in, enc, out; + atsc_mpeg_packet_rs_encoded zero; + + memset (&zero, 0, sizeof (zero)); + + for (int frame = 0; frame < 4; frame++){ + for (int field = 0; field < 2; field++){ + for (int segment = 0; segment < 312; segment++, counter++){ + + // build test packet + init_test_packet (counter, in); + in.pli.set_regular_seg (field == 1, segment); + + // interleave it + outbound.interleave (enc, in); + + // deinterleave it + inbound.deinterleave (out, enc); + + if (counter < 52) + // CPPUNIT_ASSERT (zero == out); + chk_assert (zero, out); + + else if (counter >= 52){ + atsc_mpeg_packet_rs_encoded expected; + init_test_packet (counter - 52, expected); + // CPPUNIT_ASSERT (expected == out); + chk_assert (expected, out); + } + } + } + } +} + +// +// Note, this assumes that the interleaver and deinterleaver +// have the state left by t0. +// +// This test pushes crap into the interleaver, and then confirms that +// the deinterleaver recovers. This would be part of what you'd see +// on a channel change. +// + +void +qa_atsci_data_interleaver::t1 () +{ + int counter = 0; + atsc_mpeg_packet_rs_encoded in, enc, out; + atsc_mpeg_packet_rs_encoded zero; + + memset (&zero, 0, sizeof (zero)); + + static const int NCRAP = 13; + + // push NCRAP segments of crap into the interleaver, + // but don't change the deinterleaver state + + for (int i = 0; i < NCRAP; i++){ + init_test_packet (i + 2758, in); + in.pli.set_regular_seg (false, i + 5); + + outbound.interleave (enc, in); + } + + // now run the normal test. + // we should get good segments after NCRAP + 52 + + int starting_counter = 3141; + counter = starting_counter; + + for (int frame = 0; frame < 4; frame++){ + for (int field = 0; field < 2; field++){ + for (int segment = 0; segment < 312; segment++, counter++){ + + // build test packet + init_test_packet (counter, in); + in.pli.set_regular_seg (field == 1, segment); + + // interleave it + outbound.interleave (enc, in); + + // deinterleave it + inbound.deinterleave (out, enc); + + if (counter < starting_counter + 52 + NCRAP){ + // don't care... + } + else if (counter >= starting_counter + 52 + NCRAP){ + atsc_mpeg_packet_rs_encoded expected; + init_test_packet (counter - 52, expected); + // CPPUNIT_ASSERT (expected == out); + chk_assert (expected, out); + } + } + } + } +} diff --git a/gr-atsc/src/lib/qa_atsci_data_interleaver.h b/gr-atsc/src/lib/qa_atsci_data_interleaver.h new file mode 100644 index 00000000..9d72f1a9 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_data_interleaver.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_DATA_INTERLEAVER_H_ +#define _QA_ATSC_DATA_INTERLEAVER_H_ + +#include +#include +#include + +#include + +class qa_atsci_data_interleaver : public CppUnit::TestCase { + public: + + void setUp (){ + outbound.reset (); + inbound.reset (); + } + + CPPUNIT_TEST_SUITE (qa_atsci_data_interleaver); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + atsci_data_interleaver outbound; + atsci_data_deinterleaver inbound; + + void t0 (); + void t1 (); + + void init_test_packet (int counter, atsc_mpeg_packet_rs_encoded &out); + void print_packet (FILE *fp, int frame_number, int field_number, int segment_number, + const atsc_mpeg_packet_rs_encoded &in); + void chk_assert (const atsc_mpeg_packet_rs_encoded &expected, + const atsc_mpeg_packet_rs_encoded &actual); +}; + + +#endif /* _QA_ATSC_DATA_INTERLEAVER_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_equalizer_nop.cc b/gr-atsc/src/lib/qa_atsci_equalizer_nop.cc new file mode 100644 index 00000000..a12f2536 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_equalizer_nop.cc @@ -0,0 +1,246 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cerr; +using std::endl; + + +static const int SYMBOLS_PER_FIELD = (ATSC_DSEGS_PER_FIELD + 1) * ATSC_DATA_SEGMENT_LENGTH; +static const int PAD = 500; +static const int NFIELDS = 2; + +static const int INPUT_SIZE = PAD + (NFIELDS * SYMBOLS_PER_FIELD); + +static float +bin_map (int bit) +{ + return bit ? +5 : -5; +} + +static void +init_tags (atsc::syminfo *tags, int segnum, int fieldnum) +{ + int i; + + for (i = 0; i < ATSC_DATA_SEGMENT_LENGTH; i++){ + tags[i].symbol_num = i; + tags[i].segment_num = segnum; + tags[i].field_num = fieldnum; + tags[i].valid = 1; + } +} + +static void +init_data_seg (float *p, atsc::syminfo *tags, int v, int segnum, int fieldnum) +{ + init_tags (tags, segnum, fieldnum); + + int i = 0; + + p[i++] = bin_map (1); // data segment sync pulse + p[i++] = bin_map (0); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + + for (; i < ATSC_DATA_SEGMENT_LENGTH; i++) + p[i] = (float) (i + v); +} + +static void +init_field_sync_tags (atsc::syminfo *tags, int fieldnum) +{ + init_tags (tags, atsc::SI_FIELD_SYNC_SEGMENT_NUM, fieldnum); +} + +static void +init_field_sync_common (float *p, int mask) + +{ + int i = 0; + + p[i++] = bin_map (1); // data segment sync pulse + p[i++] = bin_map (0); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + + for (int j = 0; j < 511; j++) // PN511 + p[i++] = bin_map (atsc_pn511[j]); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map (atsc_pn63[j]); + + for (int j = 0; j < 63; j++) // PN63, toggled on field 2 + p[i++] = bin_map (atsc_pn63[j] ^ mask); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map (atsc_pn63[j]); + + p[i++] = bin_map (0); // 24 bits of VSB8 mode identifiera + p[i++] = bin_map (0); + p[i++] = bin_map (0); + p[i++] = bin_map (0); + + p[i++] = bin_map (1); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + p[i++] = bin_map (0); + + p[i++] = bin_map (0); + p[i++] = bin_map (1); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + + p[i++] = bin_map (1); + p[i++] = bin_map (1); + p[i++] = bin_map (1); + p[i++] = bin_map (1); + + p[i++] = bin_map (0); + p[i++] = bin_map (1); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + + p[i++] = bin_map (1); + p[i++] = bin_map (0); + p[i++] = bin_map (1); + p[i++] = bin_map (0); + + + for (int j = 0; j < 92; j++) // 92 more bits + p[i++] = bin_map (atsc_pn63[j % 63]); + + // now copy the last 12 symbols of the previous segment + // bogus fill + + for (int j = 0; j < 12; j++) + p[i++] = bin_map (j & 1); + + assert (i == ATSC_DATA_SEGMENT_LENGTH); +} + +void +qa_atsci_equalizer_nop::setUp () +{ + eq = new atsci_equalizer_nop (); +} + +void +qa_atsci_equalizer_nop::tearDown () +{ + delete eq; + eq = 0; +} + +static void +setup_test_data (float *data, atsc::syminfo *tags) +{ + int mask = 0; + int i = 0; + + for (i = 0; i < PAD; i++){ + data[i] = (float) i; + tags[i].symbol_num = 13 + i; + tags[i].segment_num = 17; + tags[i].field_num = 0; + tags[i].valid = 1; + } + + for (int nfields = 0; nfields < NFIELDS; nfields++){ + init_field_sync_common (&data[i], mask); + init_field_sync_tags (&tags[i], mask); + i += ATSC_DATA_SEGMENT_LENGTH; + + for (int segnum = 0; segnum < 312; segnum++){ + init_data_seg (&data[i], &tags[i], i, segnum, mask); + i += ATSC_DATA_SEGMENT_LENGTH; + } + mask ^= 1; + } + assert (i == INPUT_SIZE); +} + +void +qa_atsci_equalizer_nop::t0 () +{ + // these are dynamically allocated because they are bigger + // than the default stack limit. + + float *input_data = new float[INPUT_SIZE]; + atsc::syminfo *input_tags = new atsc::syminfo[INPUT_SIZE]; + float *output_data = new float[INPUT_SIZE]; + + try { + + memset (input_data, 0, sizeof (input_data)); + memset (input_tags, 0, sizeof (input_tags)); + memset (output_data, 0, sizeof (output_data)); + + setup_test_data (input_data, input_tags); + + eq->filter (input_data, input_tags, + output_data, INPUT_SIZE); + + + // now check that data values got copied correctly + + for (int i = 0; i < INPUT_SIZE; i++){ + + if (input_tags[i].segment_num == atsc::SI_FIELD_SYNC_SEGMENT_NUM){ + // ignore entire field sync data segment + } + else if (input_tags[i].symbol_num <= 3){ + // ignore 4 symbols of data segment sync (+5, -5, -5, +5) + } + else { + if (output_data[i] != (float) i){ + cerr << "output_data[" << i << "] == " << output_data[i] << endl; + CPPUNIT_ASSERT_DOUBLES_EQUAL ((float) i, output_data[i], 1e-6); + } + } + } + + delete [] input_data; + delete [] input_tags; + delete [] output_data; + } + + catch ( ... ){ + delete [] input_data; + delete [] input_tags; + delete [] output_data; + } +} + +void +qa_atsci_equalizer_nop::t1 () +{ + // think of another test... +} diff --git a/gr-atsc/src/lib/qa_atsci_equalizer_nop.h b/gr-atsc/src/lib/qa_atsci_equalizer_nop.h new file mode 100644 index 00000000..cfe8920e --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_equalizer_nop.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_EQUALIZER_NOP_H_ +#define _QA_ATSC_EQUALIZER_NOP_H_ + +#include +#include + +class atsci_equalizer; + +class qa_atsci_equalizer_nop : public CppUnit::TestCase { +private: + atsci_equalizer *eq; + +public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_atsci_equalizer_nop); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + +private: + + void t0 (); + void t1 (); + +}; + +#endif /* _QA_ATSC_EQUALIZER_NOP_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_fake_single_viterbi.cc b/gr-atsc/src/lib/qa_atsci_fake_single_viterbi.cc new file mode 100644 index 00000000..f0ff6356 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_fake_single_viterbi.cc @@ -0,0 +1,143 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + + +static const int NTRIALS = 50; +static const int MAXERRORS = 10; +static const int NN = 200; + +static const int MAXDIBIT = 3; + +void +qa_atsci_fake_single_viterbi::encode_block (unsigned char *out, unsigned char *in, + unsigned int n) +{ + for (unsigned int i = 0; i < n; i++) { + out[i] = encoder.encode(in[i]); + } +} + + +void +qa_atsci_fake_single_viterbi::decode_block (unsigned char *out, unsigned char *in, + unsigned int n) +{ + for (unsigned int i = 0; i < n; i++) { + out[i] = decoder.decode ((2*in[i]-7) + noise ()); + } +} + +float +qa_atsci_fake_single_viterbi::noise () +{ +#if 1 + return 2.0 * ((float) random () / RANDOM_MAX - 0.5);; +#else + return 0; +#endif +} + +void +qa_atsci_fake_single_viterbi::t0 () +{ + int blocklen = NN; + unsigned char in[blocklen]; + unsigned char enc[blocklen]; + unsigned char out[blocklen]; + int decoder_errors = 0; + int delay = decoder.delay (); + int i; + + // printf (" Delay is %d.\n", delay); + + srandom (27); // reproducable sequence of "random" values + + for (int nt = 0; nt < NTRIALS; nt++){ + + // load block with random data and encode + + for (i = 0; i < (blocklen-delay); i++) + in[i] = random () & MAXDIBIT; + for ( ; i < blocklen; i++) + in[i] = 0; /* To empty the delay buffers */ + + encoder.reset (); + encode_block (enc, in, blocklen); + + decoder.reset (); + + // decode the block + decode_block (out, enc, blocklen); + + // int offset = delay/4; + int offset = 2; + bool differs = (memcmp (in+offset, + out+delay+offset, blocklen-(delay+offset))); + + // initial values after reset are 0 + for (i = 0; i < delay; i++){ + if (out[i] != 0) + printf (" initial output at %i is %X, not 0\n", + i, out[i]); + } + + if (differs){ + printf (" incorrect data, trial #%d\n", nt); + + printf ("\n Erroneous result dibits:"); + for (int erri = 0; erri < (NN-delay); erri++) { + if (in[erri] != out[erri+delay]) + printf (" %d", erri); + } + printf ("\n In: "); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %d", in[erri]); + } + printf ("\n Out: "); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %d", out[erri+delay]); + } + printf ("\n Errs:"); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %c", (in[erri] != out[erri+delay])? '*': ' '); + } + printf ("\n THIS IS A REAL PROBLEM.\n"); + decoder_errors++; + } + } + + printf (" Summary: %d decoder errors out of %d trials.\n", + decoder_errors, NTRIALS); + + CPPUNIT_ASSERT (decoder_errors == 0); +} + diff --git a/gr-atsc/src/lib/qa_atsci_fake_single_viterbi.h b/gr-atsc/src/lib/qa_atsci_fake_single_viterbi.h new file mode 100644 index 00000000..2161d5d9 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_fake_single_viterbi.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_FAKE_SINGLE_VITERBI_H +#define _QA_ATSC_FAKE_SINGLE_VITERBI_H + +#include +#include + +#include +#include + +class qa_atsci_fake_single_viterbi : public CppUnit::TestCase { + private: + atsci_fake_single_viterbi decoder; + atsci_basic_trellis_encoder encoder; + + CPPUNIT_TEST_SUITE (qa_atsci_fake_single_viterbi); + CPPUNIT_TEST (t0); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t0 (); + + void encode_block(unsigned char *out, unsigned char *in, unsigned n); + void decode_block(unsigned char *out, unsigned char *in, unsigned n); + float noise (); + +}; + +#endif /* _QA_ATSC_FAKE_SINGLE_VITERBI_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_fs_correlator.cc b/gr-atsc/src/lib/qa_atsci_fs_correlator.cc new file mode 100644 index 00000000..97d45f5c --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_fs_correlator.cc @@ -0,0 +1,255 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + + +static float +bin_map (int bit) +{ + return bit ? +5 : -5; +} + +static void +init_field_sync_common (float *p, int mask) + +{ + int i = 0; + + p[i++] = bin_map(1); // data segment sync pulse + p[i++] = bin_map(0); + p[i++] = bin_map(0); + p[i++] = bin_map(1); + + for (int j = 0; j < 511; j++) // PN511 + p[i++] = bin_map(atsc_pn511[j]); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map(atsc_pn63[j]); + + for (int j = 0; j < 63; j++) // PN63, toggled on field 2 + p[i++] = bin_map(atsc_pn63[j] ^ mask); + + for (int j = 0; j < 63; j++) // PN63 + p[i++] = bin_map(atsc_pn63[j]); + + p[i++] = bin_map(0); // 24 bits of VSB8 mode identifiera + p[i++] = bin_map(0); + p[i++] = bin_map(0); + p[i++] = bin_map(0); + + p[i++] = bin_map(1); + p[i++] = bin_map(0); + p[i++] = bin_map(1); + p[i++] = bin_map(0); + + p[i++] = bin_map(0); + p[i++] = bin_map(1); + p[i++] = bin_map(0); + p[i++] = bin_map(1); + + p[i++] = bin_map(1); + p[i++] = bin_map(1); + p[i++] = bin_map(1); + p[i++] = bin_map(1); + + p[i++] = bin_map(0); + p[i++] = bin_map(1); + p[i++] = bin_map(0); + p[i++] = bin_map(1); + + p[i++] = bin_map(1); + p[i++] = bin_map(0); + p[i++] = bin_map(1); + p[i++] = bin_map(0); + + + for (int j = 0; j < 92; j++) // 92 more bits + p[i++] = bin_map(atsc_pn63[j % 63]); + + // now copy the last 12 symbols of the previous segment + // bogus pad for this test... + + for (int j = 0; j < 12; j++) + p[i++] = bin_map(j & 1); + + assert (i == ATSC_DATA_SEGMENT_LENGTH); +} + +inline static void +init_field_sync_1 (float *s) +{ + init_field_sync_common (s, 0); +} + +inline static void +init_field_sync_2 (float *s) +{ + init_field_sync_common (s, 1); +} + +static void +cause_errors (float *p, int nerrs1, int nerrs2) +{ + static const int offset1 = 4; // offset to PN 511 + static const int offset2 = 578; // offset to 2nd PN 63 + + for (int i = 0; i < nerrs1; i++){ // flip nerrs1 bits in PN 511 + p[i + offset1] = -p[i + offset1]; + } + + for (int i = 0; i < nerrs2; i++){ // flip nerrs2 bits in PN 63 + p[i + offset2] = -p[i + offset2]; + } +} + + +void +qa_atsci_fs_correlator::setUp () +{ + fsc = create_atsci_fs_correlator (); +} + +void +qa_atsci_fs_correlator::tearDown () +{ + delete fsc; + fsc = 0; +} + + +// check sample fifo + +void +qa_atsci_fs_correlator::t0 () +{ + int delay = fsc->delay (); + int i; + float output_sample, output_tag; + + for (i = 0; i < delay; i++){ + fsc->filter ((float) i, &output_sample, &output_tag); + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, output_sample, 1e-6); + CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::NORMAL, output_tag, 1e-6); + } + + for (; i < delay + 5000; i++){ + fsc->filter ((float) i, &output_sample, &output_tag); + CPPUNIT_ASSERT_DOUBLES_EQUAL ((float) (i - delay), output_sample, 1e-6); + CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::NORMAL, output_tag, 1e-6); + } +} + +void +qa_atsci_fs_correlator::util (int which_field, int nerrs1, int nerrs2) +{ + static const int PAD = 303; + static const int ISIZE = 4096; + int delay = fsc->delay (); + float output_sample, output_tag; + int i; + float input[ISIZE]; + + fsc->reset (); // known starting conditions + + // build input + + for (i = 0; i < PAD; i++) + input[i] = uniform () * 7; + + init_field_sync_common (&input[i], which_field); + cause_errors (&input[i], nerrs1, nerrs2); + i += ATSC_DATA_SEGMENT_LENGTH; + + for (; i < ISIZE; i++) + input[i] = uniform () * 7; + + // run the input and check + + for (i = 0; i < ISIZE; i++){ + fsc->filter (input[i], &output_sample, &output_tag); + if (i == delay + PAD){ // should be field sync + if (which_field == 0) + CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::START_FIELD_SYNC_1, output_tag, 1e-6); + else + CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::START_FIELD_SYNC_2, output_tag, 1e-6); + } + else { + CPPUNIT_ASSERT_DOUBLES_EQUAL (atsc_sync_tag::NORMAL, output_tag, 1e-6); + } + } +} + + +void +qa_atsci_fs_correlator::t1 () +{ + util (0, 0, 0); +} + +void +qa_atsci_fs_correlator::t2 () +{ + util (1, 0, 0); +} + +void +qa_atsci_fs_correlator::t3 () +{ + for (int nerrs1 = 0; nerrs1 < 20; nerrs1++){ + for (int nerrs2 = 0; nerrs2 < 5; nerrs2++){ + util (0, nerrs1, nerrs2); + } + } +} + +void +qa_atsci_fs_correlator::t4 () +{ + for (int nerrs1 = 0; nerrs1 < 5; nerrs1++){ + for (int nerrs2 = 0; nerrs2 < 5; nerrs2++){ + util (1, nerrs1, nerrs2); + } + } +} + diff --git a/gr-atsc/src/lib/qa_atsci_fs_correlator.h b/gr-atsc/src/lib/qa_atsci_fs_correlator.h new file mode 100644 index 00000000..a38a5e20 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_fs_correlator.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_ATSC_FS_CORRELATOR_H_ +#define _QA_ATSC_FS_CORRELATOR_H_ + +#include +#include + +class atsci_fs_correlator; + +class qa_atsci_fs_correlator : public CppUnit::TestCase { +private: + atsci_fs_correlator *fsc; + + public: + + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_atsci_fs_correlator); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST_SUITE_END (); + + private: + + void util (int which_field, int nerr1, int nerr2); + + void t0 (); + void t1 (); + void t2 (); + void t3 (); + void t4 (); +}; + +#endif /* _QA_ATSC_FS_CORRELATOR_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_randomizer.cc b/gr-atsc/src/lib/qa_atsci_randomizer.cc new file mode 100644 index 00000000..46b228f0 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_randomizer.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include + +static unsigned int expected_initial_states[] = { + 0x018f, + 0xd3db, + 0xbaf1, + 0x8e64, + 0x4732, + 0x2399, + 0xc2d0, + 0x6168 +}; + +static unsigned char expected_initial_values[] = { + 0xc0, + 0x6d, + 0x3f, + 0x99, + 0x38, + 0x6a, + 0x29, + 0x52 +}; + +#define NELEMENTS(ary) ((sizeof (ary)) / sizeof (ary[0])) + +void +qa_atsci_randomizer::t0_compare_output_maps () +{ + for (int i = 0; i < 0x10000; i++){ + unsigned char slow = atsci_randomizer::slow_output_map(i); + unsigned char fast = atsci_randomizer::fast_output_map(i); + CPPUNIT_ASSERT_EQUAL (slow, fast); + } +} + +void +qa_atsci_randomizer::t1_initial_states () +{ + // LFSR should start with expected states + + for (unsigned int i = 0; i < NELEMENTS (expected_initial_values); i++){ + unsigned int got = randomizer.state(); + randomizer.clk (); + CPPUNIT_ASSERT_EQUAL (expected_initial_states[i], got); + } +} + +void +qa_atsci_randomizer::t2_initial_values () +{ + // LFSR should start with expected values + + for (unsigned int i = 0; i < NELEMENTS (expected_initial_values); i++){ + unsigned char got = randomizer.output_and_clk (); + CPPUNIT_ASSERT_EQUAL (expected_initial_values[i], got); + } +} + +void +qa_atsci_randomizer::t3_reset () +{ + // LFSR should start with expected values + + for (unsigned int i = 0; i < NELEMENTS (expected_initial_values); i++){ + unsigned char got = randomizer.output_and_clk (); + CPPUNIT_ASSERT_EQUAL (expected_initial_values[i], got); + } + + randomizer.reset (); // reset LFSR + + // and now should repeat expected values + + for (unsigned int i = 0; i < NELEMENTS (expected_initial_values); i++){ + unsigned char got = randomizer.output_and_clk (); + CPPUNIT_ASSERT_EQUAL (expected_initial_values[i], got); + } +} + +void +qa_atsci_randomizer::t4_high_level () +{ + static const int N = 5; + + atsc_mpeg_packet in[N]; + atsc_mpeg_packet_no_sync middle[N]; + atsc_mpeg_packet out[N]; + + memset (in, 0, sizeof (in)); + memset (middle, 0, sizeof (middle)); + memset (out, 0, sizeof (out)); + + // setup input test data + + int counter = 0xff; + for (int n = 0; n < N; n++){ + in[n].data[0] = MPEG_SYNC_BYTE; + for (int i = 0; i < ATSC_MPEG_DATA_LENGTH; i++) + in[n].data[i + 1] = counter++; + } + + // randomize N packets + + for (int n = 0; n < N; n++) + randomizer.randomize (middle[n], in[n]); + + // reset LFSR and derandomize N packets + + randomizer.reset (); // reset LFSR + + for (int n = 0; n < N; n++) + randomizer.derandomize (out[n], middle[n]); + + // compare packets + + for (int n = 0; n < N; n++){ + CPPUNIT_ASSERT (in[n] == out[n]); + } +} + diff --git a/gr-atsc/src/lib/qa_atsci_randomizer.h b/gr-atsc/src/lib/qa_atsci_randomizer.h new file mode 100644 index 00000000..5a805df8 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_randomizer.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _QA_ATSC_RANDOMIZER_H_ +#define _QA_ATSC_RANDOMIZER_H_ + +#include +#include + +#include + +class qa_atsci_randomizer : public CppUnit::TestCase { + private: + atsci_randomizer randomizer; + + public: + + void setUp (){ + // nop + } + + void tearDown (){ + // nop + } + + CPPUNIT_TEST_SUITE (qa_atsci_randomizer); + CPPUNIT_TEST (t0_compare_output_maps); + CPPUNIT_TEST (t1_initial_states); + CPPUNIT_TEST (t2_initial_values); + CPPUNIT_TEST (t3_reset); + CPPUNIT_TEST (t4_high_level); + CPPUNIT_TEST_SUITE_END (); + + + private: + void t0_compare_output_maps (); + void t1_initial_states (); + void t2_initial_values (); + void t3_reset (); + void t4_high_level (); + +}; + +#endif /* _QA_ATSC_RANDOMIZER_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_reed_solomon.cc b/gr-atsc/src/lib/qa_atsci_reed_solomon.cc new file mode 100644 index 00000000..8b52359e --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_reed_solomon.cc @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + + +static const int NROOTS = 20; +static const int NTRIALS = 100; +static const int NN = ATSC_MPEG_RS_ENCODED_LENGTH; + +void +qa_atsci_reed_solomon::t0_reed_solomon () +{ + atsc_mpeg_packet_no_sync in; + atsc_mpeg_packet_rs_encoded enc; + atsc_mpeg_packet_no_sync out; + int derrors; + int errlocs[NN]; + int errval; + int errloc; + int decoder_errors = 0; + + for (int nt = 0; nt < NTRIALS; nt++){ + + // test up to the error correction capacity of the code + for (int errors = 0; errors <= NROOTS*2; errors++){ + + // load block with random data and encode + + for (int i = 0; i < ATSC_MPEG_DATA_LENGTH; i++) + in.data[i] = random () & 0xff; + + rs.encode (enc, in); + + memset (errlocs, 0, sizeof (errlocs)); + + for (int i = 0; i < errors; i++){ + + do { + errval = random () & 0xff; + } while (errval == 0); // error value must be non-zero + + do { + errloc = random () % NN; + } while (errlocs[errloc] != 0); // must not choose the same location twice + + errlocs[errloc] = 1; + + enc.data[errloc] ^= errval; // cause the error + } + + // decode the errored block + derrors = rs.decode (out, enc); + + if (errors <= NROOTS/2) { + // We should have handled all these errors and corrected them. + if (derrors != errors){ + fprintf (stderr, " decoder says %d errors, true number is %d\n", derrors, errors); + decoder_errors++; + } + + if (in != out){ + fprintf (stderr, " uncorrected errors!\n"); + decoder_errors++; + } + } else { + // We have been given more errors than we could cope with. Make + // sure that we detect these errors. Complain if we get incorrect + // block but don't say it's incorrect. + bool differs = (in != out); + + if (differs && (derrors < 0)) { + // Reported uncorrectable error accurately + } else if (differs) { + fprintf (stderr, + " decoder found %d of %d errors, but incorrect block\n", + derrors, errors); + } else { + fprintf (stderr, " decoder corrected %d of %d errors unexpectedly\n", + derrors, errors); + } + } + } + } + + CPPUNIT_ASSERT (decoder_errors == 0); +} diff --git a/gr-atsc/src/lib/qa_atsci_reed_solomon.h b/gr-atsc/src/lib/qa_atsci_reed_solomon.h new file mode 100644 index 00000000..d78aa747 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_reed_solomon.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_REED_SOLOMON_H_ +#define _QA_ATSC_REED_SOLOMON_H_ + +#include +#include + +#include + +class qa_atsci_reed_solomon : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_atsci_reed_solomon); + CPPUNIT_TEST (t0_reed_solomon); + CPPUNIT_TEST_SUITE_END (); + + private: + atsci_reed_solomon rs; + + void t0_reed_solomon (); +}; + +#endif /* _QA_ATSC_REED_SOLOMON_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc new file mode 100644 index 00000000..ea94e693 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc @@ -0,0 +1,283 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + + +static const int NTRIALS = 50; +static const int MAXERRORS = 10; +static const int NN = 200; + +static const int MAXDIBIT = 3; + +void +qa_atsci_single_viterbi::encode_block (unsigned char *out, unsigned char *in, + unsigned int n) +{ + for (unsigned int i = 0; i < n; i++) { + out[i] = encoder.encode(in[i]); + } +} + + +void +qa_atsci_single_viterbi::decode_block (unsigned char *out, unsigned char *in, + unsigned int n, float noise_factor) +{ + for (unsigned int i = 0; i < n; i++) { + out[i] = decoder.decode((2*in[i]-7) + noise () * noise_factor); + } +} + +float +qa_atsci_single_viterbi::noise () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +void +qa_atsci_single_viterbi::t0 () +{ + int blocklen = NN; + unsigned char in[blocklen]; + unsigned char enc[blocklen]; + unsigned char out[blocklen]; + int decoder_errors = 0; + int delay = decoder.delay (); + int i; + + // printf (" Delay is %d.\n", delay); + + srandom (27); // reproducable sequence of "random" values + + for (int nt = 0; nt < NTRIALS; nt++){ + + // load block with random data and encode + + for (i = 0; i < (blocklen-delay); i++) + in[i] = random () & MAXDIBIT; + for ( ; i < blocklen; i++) + in[i] = 0; /* To empty the delay buffers */ + + encoder.reset (); + encode_block (enc, in, blocklen); + + decoder.reset (); + + // decode the block + decode_block (out, enc, blocklen, 1.0); + + // int offset = delay/4; + int offset = 2; + bool differs = (memcmp (in+offset, + out+delay+offset, blocklen-(delay+offset))); + + // initial values after reset are 0 + for (i = 0; i < delay; i++){ + if (out[i] != 0) + printf (" initial output at %i is %X, not 0\n", + i, out[i]); + } + + if (differs){ + printf (" incorrect data\n"); + + printf ("\n Erroneous result dibits:"); + for (int erri = 0; erri < (NN-delay); erri++) { + if (in[erri] != out[erri+delay]) + printf (" %d", erri); + } + printf ("\n In: "); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %d", in[erri]); + } + printf ("\n Out: "); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %d", out[erri+delay]); + } + printf ("\n Errs:"); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %c", (in[erri] != out[erri+delay])? '*': ' '); + } + printf ("\n THIS IS A REAL PROBLEM.\n"); + decoder_errors++; + } + } + + printf (" Summary: %d decoder errors out of %d trials.\n", + decoder_errors, NTRIALS); + + CPPUNIT_ASSERT (decoder_errors == 0); +} + +void +qa_atsci_single_viterbi::t1 () +{ + int blocklen = NN; + unsigned char in[blocklen]; + unsigned char enc[blocklen]; + unsigned char out[blocklen]; + int errlocs[NN]; + int errval; + int errloc; + int decoder_errors = 0; + int delay = decoder.delay (); + int i; + + // printf (" Delay is %d.\n", delay); + + srandom (1); // reproducable sequence of "random" values + + for (int nt = 0; nt < NTRIALS; nt++){ + + // test up to the error correction capacity of the code + for (int errors = 0; errors <= MAXERRORS; errors++){ + + // load block with random data and encode + + for (i = 0; i < (blocklen-delay); i++) + in[i] = random () & MAXDIBIT; + for ( ; i < blocklen; i++) + in[i] = 0; /* To empty the delay buffers */ + + encoder.reset (); + encode_block (enc, in, blocklen); + + // Now generate 0 to N errors in the encoded symbols. + // + // If we restrict ourselves to damaging the low-order bit, + // our decoder finds and fixes the vast majority of errors. + // + // If we munge any or all of the three bits of the symbol, + // our decoder frequently gets the wrong data even with a single + // error. + // + // Let's see what it can do with just the two low-order bits. + // + // ALSO: Don't let any error be within 12 spots of another + // error. This simulates the muxed behavior. + + memset (errlocs, 0, sizeof (errlocs)); + + for (int j = 0; j < errors; j++){ + + do { + // errval = random () & 3; // FIXME: 1; // FIXME: MAXSYM; + errval = random () & 1; // FIXME: 1; // FIXME: MAXSYM; + } while (errval == 0); // error value must be non-zero + + // Don't insert errors in the first delay slot, since we + // don't have valid history to correct them. Also, don't + // insert burst errors (adjacent errors), or errors within 2, + // since we can't reliably correct them. Also we must not choose + // the same location twice when inserting an error. + + do { + errloc = random () % NN; + } while (errloc < delay || errlocs[errloc] != 0 + || (errloc > 0 && errlocs[errloc-1] != 0) + || (errloc > 1 && errlocs[errloc-2] != 0) + || (errloc < (NN-1) && errlocs[errloc+1] != 0) + || (errloc < (NN-2) && errlocs[errloc+2] != 0)); + + errlocs[errloc] = 1; + + enc[errloc] ^= errval; // cause the error + } + + // decode the errored block + decoder.reset (); + decode_block (out, enc, blocklen, 0.5); + + // int offset = delay/4; + int offset = 2; + bool differs = (memcmp (in+offset, + out+delay+offset, blocklen-(delay+offset))); + + // initial values after reset are 0 + for (i = 0; i < delay; i++){ + if (out[i] != 0) + printf (" initial output at %i is %X, not 0\n", + i, out[i]); + } + + if (differs){ + printf (" %2d errors introduced, %scorrect data\n", + errors, differs? "in": ""); + + // FIXME, should we be able to tell how many errs too? + if (differs) { + const int ERRTOL = 12; /* Or relate to delay? */ + int shouldfix = 1; + int lasti = -ERRTOL; + + printf ( " Inserted errors: "); + for (int erri = 0; erri < NN; erri++) { + if (errlocs[erri]) { + printf (" %d", erri); + // if (erri < lasti+ERRTOL) + // shouldfix = 0; + lasti = erri; + } + } + printf ("\n Erroneous result dibits:"); + for (int erri = 0; erri < (NN-delay); erri++) { + if (in[erri] != out[erri+delay]) + printf (" %d", erri); + } + printf ("\n In: "); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %d", in[erri]); + } + printf ("\n Out: "); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %d", out[erri+delay]); + } + printf ("\n Errs:"); + for (int erri = 0; erri < (NN-delay); erri++) { + printf (" %c", (in[erri] != out[erri+delay])? '*': ' '); + } + if (shouldfix) + printf ("\n THIS IS A REAL PROBLEM.\n"); + else + printf ("\n BUT THAT'S OK since errors are too close.\n"); + if (shouldfix) + decoder_errors++; + } + } + } + } + + printf (" Summary: %d decoder errors out of %d trials.\n", + decoder_errors, (MAXERRORS*NTRIALS)); + + CPPUNIT_ASSERT (decoder_errors <= (MAXERRORS*NTRIALS) * .1); +} diff --git a/gr-atsc/src/lib/qa_atsci_single_viterbi.h b/gr-atsc/src/lib/qa_atsci_single_viterbi.h new file mode 100644 index 00000000..0c0a3349 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_single_viterbi.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_SINGLE_VITERBI_H +#define _QA_ATSC_SINGLE_VITERBI_H + +#include +#include + +#include +#include + +class qa_atsci_single_viterbi : public CppUnit::TestCase { + private: + atsci_single_viterbi decoder; + atsci_basic_trellis_encoder encoder; + + CPPUNIT_TEST_SUITE (qa_atsci_single_viterbi); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t0 (); + void t1 (); + + void encode_block(unsigned char *out, unsigned char *in, unsigned n); + void decode_block(unsigned char *out, unsigned char *in, unsigned n, float noise_factor); + float noise (); + +}; + +#endif /* _QA_ATSC_SINGLE_VITERBI_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_sliding_correlator.cc b/gr-atsc/src/lib/qa_atsci_sliding_correlator.cc new file mode 100644 index 00000000..e3158471 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_sliding_correlator.cc @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +void +qa_atsci_sliding_correlator::t0 () +{ + +#if 0 + int count = 0; + int i; + for (i = 0; i < 100; i++) + printf ("%6d: %3d\n", count++, corr.input_bit (i & 1)); + + for (i = 0; i < 511; i++) + printf ("%6d: %3d\n", count++, corr.input_bit (atsc_pn511[i])); + + for (i = 0; i < 100; i++) + printf ("%6d: %3d\n", count++, corr.input_bit ((i & 2) != 0)); + + for (i = 0; i < 511; i++) + printf ("%6d: %3d\n", count++, corr.input_bit (atsc_pn511[i] ^ 1)); + + for (i = 0; i < 100; i++) + printf ("%6d: %3d\n", count++, + corr.input_bit (atsc_pn511[i] ^ atsc_pn511[i+31])); +#endif + +} diff --git a/gr-atsc/src/lib/qa_atsci_sliding_correlator.h b/gr-atsc/src/lib/qa_atsci_sliding_correlator.h new file mode 100644 index 00000000..508020c2 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_sliding_correlator.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_SLIDING_CORRELATOR_H_ +#define _QA_ATSC_SLIDING_CORRELATOR_H_ + +#include +#include +#include + +#include + +class qa_atsci_sliding_correlator : public CppUnit::TestCase { + + public: + + void setUp (void) + { + corr.reset (); + } + + CPPUNIT_TEST_SUITE (qa_atsci_sliding_correlator); + CPPUNIT_TEST (t0); + CPPUNIT_TEST_SUITE_END (); + + private: + atsci_sliding_correlator corr; + + void t0 (); +}; + + +#endif /* _QA_ATSC_SLIDING_CORRELATOR_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_trellis_encoder.cc b/gr-atsc/src/lib/qa_atsci_trellis_encoder.cc new file mode 100644 index 00000000..193f2b31 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_trellis_encoder.cc @@ -0,0 +1,115 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static const int NCODERS = atsci_trellis_encoder::NCODERS; + +void +qa_atsci_trellis_encoder::t0 () +{ +#if 0 // generate i/o test data for t1 + + atsc_mpeg_packet_rs_encoded in[NCODERS]; + atsc_data_segment out[NCODERS]; + + + memset (in, 0, sizeof (in)); + memset (out, 0, sizeof (out)); + + srandom (1); + + printf ("@@@ INPUT @@@\n"); + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (in[i].data); j++){ + int t = (random () >> 8) & 0xff; // 8 random bits + in[i].data[j] = t; + printf ("%d\n", t); + } + } + + enc.reset (); + enc.encode (out, in); + + printf ("@@@ OUTPUT @@@\n"); + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (out[i].data); j++){ + printf ("%d\n", out[i].data[j]); + } + } +#endif +} + +void +qa_atsci_trellis_encoder::t1 () +{ + atsc_mpeg_packet_rs_encoded in[NCODERS]; + atsc_data_segment expected_out[NCODERS]; + atsc_data_segment actual_out[NCODERS]; + static const unsigned char raw_input[NCODERS * NELEM (in[0].data)] = { +#include "qa_atsci_trellis_encoder_t1_input.dat" + }; + static const unsigned char raw_output[NCODERS * NELEM (expected_out[0].data)] = { +#include "qa_atsci_trellis_encoder_t1_output.dat" + }; + + + // load up input + const unsigned char *r = &raw_input[0]; + for (int i = 0; i < NCODERS; i++){ + in[i].pli.set_regular_seg (false, i); + for (unsigned int j = 0; j < NELEM (in[i].data); j++){ + in[i].data[j] = *r++; + } + } + + // load up expected output + r = &raw_output[0]; + for (int i = 0; i < NCODERS; i++){ + expected_out[i].pli.set_regular_seg (false, i); + for (unsigned int j = 0; j < NELEM (expected_out[i].data); j++){ + expected_out[i].data[j] = *r++; + } + } + + memset (&actual_out, 0, sizeof (actual_out)); // ensure zero + + enc.reset (); + enc.encode (actual_out, in); // trellis code test data + + for (int i = 0; i < NCODERS; i++){ // check the result + CPPUNIT_ASSERT (expected_out[i] == actual_out[i]); + CPPUNIT_ASSERT (expected_out[i].pli == actual_out[i].pli); + } +} diff --git a/gr-atsc/src/lib/qa_atsci_trellis_encoder.h b/gr-atsc/src/lib/qa_atsci_trellis_encoder.h new file mode 100644 index 00000000..40657169 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_trellis_encoder.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_TRELLIS_ENCODER_H_ +#define _QA_ATSC_TRELLIS_ENCODER_H_ + +#include +#include +#include + +#include + +class qa_atsci_trellis_encoder : public CppUnit::TestCase { + + public: + + void setUp (void) + { + enc.reset (); + } + + CPPUNIT_TEST_SUITE (qa_atsci_trellis_encoder); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + atsci_trellis_encoder enc; + + void t0 (); + void t1 (); +}; + + +#endif /* _QA_ATSC_TRELLIS_ENCODER_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_input.dat b/gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_input.dat new file mode 100644 index 00000000..e6109ddf --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_input.dat @@ -0,0 +1,2484 @@ +69, +35, +152, +72, +220, +92, +148, +88, +31, +124, +88, +215, +65, +30, +169, +225, +0, +98, +8, +39, +35, +233, +205, +67, +15, +37, +249, +114, +194, +215, +196, +7, +251, +93, +80, +215, +186, +228, +48, +217, +97, +137, +177, +163, +168, +90, +132, +168, +189, +140, +208, +224, +118, +158, +36, +134, +196, +29, +248, +134, +245, +189, +141, +240, +26, +221, +200, +212, +194, +248, +173, +35, +130, +95, +198, +42, +185, +74, +211, +119, +215, +164, +88, +78, +66, +124, +212, +6, +154, +204, +141, +143, +137, +27, +127, +164, +249, +72, +120, +187, +64, +38, +222, +195, +133, +165, +237, +63, +240, +193, +183, +199, +101, +15, +21, +168, +140, +233, +175, +38, +182, +60, +182, +64, +87, +53, +228, +80, +126, +93, +11, +191, +132, +234, +130, +10, +143, +112, +74, +127, +49, +2, +71, +150, +18, +93, +63, +158, +71, +238, +197, +253, +43, +123, +62, +130, +177, +35, +211, +47, +129, +223, +238, +6, +202, +112, +17, +89, +224, +91, +217, +17, +94, +33, +168, +112, +126, +231, +14, +197, +214, +212, +195, +1, +79, +1, +132, +1, +36, +87, +48, +165, +55, +30, +172, +1, +143, +189, +90, +112, +24, +52, +130, +119, +85, +42, +231, +211, +18, +246, +153, +232, +202, +92, +234, +26, +93, +110, +27, +130, +197, +75, +40, +253, +106, +212, +254, +250, +145, +89, +106, +170, +141, +236, +33, +227, +23, +9, +183, +41, +255, +80, +18, +201, +172, +252, +227, +10, +107, +255, +141, +49, +74, +181, +46, +181, +138, +44, +175, +27, +133, +26, +198, +19, +6, +232, +246, +29, +241, +174, +71, +240, +254, +90, +185, +171, +87, +157, +182, +194, +157, +67, +243, +232, +248, +34, +157, +130, +78, +77, +158, +212, +103, +100, +231, +110, +76, +222, +140, +61, +140, +211, +46, +138, +46, +232, +54, +133, +133, +236, +72, +35, +47, +59, +11, +40, +94, +168, +171, +172, +246, +74, +128, +93, +174, +104, +204, +251, +70, +88, +57, +210, +44, +103, +93, +90, +79, +148, +223, +213, +129, +39, +248, +177, +99, +4, +217, +193, +172, +133, +110, +162, +207, +239, +0, +126, +87, +205, +121, +158, +37, +179, +113, +81, +27, +207, +171, +107, +99, +139, +65, +228, +178, +58, +149, +22, +62, +111, +216, +234, +244, +70, +141, +195, +54, +142, +66, +141, +91, +187, +44, +129, +111, +157, +210, +138, +108, +126, +245, +208, +9, +55, +180, +188, +113, +74, +211, +175, +185, +171, +154, +174, +242, +40, +114, +40, +183, +180, +182, +19, +112, +226, +148, +223, +128, +103, +106, +237, +229, +96, +189, +239, +151, +114, +172, +8, +189, +127, +184, +118, +43, +83, +37, +29, +123, +151, +70, +50, +76, +252, +69, +188, +223, +218, +156, +96, +65, +6, +77, +39, +102, +11, +23, +254, +125, +195, +7, +59, +67, +191, +178, +111, +18, +215, +141, +142, +111, +211, +192, +187, +208, +6, +119, +176, +225, +19, +16, +34, +26, +94, +74, +128, +105, +97, +127, +231, +37, +134, +35, +104, +69, +213, +215, +88, +172, +101, +230, +27, +56, +167, +214, +9, +174, +78, +185, +143, +98, +202, +178, +124, +40, +253, +253, +146, +94, +124, +122, +131, +2, +157, +236, +72, +114, +196, +161, +31, +41, +136, +58, +98, +47, +17, +107, +222, +96, +37, +110, +194, +239, +32, +63, +24, +29, +60, +170, +124, +185, +37, +0, +188, +195, +237, +4, +53, +178, +165, +84, +219, +45, +143, +62, +93, +161, +169, +60, +1, +206, +170, +196, +190, +203, +4, +214, +232, +65, +129, +101, +250, +166, +102, +182, +105, +83, +186, +159, +5, +96, +244, +225, +142, +132, +31, +236, +37, +201, +40, +39, +152, +210, +236, +86, +157, +240, +44, +134, +49, +173, +235, +44, +83, +81, +226, +189, +165, +157, +93, +170, +254, +81, +140, +141, +213, +171, +121, +251, +117, +161, +35, +13, +116, +16, +99, +17, +0, +144, +152, +50, +61, +132, +95, +145, +214, +66, +79, +123, +223, +172, +38, +222, +254, +178, +107, +211, +94, +229, +207, +212, +134, +242, +225, +251, +2, +69, +12, +3, +214, +164, +54, +20, +40, +149, +165, +254, +215, +245, +122, +183, +162, +160, +150, +160, +83, +1, +116, +177, +230, +67, +133, +109, +54, +103, +104, +56, +173, +117, +60, +131, +26, +115, +151, +67, +9, +61, +65, +224, +50, +188, +152, +212, +92, +46, +116, +175, +48, +232, +97, +23, +44, +231, +132, +98, +78, +237, +155, +251, +98, +215, +126, +124, +74, +22, +191, +83, +83, +1, +52, +133, +189, +205, +90, +26, +252, +207, +202, +45, +183, +43, +68, +228, +19, +201, +70, +98, +182, +225, +93, +25, +185, +220, +150, +4, +243, +86, +88, +70, +88, +141, +203, +21, +90, +38, +48, +87, +245, +250, +132, +173, +38, +200, +145, +57, +145, +215, +156, +72, +185, +250, +98, +114, +215, +248, +119, +202, +78, +207, +16, +166, +92, +220, +188, +183, +2, +237, +14, +247, +231, +146, +164, +14, +91, +53, +72, +237, +13, +228, +53, +199, +222, +151, +57, +181, +144, +177, +127, +222, +128, +143, +133, +220, +107, +66, +147, +109, +47, +162, +101, +23, +52, +9, +37, +143, +63, +110, +125, +77, +82, +179, +20, +49, +75, +78, +230, +219, +255, +102, +186, +127, +246, +64, +92, +98, +130, +240, +208, +177, +146, +53, +200, +198, +63, +238, +86, +127, +92, +212, +204, +175, +135, +224, +224, +210, +47, +199, +173, +46, +45, +104, +174, +36, +168, +10, +134, +42, +250, +86, +220, +141, +139, +165, +83, +203, +148, +170, +74, +241, +126, +22, +160, +6, +247, +128, +216, +38, +72, +134, +85, +117, +238, +3, +153, +151, +13, +32, +194, +8, +118, +158, +149, +2, +68, +233, +205, +217, +148, +23, +202, +19, +46, +106, +25, +38, +235, +241, +76, +51, +120, +162, +169, +103, +165, +66, +254, +179, +98, +192, +188, +217, +95, +82, +219, +164, +59, +169, +125, +208, +193, +71, +227, +239, +177, +252, +22, +157, +238, +98, +208, +102, +5, +121, +206, +170, +188, +204, +94, +31, +141, +26, +248, +237, +108, +212, +146, +168, +125, +15, +120, +62, +87, +91, +46, +9, +88, +68, +166, +70, +167, +118, +173, +172, +240, +124, +87, +172, +72, +181, +203, +214, +207, +196, +196, +59, +152, +86, +228, +21, +102, +92, +84, +190, +183, +131, +199, +16, +199, +110, +86, +110, +229, +4, +27, +213, +128, +114, +129, +201, +39, +77, +160, +247, +17, +100, +51, +169, +187, +23, +191, +33, +115, +20, +223, +43, +151, +167, +59, +94, +21, +146, +205, +251, +150, +233, +208, +23, +91, +82, +224, +131, +159, +129, +122, +177, +229, +173, +91, +160, +196, +27, +194, +56, +47, +162, +99, +198, +74, +159, +37, +95, +49, +243, +91, +200, +220, +43, +223, +55, +126, +192, +187, +29, +65, +53, +207, +39, +226, +42, +200, +167, +69, +138, +223, +116, +45, +67, +59, +119, +226, +97, +215, +20, +84, +50, +221, +48, +94, +188, +104, +220, +125, +35, +249, +191, +89, +200, +230, +60, +243, +175, +227, +56, +57, +195, +173, +103, +7, +233, +222, +234, +74, +181, +254, +158, +232, +219, +207, +70, +152, +56, +34, +22, +92, +28, +213, +181, +229, +188, +241, +216, +107, +213, +17, +165, +153, +190, +12, +160, +167, +235, +139, +242, +161, +138, +144, +137, +101, +96, +208, +254, +152, +242, +20, +244, +14, +234, +170, +243, +167, +155, +204, +19, +113, +221, +184, +11, +156, +197, +171, +68, +177, +55, +54, +82, +193, +199, +220, +39, +39, +172, +37, +192, +158, +58, +180, +173, +37, +94, +161, +204, +250, +109, +224, +108, +75, +153, +119, +232, +94, +35, +45, +15, +90, +99, +98, +27, +43, +62, +66, +83, +234, +104, +20, +137, +162, +201, +54, +200, +39, +215, +149, +34, +69, +117, +142, +144, +14, +6, +121, +109, +41, +166, +125, +131, +10, +223, +159, +53, +29, +225, +137, +8, +74, +157, +145, +237, +102, +200, +181, +142, +159, +74, +177, +229, +192, +64, +118, +207, +70, +239, +60, +111, +149, +185, +243, +160, +153, +146, +214, +182, +116, +95, +191, +190, +253, +80, +171, +99, +25, +97, +242, +185, +172, +163, +158, +108, +228, +20, +59, +42, +4, +120, +154, +154, +49, +141, +58, +202, +32, +16, +129, +149, +112, +65, +83, +109, +146, +255, +209, +171, +96, +196, +100, +13, +103, +2, +121, +76, +23, +181, +118, +28, +45, +17, +183, +95, +158, +241, +42, +191, +2, +172, +84, +115, +237, +168, +224, +127, +168, +178, +42, +8, +118, +142, +22, +222, +145, +143, +42, +169, +69, +160, +197, +114, +177, +124, +210, +80, +110, +252, +16, +113, +168, +101, +228, +149, +13, +197, +20, +181, +119, +63, +190, +237, +206, +212, +203, +95, +100, +245, +9, +169, +150, +207, +28, +72, +76, +238, +153, +186, +234, +169, +44, +146, +14, +17, +40, +28, +214, +61, +209, +77, +125, +144, +59, +75, +100, +6, +171, +200, +252, +180, +114, +147, +131, +142, +219, +207, +124, +117, +138, +102, +31, +183, +249, +45, +200, +34, +74, +158, +96, +27, +236, +221, +172, +39, +40, +16, +46, +212, +217, +43, +136, +75, +190, +11, +217, +154, +219, +85, +15, +102, +188, +46, +29, +182, +92, +229, +217, +166, +131, +57, +194, +112, +22, +110, +151, +63, +127, +197, +19, +88, +241, +156, +163, +175, +168, +125, +73, +131, +211, +88, +233, +143, +135, +7, +70, +227, +236, +31, +138, +112, +88, +77, +224, +111, +187, +120, +174, +59, +62, +194, +147, +47, +94, +55, +222, +6, +180, +40, +138, +135, +129, +116, +23, +8, +123, +93, +236, +103, +125, +118, +216, +213, +195, +184, +69, +127, +49, +244, +187, +111, +182, +78, +158, +21, +134, +125, +27, +59, +165, +165, +195, +38, +25, +218, +47, +149, +56, +27, +252, +181, +146, +213, +139, +86, +142, +208, +213, +191, +196, +145, +46, +123, +223, +205, +144, +102, +75, +171, +161, +240, +81, +101, +23, +107, +64, +70, +0, +120, +98, +253, +46, +244, +210, +185, +74, +96, +138, +32, +32, +78, +177, +79, +201, +145, +28, +89, +248, +103, +5, +154, +88, +87, +255, +112, +195, +63, +183, +196, +184, +25, +193, +230, +14, +148, +160, +89, +245, +42, +122, +21, +121, +43, +100, +67, +189, +129, +157, +182, +233, +162, +80, +65, +250, +80, +178, +190, +143, +105, +130, +72, +131, +67, +47, +145, +216, +208, +235, +205, +251, +101, +227, +116, +145, +71, +183, +78, +201, +84, +4, +178, +247, +85, +244, +242, +165, +166, +176, +53, +16, +50, +126, +147, +118, +173, +37, +78, +125, +16, +28, +120, +117, +0, +237, +6, +71, +164, +85, +17, +249, +90, +195, +240, +175, +184, +227, +85, +94, +147, +138, +110, +197, +8, +2, +60, +182, +39, +139, +51, +55, +167, +172, +173, +167, +153, +179, +239, +62, +9, +1, +55, +99, +196, +40, +19, +124, +12, +104, +219, +159, +243, +74, +101, +251, +76, +161, +178, +115, +44, +230, +171, +212, +146, +88, +124, +44, +12, +108, +107, +21, +109, +163, +121, +50, +204, +140, +175, +216, +244, +138, +119, +232, +213, +221, +228, +33, +127, +150, +149, +172, +124, +64, +129, +15, +153, +253, +59, +166, +105, +167, +187, +215, +74, +53, +9, +22, +193, +184, +238, +182, +67, +102, +158, +24, +68, +130, +58, +195, +24, +207, +111, +149, +16, +240, +164, +170, +238, +224, +80, +88, +135, +12, +47, +209, +65, +57, +232, +2, +242, +215, +185, +53, +62, +87, +78, +130, +218, +136, +69, +243, +87, +181, +136, +104, +166, +44, +18, +148, +13, +99, +237, +148, +111, +28, +102, +176, +86, +79, +179, +72, +38, +109, +125, +100, +197, +203, +231, +159, +83, +44, +146, +171, +226, +27, +20, +137, +72, +39, +29, +85, +138, +10, +234, +249, +39, +81, +170, +125, +160, +94, +197, +198, +203, +67, +43, +145, +15, +18, +48, +98, +63, +195, +14, +34, +222, +35, +171, +39, +74, +201, +125, +212, +212, +103, +206, +251, +185, +121, +121, +89, +215, +63, +32, +163, +130, +75, +52, +145, +94, +101, +244, +158, +40, +3, +192, +7, +38, +107, +47, +113, +52, +172, +69, +8, +20, +20, +4, +205, +141, +126, +38, +101, +189, +71, +9, +64, +147, +62, +210, +241, +163, +198, +143, +204, +202, +80, +212, +241, +187, +4, +98, +240, +176, +168, +249, +197, +188, +254, +146, +73, +124, +185, +175, +57, +1, +184, +122, +148, +246, +76, +134, +154, +19, +21, +102, +222, +102, +59, +207, +33, +63, +49, +18, +240, +218, +11, +181, +150, +9, +72, +224, +134, +2, +143, +192, +3, +71, +58, +151, +62, +135, +29, +216, +154, +51, +63, +120, +153, +123, +72, +187, +187, +122, +206, +171, +84, +218, +97, +234, +228, +169, +203, +106, +172, +90, +42, +175, +162, +101, +71, +224, +236, +101, +185, +135, +153, +248, +0, +51, +116, +72, +238, +47, +194, +189, +218, +22, +151, +60, +1, +123, +230, +204, +230, +146, +38, +17, +66, +200, +118, +137, +169, +99, +239, +98, +234, +136, +91, +234, +187, +208, +51, +170, +255, +245, +103, +218, +11, +255, +22, +12, +123, +252, +217, +97, +142, +255, +115, +208, +200, +234, +90, +114, +77, +73, +212, +56, +209, +48, +35, +141, +0, +86, +55, +0, +75, +159, +218, +87, +159, +240, +100, +26, +237, +61, +124, +124, +61, +239, +77, +6, +218, +167, +120, +39, +241, +77, +96, +195, +125, +132, +80, +126, +218, +136, +126, +38, +40, +88, +126, +199, +73, +226, +225, +55, +32, +94, +179, +94, +78, +1, +100, +40, +168, +220, +80, +154, +41, +177, +93, +167, +53, +173, +37, +16, +54, +164, +55, +94, +253, +181, +37, +70, +152, +7, +126, +184, +102, +50, +22, +180, +51, +123, +221, +220, +87, +46, +118, +129, +223, +211, +41, +20, +129, +78, +37, +183, +243, +92, +21, +240, +17, +59, +55, +169, +67, +181, +98, +170, +231, +121, +94, +27, +244, +60, +247, +76, +106, +109, +206, +73, +64, +247, +94, +193, +70, +131, +121, +57, +223, +143, +41, +241, +203, +97, +155, +14, +23, +253, +184, +255, +119, +23, +26, +108, +83, +17, +184, +190, +127, +135, +7, +191, +126, +102, +129, +196, +233, +251, +254, +200, +138, +40, +186, +85, +137, +85, +100, +160, +83, +29, +159, +202, +53, +185, +54, +137, +203, +239, +71, +74, +119, +79, +10, +245, +181, +140, +186, +158, +135, +184, +103, +18, +224, +33, +103, +106, +118, +204, +10, +201, +234, +170, +147, +31, +99, +202, +168, +47, +186, +239, +121, +50, +62, +131, +39, +243, +15, +225, +146, +151, +154, +249, +169, +123, +26, +17, +229, +145, +221, +239, +90, +199, +153, +238, +230, +253, +185, +142, +44, +116, +126, +166, +166, +189, +41, +206, +176, +57, +176, +67, +208, +74, +60, +121, +197, +87, +138, +170, +232, +104, +154, +67, +48, +52, +50, +22, +49, +236, +165, +94, +96, +36, +4, +7, +225, +46, +213, +146, +104, +133, +213, +57, +207, +18, +178, +149, +105, +61, +63, +82, +166, +218, +150, +214, +14, +200, +237, +64, +180, +147, +159, +21, +183, +164, +28, +152, +210, +241, +42, +59, +118, +0, +116, +70, +18, diff --git a/gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_output.dat b/gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_output.dat new file mode 100644 index 00000000..175d482b --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_output.dat @@ -0,0 +1,9984 @@ +6, +1, +1, +6, +2, +0, +4, +2, +6, +2, +4, +2, +0, +2, +2, +6, +1, +4, +6, +1, +7, +3, +6, +3, +2, +7, +3, +7, +2, +4, +1, +4, +3, +7, +7, +5, +7, +3, +5, +7, +2, +2, +0, +5, +0, +4, +5, +5, +3, +0, +5, +2, +3, +1, +5, +2, +1, +7, +5, +5, +0, +7, +3, +2, +1, +2, +0, +4, +0, +1, +5, +1, +5, +1, +0, +1, +1, +6, +5, +4, +1, +1, +1, +3, +4, +5, +7, +0, +3, +1, +6, +6, +0, +5, +1, +6, +3, +7, +7, +7, +0, +0, +2, +7, +7, +3, +7, +4, +7, +6, +6, +3, +1, +5, +7, +3, +5, +2, +4, +4, +2, +6, +6, +2, +6, +6, +1, +0, +5, +2, +7, +6, +4, +3, +5, +2, +2, +6, +3, +5, +1, +7, +5, +3, +2, +3, +4, +7, +5, +3, +0, +2, +3, +1, +1, +5, +5, +2, +1, +1, +2, +5, +7, +2, +4, +1, +7, +1, +0, +2, +0, +5, +4, +7, +5, +5, +5, +5, +4, +1, +5, +5, +3, +1, +0, +4, +5, +6, +6, +7, +7, +7, +4, +0, +1, +1, +4, +1, +3, +2, +6, +0, +5, +0, +3, +1, +7, +5, +2, +0, +2, +5, +3, +3, +1, +1, +1, +2, +2, +5, +7, +7, +0, +4, +3, +7, +3, +2, +3, +6, +4, +7, +7, +5, +0, +5, +4, +0, +0, +4, +0, +7, +4, +0, +2, +1, +4, +2, +5, +7, +7, +2, +7, +3, +0, +1, +6, +7, +4, +6, +6, +7, +5, +3, +5, +6, +4, +4, +7, +2, +2, +5, +0, +2, +1, +3, +5, +0, +2, +5, +7, +2, +3, +4, +4, +2, +1, +0, +1, +0, +3, +2, +0, +3, +7, +5, +0, +3, +7, +3, +7, +4, +3, +2, +1, +3, +4, +0, +6, +1, +6, +7, +6, +0, +2, +1, +0, +6, +7, +5, +1, +5, +4, +6, +6, +2, +4, +6, +5, +2, +1, +0, +2, +1, +2, +2, +3, +1, +4, +0, +6, +3, +7, +1, +4, +7, +5, +5, +5, +0, +6, +4, +4, +7, +6, +0, +6, +4, +4, +4, +5, +3, +3, +0, +4, +2, +6, +3, +1, +3, +3, +3, +1, +5, +7, +2, +0, +0, +5, +5, +4, +1, +3, +7, +3, +3, +2, +1, +6, +2, +6, +1, +7, +1, +6, +2, +4, +4, +6, +0, +3, +1, +2, +7, +5, +5, +6, +0, +5, +1, +1, +7, +5, +4, +5, +0, +5, +7, +3, +0, +6, +2, +6, +3, +7, +5, +4, +7, +5, +0, +5, +6, +6, +2, +6, +6, +2, +2, +1, +3, +7, +1, +5, +1, +1, +7, +1, +4, +6, +0, +6, +0, +0, +0, +7, +4, +0, +1, +4, +0, +5, +0, +6, +3, +3, +7, +6, +1, +7, +5, +3, +2, +4, +2, +3, +7, +3, +3, +6, +0, +5, +7, +7, +5, +1, +1, +5, +6, +2, +0, +3, +3, +7, +6, +4, +0, +6, +6, +3, +4, +2, +7, +5, +3, +2, +6, +5, +7, +6, +2, +2, +4, +3, +7, +7, +0, +6, +3, +0, +3, +1, +1, +4, +4, +7, +6, +4, +1, +1, +3, +7, +6, +4, +6, +0, +4, +0, +6, +7, +2, +0, +0, +7, +0, +5, +0, +0, +4, +1, +3, +5, +6, +7, +1, +4, +2, +6, +4, +0, +0, +6, +1, +1, +3, +5, +0, +7, +3, +4, +0, +4, +4, +2, +1, +5, +7, +7, +5, +3, +5, +4, +2, +4, +0, +3, +7, +3, +2, +4, +6, +0, +1, +6, +3, +2, +2, +1, +0, +0, +6, +1, +2, +7, +1, +5, +7, +7, +7, +3, +7, +3, +3, +4, +5, +3, +1, +0, +6, +3, +1, +6, +1, +3, +3, +3, +2, +4, +5, +5, +4, +6, +1, +0, +7, +6, +0, +7, +2, +5, +7, +2, +0, +6, +5, +0, +6, +0, +1, +4, +7, +6, +6, +0, +0, +5, +3, +0, +2, +6, +2, +1, +5, +4, +0, +2, +6, +2, +6, +2, +7, +1, +4, +4, +5, +6, +2, +7, +7, +6, +4, +3, +5, +4, +6, +7, +3, +5, +7, +1, +7, +7, +6, +3, +1, +1, +3, +3, +4, +4, +5, +1, +0, +1, +5, +6, +1, +4, +1, +6, +7, +3, +7, +1, +7, +3, +6, +0, +3, +5, +1, +0, +3, +5, +6, +7, +3, +6, +4, +2, +0, +0, +1, +0, +2, +5, +0, +6, +2, +4, +4, +1, +1, +1, +1, +4, +2, +3, +4, +6, +2, +4, +4, +6, +0, +2, +1, +6, +3, +0, +6, +1, +1, +2, +6, +2, +3, +0, +3, +5, +7, +1, +7, +0, +0, +5, +5, +5, +5, +2, +2, +4, +4, +4, +7, +7, +3, +0, +4, +4, +3, +3, +6, +7, +3, +5, +2, +7, +7, +7, +5, +3, +6, +5, +5, +1, +3, +4, +2, +2, +0, +5, +6, +7, +6, +1, +4, +1, +0, +1, +7, +2, +1, +3, +2, +4, +3, +5, +3, +7, +3, +6, +5, +6, +1, +1, +6, +7, +7, +7, +5, +4, +3, +0, +7, +3, +4, +4, +3, +5, +6, +0, +1, +1, +6, +4, +0, +3, +1, +7, +1, +1, +0, +3, +1, +4, +4, +0, +5, +2, +4, +3, +7, +3, +2, +1, +5, +3, +6, +0, +2, +2, +3, +6, +2, +2, +5, +3, +5, +1, +5, +4, +6, +5, +3, +2, +6, +6, +2, +4, +5, +3, +0, +0, +3, +0, +2, +7, +1, +7, +4, +3, +1, +2, +7, +0, +3, +5, +0, +1, +4, +1, +6, +3, +5, +4, +3, +0, +6, +4, +0, +5, +5, +3, +7, +4, +1, +4, +4, +4, +0, +7, +0, +3, +0, +0, +1, +1, +5, +2, +3, +4, +0, +7, +4, +2, +5, +3, +3, +4, +1, +3, +1, +6, +6, +2, +6, +6, +6, +7, +2, +5, +7, +5, +7, +3, +5, +2, +3, +1, +4, +2, +2, +6, +4, +1, +2, +5, +4, +5, +7, +0, +2, +6, +1, +4, +1, +7, +6, +5, +1, +0, +2, +7, +1, +3, +0, +0, +2, +4, +5, +3, +4, +7, +6, +7, +2, +3, +5, +0, +4, +1, +4, +4, +5, +1, +5, +2, +0, +0, +2, +4, +2, +0, +1, +1, +6, +1, +6, +0, +2, +5, +2, +2, +3, +5, +6, +6, +0, +3, +0, +2, +1, +0, +3, +5, +3, +0, +4, +2, +6, +2, +4, +5, +6, +1, +7, +2, +0, +7, +0, +3, +3, +6, +6, +0, +0, +0, +0, +6, +3, +3, +4, +1, +7, +3, +7, +7, +4, +3, +5, +7, +7, +0, +2, +3, +4, +7, +1, +1, +0, +5, +4, +1, +6, +3, +5, +6, +5, +0, +5, +3, +6, +7, +1, +5, +2, +5, +6, +2, +2, +7, +5, +4, +1, +6, +2, +3, +1, +7, +4, +7, +4, +3, +1, +7, +0, +6, +6, +2, +0, +2, +4, +5, +0, +4, +1, +3, +1, +3, +7, +4, +5, +2, +2, +3, +0, +5, +5, +2, +4, +3, +7, +0, +2, +3, +3, +6, +2, +6, +3, +4, +5, +0, +4, +2, +2, +5, +5, +0, +5, +4, +2, +4, +2, +7, +3, +7, +3, +7, +7, +2, +2, +2, +6, +2, +6, +1, +3, +1, +1, +2, +4, +7, +4, +1, +1, +1, +7, +5, +6, +1, +5, +0, +3, +5, +0, +4, +6, +2, +5, +5, +6, +5, +5, +4, +5, +3, +0, +5, +0, +0, +1, +3, +5, +3, +1, +2, +1, +2, +2, +6, +6, +4, +1, +0, +2, +4, +5, +5, +1, +4, +3, +6, +5, +4, +7, +1, +0, +5, +5, +6, +5, +0, +5, +3, +6, +0, +6, +4, +6, +4, +1, +6, +1, +4, +1, +7, +4, +0, +6, +3, +1, +1, +5, +3, +5, +0, +7, +6, +0, +0, +3, +7, +6, +6, +5, +5, +5, +6, +4, +0, +4, +0, +3, +0, +6, +2, +3, +7, +7, +5, +3, +0, +6, +2, +2, +5, +1, +1, +6, +4, +6, +2, +3, +4, +1, +3, +2, +2, +4, +6, +0, +7, +0, +4, +0, +2, +2, +7, +5, +4, +5, +4, +6, +1, +0, +6, +5, +1, +6, +6, +0, +6, +0, +2, +3, +5, +0, +3, +0, +2, +5, +2, +7, +5, +3, +3, +3, +5, +4, +7, +7, +4, +4, +3, +5, +2, +3, +7, +2, +5, +6, +0, +5, +4, +7, +5, +5, +6, +0, +2, +2, +7, +3, +1, +7, +2, +5, +7, +7, +1, +5, +2, +5, +2, +7, +0, +6, +3, +3, +6, +0, +4, +4, +5, +0, +0, +0, +1, +2, +3, +0, +2, +3, +3, +7, +2, +1, +6, +7, +0, +7, +2, +7, +5, +7, +1, +7, +4, +4, +3, +3, +1, +1, +6, +7, +6, +0, +1, +0, +6, +7, +1, +6, +4, +3, +7, +0, +6, +7, +5, +7, +3, +7, +3, +4, +1, +4, +1, +1, +5, +1, +7, +5, +1, +4, +4, +2, +4, +1, +1, +4, +4, +3, +6, +3, +3, +7, +3, +7, +3, +6, +7, +3, +7, +0, +0, +0, +4, +5, +1, +7, +7, +2, +2, +3, +1, +7, +6, +7, +7, +7, +7, +0, +6, +5, +6, +0, +1, +5, +5, +1, +7, +6, +2, +7, +0, +0, +7, +3, +7, +5, +0, +5, +6, +0, +4, +3, +0, +5, +5, +5, +6, +3, +1, +1, +6, +4, +6, +4, +0, +0, +7, +1, +2, +4, +6, +1, +5, +4, +7, +3, +4, +1, +0, +3, +3, +5, +6, +7, +4, +2, +1, +5, +2, +0, +7, +6, +1, +0, +1, +0, +1, +3, +7, +3, +1, +3, +3, +6, +5, +5, +2, +3, +6, +7, +4, +0, +4, +5, +2, +7, +3, +0, +4, +7, +2, +6, +5, +7, +3, +3, +6, +5, +2, +5, +2, +2, +3, +4, +0, +7, +3, +6, +5, +1, +0, +2, +1, +4, +3, +4, +3, +2, +0, +4, +6, +5, +6, +6, +4, +0, +4, +0, +7, +0, +3, +4, +0, +1, +1, +5, +3, +4, +7, +4, +2, +4, +7, +0, +6, +7, +6, +6, +6, +1, +1, +6, +0, +0, +4, +4, +7, +6, +6, +4, +5, +0, +1, +2, +4, +0, +1, +4, +3, +4, +1, +2, +7, +6, +5, +5, +6, +6, +4, +2, +4, +6, +2, +7, +2, +7, +1, +2, +3, +1, +7, +3, +5, +1, +4, +1, +4, +1, +7, +4, +1, +0, +7, +7, +4, +2, +0, +7, +6, +1, +2, +2, +1, +5, +4, +2, +5, +6, +4, +6, +7, +1, +2, +7, +5, +6, +1, +0, +0, +7, +0, +6, +5, +3, +1, +5, +7, +2, +4, +0, +7, +3, +6, +3, +1, +2, +4, +7, +6, +1, +3, +4, +3, +6, +1, +3, +5, +0, +7, +2, +2, +4, +1, +4, +2, +2, +0, +4, +3, +6, +7, +2, +3, +1, +3, +4, +2, +7, +3, +1, +6, +3, +0, +3, +7, +2, +0, +2, +1, +3, +1, +6, +6, +3, +3, +5, +0, +2, +3, +1, +6, +6, +3, +2, +3, +4, +7, +5, +7, +7, +5, +4, +4, +4, +2, +1, +7, +1, +4, +5, +7, +5, +7, +5, +6, +4, +0, +6, +6, +6, +5, +5, +4, +5, +4, +0, +1, +4, +2, +2, +2, +4, +4, +3, +5, +7, +3, +3, +2, +0, +3, +7, +7, +4, +7, +4, +6, +0, +3, +7, +4, +6, +7, +1, +7, +2, +3, +3, +6, +5, +4, +6, +4, +3, +0, +5, +6, +7, +6, +5, +5, +2, +3, +0, +6, +3, +1, +5, +0, +7, +4, +3, +4, +6, +1, +6, +5, +2, +6, +3, +6, +4, +4, +4, +3, +3, +5, +3, +0, +6, +6, +4, +3, +3, +4, +3, +7, +1, +7, +5, +7, +5, +5, +5, +1, +3, +6, +5, +6, +1, +2, +3, +1, +6, +6, +0, +3, +2, +5, +5, +4, +3, +2, +0, +1, +4, +4, +1, +4, +6, +0, +5, +4, +4, +7, +1, +3, +2, +4, +4, +1, +1, +5, +5, +6, +7, +7, +6, +0, +5, +4, +7, +2, +6, +2, +7, +1, +1, +2, +0, +5, +4, +0, +1, +0, +6, +2, +6, +4, +1, +6, +2, +6, +7, +0, +5, +2, +7, +3, +0, +7, +3, +3, +7, +6, +1, +6, +5, +3, +7, +7, +0, +1, +2, +7, +5, +5, +5, +3, +5, +5, +6, +0, +4, +5, +4, +0, +7, +2, +1, +3, +5, +1, +4, +7, +4, +3, +6, +3, +0, +4, +3, +2, +1, +7, +2, +1, +2, +0, +7, +5, +7, +4, +6, +4, +3, +0, +5, +3, +7, +3, +3, +1, +7, +4, +2, +2, +4, +3, +6, +2, +1, +5, +0, +7, +2, +0, +7, +7, +7, +3, +2, +6, +1, +5, +5, +4, +6, +4, +3, +3, +5, +6, +7, +1, +1, +1, +0, +1, +5, +4, +2, +2, +1, +0, +5, +4, +7, +1, +5, +6, +6, +6, +6, +4, +1, +0, +1, +5, +6, +1, +6, +0, +4, +3, +5, +0, +3, +4, +1, +2, +0, +1, +2, +6, +0, +1, +6, +0, +6, +0, +5, +4, +0, +5, +3, +5, +0, +5, +4, +2, +2, +2, +5, +0, +4, +5, +1, +6, +6, +7, +4, +3, +7, +7, +5, +0, +4, +1, +3, +0, +7, +0, +0, +5, +5, +1, +1, +6, +6, +7, +0, +4, +3, +1, +2, +3, +5, +7, +1, +3, +1, +2, +3, +2, +4, +0, +3, +4, +1, +2, +1, +7, +0, +0, +1, +5, +7, +5, +1, +5, +5, +6, +7, +4, +1, +2, +7, +0, +3, +2, +5, +4, +3, +5, +0, +5, +6, +7, +2, +5, +6, +4, +7, +5, +6, +4, +7, +6, +6, +7, +0, +0, +4, +6, +6, +4, +4, +3, +7, +4, +7, +0, +4, +3, +2, +5, +0, +5, +6, +5, +0, +4, +5, +7, +0, +3, +3, +0, +0, +2, +7, +1, +5, +2, +5, +5, +2, +2, +5, +7, +6, +6, +3, +1, +0, +7, +5, +1, +3, +0, +3, +7, +3, +1, +2, +3, +3, +5, +7, +7, +5, +6, +4, +2, +1, +6, +6, +2, +5, +7, +2, +4, +1, +5, +3, +0, +1, +6, +1, +0, +5, +0, +6, +3, +5, +6, +7, +4, +3, +7, +4, +0, +5, +3, +1, +5, +1, +4, +0, +2, +0, +1, +5, +2, +7, +3, +4, +1, +3, +0, +3, +3, +5, +5, +4, +3, +2, +6, +1, +5, +4, +6, +5, +3, +2, +7, +5, +5, +6, +0, +0, +7, +7, +7, +1, +0, +4, +2, +6, +5, +7, +0, +7, +0, +1, +1, +3, +7, +0, +6, +6, +5, +5, +2, +1, +5, +1, +7, +0, +3, +0, +5, +1, +3, +3, +3, +5, +4, +3, +0, +5, +0, +4, +0, +2, +2, +4, +3, +7, +7, +6, +7, +6, +5, +0, +3, +4, +0, +3, +2, +2, +5, +2, +5, +6, +6, +0, +7, +4, +4, +1, +4, +2, +3, +1, +1, +5, +0, +6, +4, +6, +6, +7, +0, +5, +6, +4, +1, +2, +4, +1, +1, +7, +7, +0, +6, +0, +4, +3, +3, +0, +2, +4, +6, +5, +5, +1, +3, +3, +6, +1, +1, +6, +3, +3, +4, +3, +7, +4, +3, +3, +4, +1, +4, +2, +5, +3, +0, +6, +6, +1, +4, +6, +0, +3, +3, +3, +7, +2, +4, +2, +6, +0, +5, +6, +4, +6, +7, +7, +2, +6, +0, +7, +5, +7, +2, +7, +0, +0, +0, +6, +2, +7, +4, +1, +6, +5, +2, +7, +6, +2, +7, +6, +5, +5, +4, +3, +4, +7, +1, +4, +1, +5, +5, +5, +0, +1, +4, +6, +6, +0, +2, +5, +2, +6, +3, +2, +1, +1, +2, +6, +5, +1, +0, +4, +0, +0, +0, +6, +2, +7, +3, +5, +4, +6, +2, +5, +0, +0, +5, +7, +4, +6, +5, +2, +7, +6, +3, +2, +4, +0, +2, +3, +4, +6, +7, +2, +5, +5, +7, +2, +0, +4, +2, +6, +6, +3, +4, +3, +5, +2, +0, +7, +6, +6, +7, +2, +5, +7, +7, +5, +1, +6, +7, +3, +5, +1, +1, +5, +0, +6, +3, +7, +7, +3, +3, +4, +2, +6, +7, +4, +7, +0, +2, +6, +0, +1, +2, +5, +6, +0, +2, +5, +5, +4, +0, +2, +3, +7, +2, +6, +5, +0, +4, +4, +1, +2, +6, +5, +3, +2, +1, +0, +0, +2, +2, +1, +3, +1, +5, +2, +4, +0, +0, +0, +5, +5, +7, +6, +0, +0, +4, +2, +1, +6, +3, +4, +6, +0, +3, +6, +3, +7, +5, +3, +2, +7, +3, +0, +6, +3, +6, +7, +3, +5, +2, +5, +0, +1, +0, +0, +7, +3, +0, +3, +6, +7, +4, +1, +4, +5, +5, +2, +5, +2, +4, +6, +2, +2, +2, +5, +0, +7, +0, +3, +5, +6, +2, +0, +3, +4, +3, +5, +0, +6, +1, +1, +5, +7, +1, +2, +3, +0, +7, +1, +0, +0, +0, +7, +7, +5, +2, +5, +2, +4, +6, +1, +2, +2, +1, +0, +6, +5, +4, +4, +0, +4, +0, +7, +5, +5, +6, +5, +2, +3, +4, +7, +0, +6, +6, +6, +6, +0, +0, +2, +3, +6, +4, +1, +6, +7, +7, +0, +2, +1, +0, +2, +3, +4, +2, +5, +7, +1, +7, +0, +1, +2, +6, +1, +4, +0, +7, +7, +3, +3, +4, +0, +6, +0, +1, +6, +3, +2, +7, +6, +0, +2, +5, +4, +2, +0, +0, +4, +7, +5, +6, +2, +7, +6, +2, +6, +3, +2, +1, +0, +4, +4, +4, +1, +5, +7, +4, +5, +7, +3, +0, +0, +3, +1, +6, +2, +1, +3, +0, +2, +0, +5, +3, +4, +5, +0, +1, +0, +7, +2, +6, +0, +5, +5, +3, +2, +7, +3, +0, +6, +0, +0, +3, +0, +4, +7, +6, +1, +2, +1, +5, +1, +7, +4, +7, +2, +3, +6, +6, +2, +0, +5, +6, +2, +1, +6, +2, +5, +3, +2, +3, +0, +2, +3, +6, +2, +7, +1, +4, +4, +2, +7, +7, +4, +3, +6, +5, +1, +6, +6, +2, +1, +6, +1, +4, +0, +5, +2, +2, +6, +4, +4, +5, +4, +3, +3, +5, +6, +3, +7, +0, +0, +4, +2, +4, +3, +1, +2, +6, +3, +0, +5, +4, +6, +4, +3, +7, +7, +7, +4, +0, +7, +7, +1, +2, +7, +6, +1, +7, +6, +6, +0, +4, +4, +3, +5, +3, +3, +5, +3, +2, +4, +2, +2, +6, +1, +6, +7, +1, +4, +0, +0, +4, +6, +1, +1, +1, +6, +0, +6, +3, +3, +5, +3, +6, +5, +4, +2, +0, +6, +0, +2, +4, +5, +2, +1, +5, +2, +7, +4, +5, +1, +2, +3, +7, +7, +6, +5, +4, +6, +7, +6, +6, +2, +5, +7, +5, +6, +7, +7, +5, +3, +6, +7, +4, +2, +4, +4, +7, +6, +3, +6, +6, +1, +6, +1, +6, +5, +3, +1, +6, +1, +0, +0, +4, +7, +1, +1, +1, +4, +3, +6, +6, +4, +1, +0, +6, +2, +6, +5, +4, +5, +6, +0, +5, +1, +4, +6, +7, +6, +2, +5, +1, +0, +4, +2, +2, +2, +7, +5, +7, +7, +5, +7, +6, +3, +0, +1, +4, +0, +1, +4, +2, +7, +0, +4, +6, +5, +0, +2, +6, +2, +7, +1, +2, +0, +7, +7, +7, +3, +6, +2, +3, +3, +6, +2, +1, +7, +3, +1, +3, +2, +3, +7, +1, +1, +6, +6, +4, +1, +4, +1, +0, +2, +5, +7, +5, +7, +3, +5, +5, +3, +1, +5, +5, +7, +5, +2, +1, +0, +7, +4, +0, +2, +6, +1, +0, +5, +3, +0, +7, +7, +4, +7, +5, +2, +6, +7, +7, +5, +4, +0, +2, +1, +3, +5, +6, +7, +3, +2, +7, +5, +3, +6, +2, +3, +7, +5, +0, +5, +1, +0, +2, +1, +3, +1, +7, +6, +0, +1, +0, +7, +1, +2, +6, +1, +6, +0, +3, +2, +3, +5, +0, +6, +7, +1, +1, +1, +0, +7, +0, +3, +1, +7, +6, +0, +6, +4, +6, +7, +2, +7, +3, +7, +5, +4, +1, +6, +6, +5, +6, +6, +1, +6, +7, +0, +6, +1, +1, +6, +1, +4, +1, +0, +4, +6, +2, +5, +1, +1, +6, +7, +2, +3, +6, +2, +3, +3, +2, +4, +1, +0, +6, +1, +2, +5, +6, +1, +1, +7, +7, +5, +7, +3, +3, +5, +7, +7, +7, +0, +3, +2, +1, +4, +2, +3, +1, +3, +7, +0, +7, +1, +4, +2, +1, +5, +0, +0, +5, +0, +4, +3, +0, +4, +1, +5, +3, +2, +0, +5, +5, +7, +5, +1, +7, +3, +0, +6, +2, +2, +4, +6, +3, +3, +0, +7, +7, +7, +5, +6, +6, +1, +6, +6, +6, +6, +3, +6, +6, +6, +0, +5, +5, +2, +7, +3, +2, +2, +5, +2, +4, +6, +7, +6, +2, +0, +5, +5, +3, +7, +3, +7, +2, +5, +5, +6, +0, +4, +3, +7, +5, +3, +4, +7, +3, +0, +3, +5, +2, +2, +4, +0, +3, +6, +7, +0, +3, +7, +2, +6, +3, +5, +3, +7, +4, +0, +1, +7, +6, +3, +0, +6, +5, +4, +7, +7, +3, +2, +3, +1, +2, +2, +0, +3, +5, +5, +4, +4, +1, +1, +4, +5, +7, +4, +0, +1, +1, +0, +5, +5, +3, +4, +5, +3, +3, +4, +6, +3, +3, +3, +2, +2, +4, +1, +2, +0, +0, +2, +1, +2, +6, +3, +2, +0, +1, +0, +2, +5, +3, +7, +6, +2, +2, +6, +3, +6, +6, +3, +3, +4, +5, +3, +0, +5, +7, +4, +1, +5, +2, +7, +7, +3, +3, +0, +6, +0, +5, +4, +3, +0, +1, +0, +0, +5, +2, +5, +5, +5, +1, +0, +4, +5, +4, +5, +1, +5, +0, +2, +6, +2, +7, +6, +1, +2, +7, +0, +0, +5, +4, +6, +2, +2, +0, +7, +0, +4, +5, +1, +1, +1, +4, +3, +3, +7, +5, +1, +5, +6, +3, +4, +0, +1, +0, +7, +3, +7, +4, +1, +0, +7, +0, +7, +5, +3, +4, +0, +2, +2, +3, +5, +3, +5, +5, +7, +0, +4, +0, +5, +4, +0, +3, +3, +3, +3, +2, +4, +5, +7, +6, +6, +4, +4, +0, +6, +4, +6, +0, +7, +0, +5, +3, +2, +6, +0, +1, +2, +5, +6, +4, +5, +5, +1, +1, +7, +7, +0, +2, +3, +4, +1, +6, +1, +0, +5, +3, +1, +1, +0, +4, +7, +5, +0, +1, +1, +5, +7, +2, +7, +1, +4, +0, +4, +4, +7, +0, +3, +4, +6, +6, +0, +1, +6, +2, +5, +1, +5, +1, +6, +7, +6, +7, +7, +1, +1, +3, +2, +0, +5, +4, +6, +1, +7, +7, +1, +7, +2, +7, +2, +1, +1, +5, +1, +5, +1, +4, +3, +2, +6, +2, +5, +0, +7, +4, +0, +7, +3, +5, +0, +4, +5, +2, +6, +3, +4, +7, +5, +2, +2, +4, +3, +0, +2, +5, +6, +3, +1, +5, +2, +4, +2, +1, +1, +2, +2, +6, +5, +6, +4, +3, +4, +6, +1, +0, +7, +7, +3, +4, +6, +0, +1, +2, +0, +1, +2, +5, +0, +3, +1, +2, +2, +4, +4, +4, +4, +4, +4, +6, +5, +0, +7, +1, +5, +4, +1, +6, +6, +1, +6, +0, +2, +3, +4, +6, +4, +0, +2, +3, +7, +2, +3, +4, +2, +7, +1, +2, +7, +2, +6, +5, +5, +0, +7, +2, +5, +4, +6, +3, +7, +3, +7, +1, +3, +0, +2, +1, +4, +5, +2, +5, +2, +1, +1, +3, +4, +4, +4, +6, +1, +4, +1, +7, +6, +5, +7, +0, +3, +0, +6, +2, +6, +7, +6, +2, +1, +3, +4, +5, +7, +4, +3, +3, +4, +5, +0, +4, +6, +6, +7, +6, +0, +0, +7, +1, +4, +7, +0, +2, +4, +2, +7, +2, +7, +2, +6, +1, +6, +2, +6, +7, +6, +1, +0, +3, +1, +3, +2, +3, +5, +2, +3, +1, +1, +6, +3, +1, +5, +5, +3, +4, +4, +7, +1, +5, +6, +4, +3, +3, +5, +5, +1, +7, +7, +1, +7, +1, +2, +2, +6, +6, +3, +1, +1, +1, +7, +3, +0, +5, +1, +1, +0, +2, +2, +1, +7, +7, +6, +6, +5, +1, +2, +0, +2, +1, +2, +3, +2, +0, +0, +6, +6, +5, +6, +1, +7, +6, +3, +4, +4, +7, +6, +7, +4, +1, +3, +6, +1, +2, +3, +1, +4, +7, +5, +5, +0, +1, +3, +2, +1, +5, +6, +2, +4, +4, +6, +7, +4, +3, +4, +3, +5, +0, +2, +2, +0, +5, +6, +4, +0, +0, +1, +7, +1, +5, +7, +5, +6, +0, +1, +7, +2, +3, +2, +6, +7, +2, +5, +2, +1, +3, +0, +5, +5, +5, +6, +0, +6, +0, +5, +2, +2, +5, +3, +1, +2, +3, +3, +6, +2, +0, +1, +7, +2, +1, +1, +7, +0, +2, +1, +5, +1, +6, +3, +3, +3, +7, +5, +6, +4, +2, +7, +6, +2, +1, +4, +0, +7, +4, +5, +6, +2, +5, +2, +4, +0, +6, +5, +3, +2, +5, +7, +7, +3, +0, +4, +0, +6, +4, +2, +6, +1, +1, +6, +7, +3, +7, +2, +0, +5, +6, +0, +3, +4, +6, +0, +2, +2, +3, +3, +0, +6, +5, +2, +2, +6, +6, +3, +0, +0, +4, +7, +6, +2, +4, +7, +4, +5, +7, +5, +2, +2, +7, +2, +5, +1, +3, +1, +6, +0, +3, +5, +5, +3, +1, +4, +4, +2, +3, +1, +3, +1, +0, +1, +2, +3, +7, +6, +7, +4, +2, +1, +1, +0, +5, +3, +4, +4, +0, +7, +5, +2, +2, +1, +5, +3, +6, +6, +6, +1, +7, +5, +7, +1, +5, +5, +5, +5, +4, +6, +5, +4, +3, +7, +0, +6, +0, +3, +7, +3, +0, +3, +2, +5, +2, +4, +3, +4, +5, +4, +6, +6, +0, +1, +2, +4, +6, +7, +1, +2, +6, +3, +2, +2, +2, +7, +1, +3, +5, +1, +5, +1, +6, +1, +5, +7, +7, +0, +2, +3, +0, +3, +1, +6, +7, +3, +6, +5, +3, +3, +2, +6, +5, +2, +3, +0, +3, +2, +4, +3, +4, +3, +1, +2, +2, +6, +6, +6, +4, +2, +0, +2, +3, +4, +6, +7, +0, +7, +6, +3, +1, +5, +4, +2, +5, +3, +0, +7, +2, +7, +7, +5, +0, +6, +4, +7, +3, +5, +4, +4, +3, +0, +5, +5, +1, +2, +4, +1, +0, +7, +6, +5, +7, +7, +1, +5, +6, +7, +6, +5, +3, +6, +1, +6, +0, +3, +1, +3, +4, +5, +1, +7, +7, +6, +4, +6, +5, +0, +3, +0, +2, +1, +4, +0, +4, +5, +3, +1, +4, +3, +4, +1, +5, +7, +5, +1, +7, +0, +3, +6, +5, +1, +3, +4, +4, +2, +0, +6, +1, +5, +4, +4, +6, +1, +7, +7, +3, +6, +1, +2, +1, +6, +7, +0, +6, +7, +2, +7, +1, +7, +4, +3, +7, +2, +3, +2, +3, +4, +0, +0, +5, +3, +1, +7, +6, +7, +6, +3, +7, +7, +6, +7, +5, +0, +6, +2, +2, +1, +2, +5, +4, +7, +5, +3, +5, +7, +4, +6, +5, +3, +1, +3, +7, +4, +2, +0, +1, +1, +0, +5, +0, +0, +0, +4, +3, +5, +2, +7, +3, +1, +4, +0, +3, +3, +1, +3, +2, +6, +3, +3, +6, +5, +0, +1, +7, +3, +4, +7, +2, +4, +3, +0, +6, +3, +2, +6, +4, +2, +5, +6, +7, +0, +0, +7, +3, +4, +5, +6, +7, +2, +0, +2, +7, +6, +1, +1, +3, +5, +4, +7, +7, +3, +5, +7, +4, +7, +6, +7, +6, +0, +7, +3, +4, +1, +4, +3, +5, +7, +0, +6, +2, +3, +5, +6, +1, +3, +3, +2, +2, +6, +6, +0, +3, +7, +1, +2, +6, +2, +1, +6, +0, +2, +3, +4, +7, +2, +1, +5, +2, +4, +5, +7, +0, +5, +1, +4, +4, +2, +7, +6, +7, +6, +3, +3, +0, +2, +5, +2, +5, +1, +2, +0, +7, +5, +0, +4, +6, +6, +1, +5, +2, +6, +0, +4, +0, +4, +5, +7, +3, +5, +7, +4, +4, +0, +0, +2, +3, +7, +4, +1, +1, +2, +2, +3, +4, +2, +6, +3, +7, +3, +3, +7, +7, +2, +4, +7, +0, +7, +3, +7, +6, +4, +5, +6, +0, +1, +2, +2, +2, +1, +3, +4, +4, +7, +1, +2, +5, +4, +3, +6, +7, +5, +4, +3, +6, +1, +3, +5, +0, +1, +3, +1, +1, +5, +3, +7, +1, +1, +0, +4, +1, +2, +0, +6, +5, +3, +5, +2, +6, +3, +7, +1, +2, +2, +3, +6, +3, +4, +3, +6, +6, +4, +1, +0, +2, +7, +7, +7, +2, +7, +6, +5, +1, +1, +1, +5, +5, +5, +4, +7, +2, +7, +4, +6, +0, +6, +7, +4, +0, +1, +1, +4, +5, +0, +2, +0, +7, +0, +6, +7, +5, +3, +6, +5, +0, +5, +5, +0, +3, +4, +6, +5, +6, +4, +2, +2, +1, +6, +0, +4, +0, +4, +7, +7, +6, +7, +5, +0, +0, +2, +7, +2, +5, +6, +1, +0, +1, +7, +6, +6, +7, +5, +3, +1, +2, +5, +1, +3, +0, +0, +0, +7, +3, +6, +6, +2, +6, +4, +5, +1, +5, +3, +0, +5, +6, +0, +4, +2, +7, +3, +1, +1, +6, +3, +0, +5, +0, +0, +0, +1, +5, +5, +7, +5, +2, +4, +4, +3, +0, +2, +6, +4, +5, +1, +0, +1, +7, +1, +6, +0, +2, +7, +7, +3, +5, +3, +5, +5, +5, +2, +1, +7, +1, +5, +3, +5, +1, +6, +0, +1, +3, +6, +6, +5, +6, +7, +2, +5, +7, +4, +7, +5, +2, +1, +4, +5, +6, +2, +6, +3, +4, +4, +5, +1, +0, +6, +2, +3, +7, +0, +5, +2, +1, +0, +7, +5, +2, +4, +3, +2, +5, +0, +6, +6, +2, +2, +6, +3, +1, +6, +7, +4, +1, +2, +2, +5, +6, +7, +0, +0, +6, +1, +4, +0, +5, +1, +3, +0, +3, +3, +4, +5, +4, +2, +3, +6, +1, +4, +3, +5, +1, +6, +6, +1, +1, +6, +5, +7, +7, +7, +6, +4, +7, +0, +2, +6, +4, +6, +1, +5, +6, +7, +0, +7, +4, +4, +1, +6, +4, +1, +3, +3, +6, +6, +4, +7, +3, +6, +0, +5, +4, +2, +4, +4, +1, +4, +6, +2, +5, +7, +5, +0, +4, +2, +3, +5, +6, +0, +1, +2, +1, +3, +4, +7, +2, +5, +3, +4, +4, +6, +2, +7, +1, +4, +3, +7, +7, +0, +2, +7, +4, +5, +0, +7, +3, +3, +3, +4, +1, +5, +4, +1, +6, +0, +6, +4, +2, +5, +4, +7, +1, +0, +4, +1, +1, +5, +3, +5, +0, +1, +1, +7, +5, +1, +2, +5, +6, +2, +5, +0, +6, +5, +0, +4, +7, +4, +7, +5, +2, +0, +3, +5, +5, +7, +3, +1, +0, +5, +5, +3, +1, +4, +2, +6, +0, +4, +7, +0, +3, +4, +1, +2, +4, +6, +2, +6, +1, +7, +6, +7, +1, +3, +3, +4, +5, +3, +7, +7, +4, +7, +6, +1, +1, +5, +0, +6, +6, +1, +1, +7, +1, +4, +3, +5, +1, +5, +1, +3, +0, +5, +5, +2, +0, +5, +3, +7, +7, +7, +2, +5, +6, +1, +7, +6, +1, +0, +6, +2, +6, +2, +4, +7, +7, +3, +0, +7, +6, +5, +2, +6, +6, +2, +2, +0, +5, +2, +5, +1, +2, +6, +7, +1, +1, +5, +5, +1, +5, +0, +6, +3, +5, +0, +5, +6, +0, +6, +4, +4, +1, +4, +2, +0, +2, +2, +1, +6, +7, +2, +7, +7, +1, +0, +3, +3, +2, +5, +1, +7, +1, +7, +7, +1, +7, +6, +3, +3, +7, +6, +7, +5, +3, +1, +4, +7, +0, +5, +0, +6, +5, +4, +0, +3, +4, +3, +1, +4, +3, +4, +1, +6, +3, +6, +7, +6, +3, +2, +4, +7, +3, +5, +0, +1, +6, +1, +3, +4, +7, +2, +1, +3, +4, +0, +5, +6, +0, +2, +2, +0, +0, +7, +6, +6, +1, +3, +6, +6, +6, +6, +2, +6, +7, +3, +0, +4, +0, +5, +4, +7, +7, +7, +7, +3, +3, +6, +2, +2, +1, +7, +0, +1, +1, +5, +3, +7, +4, +6, +3, +5, +2, +4, +2, +7, +5, +1, +4, +0, +7, +3, +3, +0, +4, +7, +5, +2, +3, +5, +1, +3, +1, +5, +0, +5, +4, +1, +4, +0, +4, +3, +0, +7, +7, +7, +1, +2, +2, +3, +7, +4, +7, +0, +7, +0, +4, +4, +0, +0, +1, +0, +7, +0, +1, +1, +1, +1, +3, +5, +3, +6, +4, +1, +2, +2, +3, +6, +1, +6, +1, +0, +3, +1, +1, +2, +4, +5, +4, +4, +7, +0, +5, +1, +0, +6, +4, +0, +4, +0, +1, +6, +6, +4, +1, +0, +1, +0, +1, +2, +6, +3, +2, +1, +2, +2, +5, +3, +2, +0, +2, +7, +5, +3, +4, +2, +7, +3, +1, +5, +0, +0, +2, +5, +4, +0, +2, +0, +3, +1, +5, +5, +0, +2, +3, +5, +7, +7, +3, +4, +6, +3, +3, +5, +6, +3, +1, +7, +5, +7, +3, +4, +0, +2, +0, +5, +5, +5, +1, +0, +5, +2, +0, +6, +6, +6, +3, +1, +6, +7, +7, +3, +5, +4, +7, +7, +7, +7, +7, +7, +4, +4, +6, +7, +1, +6, +5, +3, +7, +1, +4, +6, +4, +1, +6, +0, +7, +5, +1, +0, +0, +3, +7, +2, +6, +6, +7, +3, +2, +0, +7, +1, +5, +2, +3, +5, +5, +6, +3, +7, +0, +5, +2, +0, +2, +2, +0, +2, +6, +3, +6, +0, +2, +0, +6, +5, +0, +1, +7, +2, +0, +7, +6, +5, +5, +1, +5, +6, +4, +0, +3, +5, +4, +0, +3, +0, +2, +4, +4, +2, +4, +3, +2, +6, +0, +1, +7, +5, +0, +1, +1, +3, +2, +3, +6, +4, +0, +0, +2, +4, +4, +4, +0, +5, +5, +4, +1, +6, +4, +1, +4, +7, +0, +3, +3, +1, +6, +3, +2, +7, +4, +4, +0, +5, +4, +1, +7, +7, +2, +3, +2, +1, +2, +1, +4, +7, +4, +3, +4, +4, +7, +0, +1, +7, +7, +4, +6, +6, +4, +2, +1, +7, +5, +5, +0, +0, +3, +5, +7, +0, +6, +6, +4, +5, +3, +4, +5, +3, +6, +6, +3, +4, +1, +1, +7, +5, +0, +7, +2, +7, +2, +4, +0, +0, +2, +2, +7, +3, +3, +7, +2, +6, +1, +4, +3, +0, +2, +0, +6, +2, +3, +4, +3, +2, +0, +0, +7, +6, +7, +6, +6, +2, +6, +5, +5, +5, +7, +6, +0, +5, +7, +5, +7, +5, +2, +4, +1, +6, +3, +3, +7, +2, +6, +0, +3, +6, +3, +1, +5, +6, +6, +5, +7, +4, +4, +7, +6, +4, +3, +2, +7, +1, +2, +5, +6, +6, +2, +1, +0, +2, +4, +0, +0, +0, +1, +7, +4, +5, +5, +3, +6, +5, +1, +4, +3, +1, +6, +2, +0, +2, +2, +4, +1, +0, +4, +2, +1, +6, +6, +1, +1, +6, +4, +7, +4, +5, +7, +1, +5, +0, +2, +0, +0, +0, +4, +5, +5, +2, +5, +6, +7, +2, +5, +0, +2, +2, +6, +1, +6, +2, +3, +6, +4, +7, +6, +6, +1, +5, +5, +5, +2, +3, +6, +5, +3, +3, +4, +1, +4, +6, +6, +5, +1, +5, +6, +6, +3, +2, +4, +6, +3, +4, +4, +1, +6, +3, +1, +6, +4, +4, +0, +2, +7, +6, +4, +5, +4, +6, +6, +3, +7, +4, +0, +3, +4, +3, +6, +1, +0, +2, +6, +1, +5, +4, +6, +5, +3, +7, +1, +7, +0, +1, +5, +5, +3, +2, +1, +3, +7, +4, +2, +0, +2, +0, +0, +3, +0, +7, +0, +2, +0, +7, +6, +1, +5, +3, +7, +6, +5, +5, +5, +0, +3, +1, +7, +4, +6, +7, +7, +0, +2, +1, +4, +4, +7, +1, +7, +1, +0, +2, +2, +2, +2, +1, +1, +0, +0, +1, +4, +6, +6, +4, +0, +1, +1, +1, +6, +6, +1, +5, +7, +0, +7, +0, +4, +4, +2, +5, +6, +7, +4, +5, +1, +6, +3, +6, +6, +1, +0, +3, +7, +1, +1, +1, +7, +5, +2, +5, +3, +0, +0, +4, +5, +3, +6, +1, +6, +0, +0, +2, +5, +7, +2, +5, +7, +4, +4, +1, +4, +7, +0, +2, +7, +7, +3, +4, +0, +3, +0, +3, +0, +3, +4, +5, +0, +0, +3, +3, +3, +7, +6, +6, +6, +4, +2, +6, +5, +7, +2, +7, +5, +4, +1, +6, +1, +7, +7, +2, +0, +1, +0, +2, +7, +5, +2, +1, +6, +7, +1, +3, +5, +1, +6, +0, +2, +6, +4, +2, +6, +2, +3, +5, +6, +1, +1, +0, +0, +6, +2, +2, +1, +0, +2, +7, +0, +7, +2, +4, +0, +1, +5, +7, +0, +2, +6, +4, +2, +2, +4, +0, +4, +4, +6, +7, +7, +7, +5, +7, +3, +6, +6, +4, +0, +1, +2, +4, +3, +3, +6, +5, +5, +5, +3, +4, +6, +4, +7, +1, +6, +6, +6, +3, +5, +6, +1, +2, +3, +5, +7, +2, +0, +2, +7, +6, +1, +0, +1, +3, +7, +2, +4, +4, +0, +3, +7, +0, +1, +0, +1, +1, +0, +4, +7, +4, +0, +1, +0, +4, +7, +2, +3, +3, +1, +2, +3, +0, +6, +7, +1, +6, +2, +7, +6, +4, +6, +1, +6, +4, +7, +6, +2, +3, +2, +1, +6, +1, +4, +0, +2, +0, +3, +6, +0, +5, +5, +7, +3, +4, +2, +7, +1, +2, +0, +1, +6, +5, +2, +0, +5, +3, +5, +3, +0, +1, +1, +0, +7, +5, +6, +7, +5, +5, +2, +4, +5, +6, +0, +3, +5, +3, +5, +1, +5, +1, +4, +1, +6, +4, +5, +3, +3, +2, +4, +7, +1, +1, +4, +0, +2, +6, +2, +6, +2, +6, +7, +6, +5, +5, +6, +1, +3, +7, +6, +0, +6, +1, +1, +4, +5, +1, +3, +2, +1, +3, +5, +2, +7, +6, +3, +6, +7, +7, +7, +6, +5, +2, +4, +7, +7, +0, +4, +3, +2, +6, +6, +5, +3, +0, +1, +1, +2, +6, +7, +7, +2, +0, +6, +4, +4, +2, +0, +7, +2, +5, +3, +6, +5, +0, +7, +3, +5, +3, +3, +4, +7, +0, +2, +0, +6, +4, +5, +5, +6, +1, +7, +3, +3, +7, +4, +6, +4, +6, +7, +5, +2, +3, +2, +1, +2, +1, +2, +7, +2, +3, +6, +7, +7, +4, +6, +3, +0, +7, +7, +1, +5, +5, +6, +0, +7, +3, +5, +4, +4, +2, +5, +1, +2, +5, +1, +1, +4, +7, +2, +1, +0, +0, +1, +3, +2, +1, +2, +6, +7, +2, +4, +2, +2, +0, +3, +4, +5, +7, +2, +0, +1, +6, +2, +2, +3, +6, +4, +7, +0, +2, +3, +0, +7, +5, +5, +5, +7, +1, +7, +1, +7, +6, +5, +6, +0, +4, +2, +6, +6, +0, +7, +1, +7, +7, +3, +5, +3, +1, +2, +4, +6, +5, +6, +7, +4, +7, +6, +6, +1, +6, +3, +0, +7, +2, +0, +0, +5, +6, +2, +4, +3, +0, +3, +6, +3, +4, +2, +3, +0, +0, +7, +6, +2, +0, +6, +7, +0, +6, +5, +1, +5, +4, +3, +7, +4, +2, +0, +3, +7, +5, +6, +5, +0, +4, +0, +5, +6, +3, +6, +6, +7, +4, +0, +3, +7, +6, +1, +7, +7, +7, +7, +6, +6, +5, +2, +2, +3, +5, +6, +2, +1, +6, +1, +5, +4, +4, +7, +4, +6, +0, +2, +2, +7, +4, +5, +4, +6, +5, +1, +4, +2, +7, +3, +1, +0, +0, +3, +5, +1, +4, +1, +0, +3, +1, +1, +4, +3, +4, +2, +0, +0, +5, +3, +4, +3, +7, +5, +5, +3, +2, +4, +1, +5, +0, +0, +2, +0, +4, +7, +6, +2, +7, +4, +4, +4, +1, +7, +1, +7, +1, +4, +2, +4, +1, +4, +1, +5, +0, +1, +2, +3, +2, +7, +1, +6, +1, +6, +1, +1, +6, +3, +0, +4, +2, +7, +6, +7, +7, +4, +4, +2, +5, +4, +0, +7, +3, +6, +2, +3, +4, +2, +3, +0, +2, +7, +2, +1, +5, +6, +7, +0, +5, +7, +3, +2, +4, +3, +3, +5, +5, +3, +3, +1, +2, +3, +6, +1, +4, +0, +7, +3, +5, +5, +4, +2, +6, +0, +6, +0, +6, +3, +4, +4, +5, +7, +1, +2, +3, +5, +3, +3, +3, +5, +5, +7, +3, +6, +0, +5, +3, +0, +5, +3, +5, +7, +6, +1, +4, +4, +1, +6, +2, +5, +1, +2, +7, +4, +6, +3, +1, +0, +4, +0, +6, +0, +3, +2, +2, +1, +1, +0, +6, +0, +7, +6, +1, +5, +2, +1, +6, +4, +2, +1, +2, +0, +3, +7, +4, +4, +0, +0, +1, +3, +0, +6, +3, +2, +2, +1, +7, +1, +0, +3, +4, +3, +4, +0, +5, +3, +4, +3, +1, +2, +0, +5, +3, +2, +2, +6, +5, +5, +4, +0, +1, +0, +4, +7, +3, +0, +1, +3, +3, +1, +4, +5, +1, +0, +2, +4, +4, +0, +4, +5, +6, +3, +0, +4, +7, +6, +7, +7, +5, +6, +3, +3, +2, +2, +6, +7, +0, +7, +1, +7, +2, +7, +5, +0, +7, +4, +1, +3, +3, +5, +7, +4, +0, +5, +1, +7, +1, +6, +0, +2, +1, +7, +6, +3, +4, +5, +7, +7, +7, +7, +7, +0, +3, +2, +2, +5, +6, +7, +4, +0, +2, +7, +3, +6, +4, +4, +5, +5, +5, +6, +5, +7, +6, +6, +6, +3, +1, +0, +2, +3, +6, +6, +6, +5, +7, +6, +6, +1, +2, +2, +0, +2, +4, +5, +4, +1, +3, +7, +5, +5, +2, +5, +0, +2, +4, +4, +6, +5, +2, +1, +4, +7, +3, +4, +0, +3, +6, +3, +3, +7, +6, +5, +1, +4, +7, +7, +2, +7, +3, +1, +7, +4, +7, +3, +2, +3, +2, +5, +7, +0, +3, +5, +0, +3, +1, +2, +2, +5, +2, +5, +5, +1, +2, +5, +7, +1, +3, +4, +3, +5, +7, +7, +3, +6, +4, +5, +1, +1, +0, +0, +3, +7, +3, +6, +0, +2, +0, +5, +7, +3, +3, +2, +2, +4, +4, +0, +1, +1, +6, +5, +6, +4, +7, +1, +2, +7, +7, +4, +6, +0, +3, +1, +2, +7, +6, +4, +5, +7, +3, +4, +4, +1, +5, +7, +5, +7, +6, +7, +4, +0, +0, +4, +4, +6, +3, +0, +4, +6, +3, +5, +1, +7, +3, +0, +4, +2, +2, +1, +3, +6, +5, +3, +4, +1, +3, +0, +0, +1, +4, +0, +5, +5, +5, +4, +1, +5, +4, +4, +4, +6, +4, +5, +5, +2, +3, +1, +4, +1, +1, +6, +2, +0, +2, +6, +1, +0, +2, +2, +3, +7, +2, +1, +1, +6, +7, +2, +7, +6, +6, +6, +1, +6, +6, +2, +6, +3, +1, +1, +4, +5, +7, +3, +1, +4, +7, +0, +6, +7, +5, +0, +5, +2, +1, +1, +5, +6, +3, +0, +1, +6, +7, +5, +4, +2, +1, +3, +1, +5, +6, +6, +4, +0, +2, +6, +7, +7, +7, +0, +1, +2, +4, +5, +5, +6, +6, +2, +7, +7, +2, +3, +5, +4, +6, +4, +2, +1, +3, +7, +4, +0, +6, +1, +1, +2, +3, +1, +4, +4, +3, +5, +1, +3, +1, +7, +1, +1, +1, +6, +6, +1, +2, +3, +4, +3, +6, +4, +3, +4, +7, +4, +1, +6, +0, +4, +7, +2, +4, +5, +2, +7, +4, +6, +4, +6, +0, +7, +7, +6, +0, +4, +4, +1, +7, +1, +1, +3, +6, +5, +0, +3, +6, +3, +2, +5, +7, +6, +0, +5, +5, +1, +1, +1, +5, +1, +1, +3, +6, +6, +7, +7, +0, +7, +4, +5, +2, +7, +4, +2, +2, +3, +3, +2, +1, +4, +5, +1, +2, +2, +5, +6, +5, +3, +2, +4, +4, +3, +2, +7, +5, +2, +0, +7, +0, +2, +6, +6, +5, +1, +0, +2, +4, +1, +5, +3, +1, +2, +7, +5, +6, +3, +4, +4, +1, +2, +6, +4, +0, +5, +3, +4, +0, +6, +6, +6, +4, +6, +4, +5, +1, +6, +6, +3, +4, +2, +7, +7, +3, +3, +4, +4, +6, +0, +2, +5, +6, +7, +1, +7, +1, +1, +4, +7, +2, +2, +3, +3, +1, +7, +5, +0, +7, +3, +4, +5, +1, +7, +5, +6, +4, +0, +1, +7, +6, +0, +2, +5, +2, +5, +3, +0, +3, +5, +3, +1, +6, +5, +3, +1, +2, +5, +4, +6, +3, +6, +6, +7, +3, +0, +3, +3, +5, +7, +5, +1, +4, +6, +6, +0, +1, +3, +4, +0, +2, +4, +2, +2, +1, +5, +1, +3, +3, +1, +5, +7, +0, +7, +0, +4, +2, +4, +2, +7, +4, +3, +4, +1, +0, +1, +6, +2, +2, +3, +4, +0, +5, +0, +1, +5, +6, +1, +3, +7, +3, +1, +2, +5, +0, +7, +6, +7, +7, +5, +1, +5, +7, +6, +1, +1, +6, +1, +0, +6, +7, +5, +1, +1, +6, +3, +7, +0, +5, +7, +0, +4, +0, +7, +7, +7, +4, +0, +5, +3, +0, +0, +0, +4, +1, +2, +4, +2, +6, +1, +5, +1, +5, +3, +0, +2, +0, +6, +3, +4, +5, +0, +7, +3, +0, +1, +6, +5, +1, +3, +3, +2, +2, +7, +6, +0, +1, +1, +1, +0, +0, +1, +2, +5, +2, +3, +6, +7, +0, +3, +2, +1, +5, +5, +6, +6, +3, +4, +3, +1, +5, +6, +4, +2, +2, +7, +1, +0, +3, +1, +1, +1, +0, +6, +4, +0, +6, +6, +6, +0, +4, +4, +5, +3, +3, +1, +0, +2, +5, +6, +6, +4, +1, +7, +3, +0, +3, +4, +0, +3, +2, +3, +7, +4, +0, +1, +0, +5, +0, +5, +2, +7, +4, +3, +5, +6, +5, +3, +3, +0, +3, +4, +5, +0, +6, +4, +7, +1, +2, +2, +1, +7, +1, +3, +4, +7, +7, +3, +2, +2, +0, +2, +7, +5, +5, +3, +3, +7, +5, +7, +0, +4, +0, +5, +2, +3, +5, +0, +3, +6, +7, +2, +6, +2, +4, +6, +0, +4, +1, +5, +4, +2, +0, +0, +5, +5, +6, +6, +4, +7, +5, +6, +3, +7, +3, +2, +0, +6, +3, +5, +2, +5, +1, +0, +3, +7, +1, +3, +7, +2, +7, +2, +1, +1, +7, +6, +0, +4, +5, +3, +5, +1, +6, +4, +0, +7, +2, +1, +3, +7, +5, +0, +1, +2, +6, +4, +1, +0, +6, +0, +5, +7, +1, +5, +3, +6, +7, +0, +4, +5, +1, +5, +3, +4, +3, +4, +6, +7, +7, +4, +1, +0, +2, +4, +2, +1, +2, +1, +6, +3, +2, +2, +2, +1, +4, +1, +2, +4, +6, +4, +7, +0, +0, +1, +0, +4, +6, +2, +1, +1, +3, +5, +3, +3, +2, +4, +0, +1, +5, +6, +2, +4, +3, +4, +4, +3, +5, +3, +6, +6, +6, +5, +0, +5, +2, +5, +3, +0, +4, +7, +5, +0, +4, +4, +2, +2, +4, +2, +1, +1, +1, +6, +0, +4, +0, +3, +1, +0, +4, +6, +1, +6, +0, +2, +1, +0, +2, +7, +4, +0, +0, +3, +7, +0, +5, +5, +6, +6, +7, +6, +3, +2, +6, +7, +6, +6, +2, +0, +6, +7, +7, +4, +1, +7, +7, +6, +0, +5, +6, +7, +3, +3, +6, +0, +5, +3, +7, +6, +2, +2, +1, +1, +5, +4, +0, +4, +7, +2, +4, +5, +7, +4, +6, +3, +7, +7, +2, +2, +4, +0, +1, +0, +7, +4, +0, +2, +6, +3, +5, +3, +3, +4, +4, +1, +4, +2, +2, +2, +0, +6, +6, +3, +7, +4, +5, +0, +1, +3, +1, +7, +2, +6, +2, +6, +2, +4, +2, +5, +6, +1, +2, +1, +3, +5, +5, +4, +0, +2, +0, +4, +6, +1, +2, +1, +5, +6, +4, +0, +0, +1, +0, +1, +1, +5, +7, +7, +1, +4, +5, +4, +0, +0, +2, +2, +4, +3, +5, +6, +7, +6, +0, +4, +6, +1, +7, +4, +3, +6, +7, +4, +4, +7, +1, +4, +5, +0, +3, +0, +3, +4, +6, +0, +7, +5, +2, +6, +6, +1, +0, +0, +6, +0, +0, +6, +5, +5, +0, +7, +6, +2, +7, +6, +2, +2, +2, +3, +7, +1, +0, +5, +5, +0, +7, +7, +5, +5, +3, +3, +2, +3, +0, +1, +4, +6, +2, +1, +2, +0, +7, +6, +2, +6, +6, +3, +3, +7, +6, +5, +0, +1, +4, +4, +3, +6, +3, +0, +7, +5, +5, +5, +2, +6, +3, +0, +1, +7, +1, +7, +0, +1, +6, +3, +5, +2, +1, +4, +1, +5, +3, +1, +1, +3, +2, +4, +0, +7, +7, +0, +7, +1, +2, +7, +0, +4, +7, +3, +5, +3, +4, +6, +2, +3, +0, +0, +3, +5, +5, +1, +0, +4, +7, +3, +6, +0, +4, +7, +1, +0, +5, +1, +1, +7, +7, +1, +1, +5, +6, +7, +5, +5, +5, +1, +4, +7, +0, +7, +2, +0, +1, +2, +3, +0, +3, +1, +3, +2, +3, +2, +0, +1, +2, +6, +4, +7, +4, +1, +5, +4, +3, +2, +6, +2, +4, +5, +7, +3, +7, +3, +5, +0, +0, +5, +5, +4, +0, +4, +5, +2, +3, +2, +5, +6, +1, +4, +4, +4, +6, +7, +7, +4, +2, +4, +3, +5, +4, +3, +3, +6, +3, +5, +6, +6, +6, +6, +4, +2, +5, +7, +1, +5, +1, +3, +6, +1, +1, +1, +3, +6, +6, +2, +3, +0, +1, +6, +5, +4, +4, +0, +3, +3, +0, +0, +4, +7, +1, +6, +4, +3, +7, +1, +0, +5, +0, +0, +5, +5, +1, +1, +1, +3, +7, +4, +5, +5, +2, +0, +2, +5, +1, +4, +6, +2, +0, +7, +4, +5, +5, +4, +6, +5, +7, +7, +4, +4, +1, +1, +5, +3, +0, +4, +5, +7, +0, +5, +2, +6, +6, +1, +6, +2, +3, +2, +2, +2, +3, +6, +1, +1, +6, +3, +2, +4, +5, +1, +6, +4, +5, +7, +5, +7, +2, +6, +3, +4, +1, +6, +3, +4, +7, +2, +0, +3, +5, +6, +3, +0, +5, +6, +7, +0, +6, +6, +3, +6, +2, +3, +0, +6, +3, +3, +4, +4, +6, +7, +5, +0, +4, +5, +5, +1, +4, +5, +3, +0, +7, +1, +5, +4, +6, +3, +4, +6, +3, +1, +5, +6, +5, +5, +7, +0, +5, +4, +3, +6, +5, +3, +5, +1, +1, +7, +6, +6, +2, +1, +1, +1, +1, +2, +1, +4, +5, +0, +4, +1, +4, +4, +5, +4, +7, +4, +5, +3, +5, +3, +6, +0, +2, +7, +3, +1, +4, +0, +1, +7, +1, +3, +3, +1, +1, +7, +4, +4, +1, +6, +1, +4, +3, +2, +7, +0, +6, +0, +3, +5, +2, +3, +1, +3, +6, +0, +0, +5, +4, +3, +5, +6, +4, +5, +1, +1, +6, +4, +7, +2, +4, +3, +7, +2, +6, +5, +1, +7, +5, +4, +1, +6, +0, +4, +2, +1, +1, +5, +1, +6, +2, +2, +7, +1, +0, +3, +2, +2, +2, +3, +1, +2, +4, +1, +0, +2, +4, +7, +5, +2, +2, +6, +1, +5, +6, +6, +3, +0, +6, +6, +0, +5, +7, +4, +3, +2, +1, +4, +5, +4, +1, +4, +3, +2, +7, +0, +4, +2, +6, +6, +3, +0, +2, +6, +1, +0, +2, +0, +1, +5, +0, +1, +4, +0, +2, +5, +1, +4, +2, +4, +4, +4, +6, +0, +1, +4, +5, +6, +5, +4, +5, +6, +7, +3, +3, +5, +4, +4, +2, +2, +1, +2, +4, +1, +3, +7, +3, +2, +5, +2, +0, +5, +7, +3, +3, +4, +6, +2, +4, +2, +4, +7, +2, +0, +0, +1, +1, +1, +2, +2, +7, +5, +1, +3, +3, +5, +7, +1, +7, +4, +7, +3, +3, +0, +6, +6, +5, +4, +7, +7, +2, +7, +1, +7, +2, +7, +2, +2, +7, +5, +2, +2, +2, +1, +1, +2, +6, +7, +1, +5, +6, +2, +4, +6, +5, +1, +7, +6, +5, +4, +4, +0, +0, +0, +2, +5, +6, +3, +0, +3, +2, +5, +5, +5, +4, +2, +3, +6, +2, +0, +7, +1, +0, +0, +4, +6, +4, +7, +1, +4, +3, +7, +7, +7, +4, +1, +5, +6, +2, +5, +7, +0, +3, +1, +4, +4, +4, +6, +4, +7, +3, +1, +6, +2, +0, +1, +7, +5, +2, +6, +5, +1, +7, +1, +6, +5, +7, +3, +1, +2, +3, +5, +2, +1, +6, +1, +5, +6, +7, +2, +3, +6, +5, +6, +4, +7, +2, +1, +0, +2, +0, +2, +6, +5, +7, +0, +2, +2, +7, +1, +7, +7, +5, +7, +2, +4, +4, +4, +3, +2, +5, +3, +5, +3, +6, +5, +7, +1, +7, +4, +7, +3, +7, +6, +3, +4, +4, +5, +7, +4, +3, +0, +2, +1, +0, +2, +6, +3, +2, +7, +0, +7, +4, +2, +0, +7, +1, +1, +6, +7, +3, +0, +5, +3, +5, +7, +2, +6, +0, +6, +7, +0, +3, +3, +2, +4, +6, +5, +1, +6, +3, +4, +3, +1, +2, +7, +2, +5, +2, +1, +4, +7, +7, +4, +6, +2, +0, +2, +5, +0, +7, +3, +1, +1, +2, +2, +6, +0, +0, +4, +0, +1, +1, +4, +0, +1, +4, +7, +7, +6, +6, +4, +1, +2, +5, +7, +3, +1, +6, +5, +5, +1, +1, +2, +4, +2, +3, +7, +1, +1, +1, +7, +1, +0, +0, +3, +5, +7, +0, +2, +7, +1, +2, +2, +3, +5, +3, +7, +4, +1, +7, +4, +0, +3, +0, +0, +4, +2, +3, +0, +5, +5, +7, +0, +1, +4, +0, +4, +1, +2, +2, +3, +0, +3, +6, +4, +6, +1, +4, +0, +4, +7, +0, +5, +5, +0, +2, +6, +6, +6, +6, +0, +5, +5, +0, +1, +6, +3, +3, +3, +7, +6, +7, +0, +4, +1, +0, +3, +2, +5, +1, +3, +1, +5, +7, +2, +3, +5, +6, +2, +7, +3, +5, +0, +3, +4, +2, +1, +3, +7, +7, +6, +3, +2, +7, +3, +4, +7, +6, +0, +4, +4, +3, +1, +2, +2, +6, +5, +5, +3, +1, +5, +7, +5, +0, +4, +0, +3, +2, +3, +6, +0, +2, +2, +1, +2, +3, +3, +6, +7, +3, +2, +6, +5, +6, +4, +3, +0, +3, +3, +5, +0, +7, +6, +7, +2, +7, +4, +4, +4, +4, +0, +2, +7, +6, +5, +3, +4, +1, +0, +3, +2, +5, +1, +4, +7, +4, +0, +6, +6, +1, +0, +3, +3, +0, +2, +4, +4, +0, +7, +2, +7, +3, +0, +6, +1, +5, +2, +4, +3, +2, +7, +1, +3, +2, +2, +2, +7, +6, +1, +6, +5, +3, +2, +6, +0, +2, +7, +1, +4, +4, +4, +7, +1, +3, +4, +2, +3, +3, +3, +2, +3, +2, +1, +5, +7, +4, +0, +5, +7, +3, +0, +0, +5, +3, +4, +5, +6, +5, +4, +6, +0, +6, +6, +1, +1, +6, +7, +3, +6, +0, +0, +2, +3, +0, +1, +2, +3, +7, +5, +6, +5, +7, +2, +3, +3, +6, +2, +3, +6, +6, +7, +2, +2, +3, +1, +5, +4, +5, +0, +1, +2, +6, +0, +3, +6, +2, +6, +1, +3, +2, +4, +1, +3, +3, +7, +1, +5, +6, +4, +5, +3, +4, +6, +1, +7, +5, +3, +3, +0, +7, +4, +3, +4, +4, +3, +7, +6, +1, +0, +0, +1, +3, +2, +2, +5, +0, +7, +4, +0, +3, +1, +3, +0, +4, +5, +6, +2, +4, +4, +1, +0, +4, +2, +5, +7, +7, +6, +3, +6, +6, +7, +6, +2, +3, +0, +5, +3, +1, +2, +3, +5, +5, +7, +6, +1, +5, +0, +7, +6, +7, +7, +6, +6, +6, +0, +7, +2, +3, +6, +6, +2, +0, +3, +6, +6, +0, +7, +5, +0, +4, +1, +2, +3, +1, +6, +3, +3, +4, +5, +3, +2, +5, +4, +3, +5, +0, +0, +3, +3, +0, +3, +6, +7, +2, +3, +7, +5, +1, +6, +6, +4, +0, +0, +0, +3, +6, +7, +2, +7, +2, +3, +2, +7, +0, +3, +4, +4, +3, +0, +6, +2, +6, +7, +5, +1, +2, +1, +6, +3, +5, +7, +1, +0, +1, +6, +0, +3, +3, +5, +7, +1, +1, +5, +0, +4, +6, +6, +1, +2, +5, +1, +7, +3, +3, +1, +5, +0, +0, +7, +4, +2, +7, +1, +4, +6, +6, +1, +0, +0, +4, +7, +7, +3, +4, +1, +3, +6, +2, +7, +1, +4, +4, +0, +3, +7, +7, +3, +3, +7, +1, +4, +6, +2, +2, +1, +0, +0, +5, +0, +6, +5, +0, +1, +6, +5, +3, +4, +5, +7, +7, +5, +6, +3, +5, +4, +7, +6, +5, +7, +2, +3, +2, +0, +3, +6, +0, +3, +1, +0, +1, +1, +4, +4, +2, +1, +7, +4, +3, +7, +7, +0, +7, +3, +4, +3, +5, +2, +0, +0, +5, +6, +6, +6, +0, +6, +6, +5, +6, +0, +1, +0, +7, +6, +6, +5, +5, +0, +3, +5, +2, +4, +0, +2, +2, +7, +7, +2, +4, +6, +7, +1, +5, +4, +3, +7, +4, +1, +3, +0, +5, +5, +0, +5, +6, +6, +5, +5, +0, +5, +2, +6, +0, +0, +5, +1, +4, +3, +5, +1, +4, +1, +4, +5, +5, +3, +0, +5, +2, +7, +3, +5, +4, +1, +0, +2, +6, +1, +1, +1, +1, +2, +0, +3, +0, +5, +6, +4, +2, +7, +6, +1, +4, +6, +1, +4, +2, +3, +1, +2, +5, +4, +2, +1, +7, +5, +6, +5, +1, +6, +4, +7, +6, +1, +5, +7, +3, +2, +2, +6, +4, +0, +1, +3, +0, +2, +4, +4, +6, +4, +7, +2, +7, +2, +2, +6, +4, +6, +7, +7, +0, +6, +7, +5, +7, +3, +4, +0, +0, +1, +1, +5, +2, +5, +2, +2, +0, +7, +0, +2, +2, +6, +5, +7, +3, +6, +2, +6, +5, +2, +4, +7, +7, +2, +1, +0, +1, +6, +3, +1, +0, +0, +6, +1, +1, +7, +7, +1, +5, +3, +7, +4, +5, +2, +1, +7, +3, +3, +0, +6, +3, +3, +2, +7, +6, +7, +2, +0, +4, +2, +3, +0, +0, +0, +4, +1, +0, +1, +0, +7, +1, +0, +5, +2, +7, +3, +4, +3, +6, +7, +4, +5, +6, +6, +3, +1, +7, +1, +2, +6, +5, +2, +0, +3, +4, +1, +0, +0, +4, +5, +7, +0, +6, +2, +2, +4, +4, +2, +1, +7, +5, +1, +5, +2, +6, +3, +5, +1, +2, +2, +4, +7, +4, +1, +5, +1, +5, +3, +4, +4, +5, +5, +7, +4, +3, +7, +3, +2, +2, +2, +1, +1, +0, +0, +1, +5, +1, +6, +0, +2, +0, +6, +4, +4, +1, +1, +5, +2, +1, +4, +5, +5, +2, +3, +1, +7, +2, +0, +5, +0, +7, +4, +2, +0, +3, +5, +4, +7, +4, +5, +5, +0, +0, +0, +2, +3, +5, +3, +7, +2, +4, +6, +7, +2, +1, +6, +3, +1, +1, +0, +7, +4, +4, +4, +4, +7, +2, +1, +3, +5, +1, +5, +2, +4, +2, +4, +1, +1, +2, +0, +0, +7, +5, +4, +2, +2, +1, +6, +6, +3, +5, +7, +7, +6, +1, +7, +3, +5, +6, +5, +4, +2, +0, +3, +3, +4, +3, +7, +3, +6, +2, +0, +0, +2, +3, +2, +6, +0, +4, +2, +4, +2, +1, +7, +6, +3, +5, +4, +0, +0, +1, +2, +7, +3, +0, +5, +1, +1, +3, +6, +2, +2, +6, +5, +7, +3, +7, +1, +6, +1, +2, +5, +7, +3, +6, +0, +0, +4, +1, +1, +6, +1, +0, +2, +3, +3, +3, +5, +1, +1, +7, +7, +5, +1, +2, +0, +2, +2, +1, +0, +2, +2, +6, +2, +0, +7, +7, +0, +6, +0, +3, +3, +6, +4, +4, +0, +5, +0, +7, +0, +7, +2, +0, +1, +5, +4, +0, +2, +0, +7, +0, +0, +5, +5, +5 diff --git a/gr-atsc/src/lib/qa_atsci_viterbi_decoder.cc b/gr-atsc/src/lib/qa_atsci_viterbi_decoder.cc new file mode 100644 index 00000000..5cc32978 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_viterbi_decoder.cc @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static const int NCODERS = atsci_viterbi_decoder::NCODERS; + +#if 0 +static void +map_to_soft_symbols (atsc_soft_data_segment &out, + const atsc_data_segment &in) +{ + for (unsigned int i = 0; i < NELEM (in.data); i++){ + out.data[i] = in.data[i] * 2 - 7; + } +} +#endif + +static void +pad_decoder_input (atsc_soft_data_segment out[NCODERS]) +{ + memset (out, 0, sizeof (out)); + + // add data segment sync + for (int i = 0; i < NCODERS; i++){ + out[i].data[0] = 5; + out[i].data[1] = -5; + out[i].data[2] = -5; + out[i].data[3] = 5; + out[i].pli.set_regular_seg (false, i); + } +} + +void +qa_atsci_viterbi_decoder::t0 () +{ +#if 0 + atsci_trellis_encoder enc; + atsc_mpeg_packet_rs_encoded encoder_in[NCODERS]; + atsc_data_segment encoder_out[NCODERS]; + atsc_soft_data_segment decoder_in[NCODERS]; + atsc_soft_data_segment decoder_in_pad[NCODERS]; + atsc_mpeg_packet_rs_encoded decoder_out[NCODERS]; + atsc_mpeg_packet_rs_encoded decoder_out_pad[NCODERS]; + + + memset (encoder_in, 0, sizeof (encoder_in)); + memset (encoder_out, 0, sizeof (encoder_out)); + memset (decoder_out_pad, 0, sizeof (decoder_out_pad)); + + srandom (1); + + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (encoder_in[i].data); j++){ + int t = (random () >> 8) & 0xff; // 8 random bits + encoder_in[i].data[j] = t; + } + } + + fflush (stdout); + printf ("@@@ ENCODER INPUT @@@\n"); + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (encoder_in[i].data); j++){ + printf ("%d\n", encoder_in[i].data[j]); + } + } + + enc.reset (); + enc.encode (encoder_out, encoder_in); + + printf ("@@@ ENCODER OUTPUT @@@\n"); + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (encoder_out[i].data); j++){ + printf ("%d\n", encoder_out[i].data[j]); + } + } + + for (int i = 0; i < NCODERS; i++) + map_to_soft_symbols (decoder_in[i], encoder_out[i]); + + viterbi.reset (); + + // this has only the previous (non-existant) output + viterbi.decode (decoder_out_pad, decoder_in); + + // now we'll see the real output + pad_decoder_input (decoder_in_pad); + viterbi.decode (decoder_out, decoder_in_pad); + + printf ("@@@ DECODER OUTPUT @@@\n"); + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (decoder_out[i].data); j++){ + printf ("%d\n", decoder_out[i].data[j]); + } + } + fflush (stdout); +#endif +} + +void +qa_atsci_viterbi_decoder::t1 () +{ + atsc_soft_data_segment decoder_in[NCODERS]; + atsc_soft_data_segment decoder_in_pad[NCODERS]; + atsc_mpeg_packet_rs_encoded decoder_out[NCODERS]; + atsc_mpeg_packet_rs_encoded decoder_out_pad[NCODERS]; + atsc_mpeg_packet_rs_encoded expected_out[NCODERS]; + static const float raw_input[NCODERS * NELEM (decoder_in[0].data)] = { +#include "qa_atsci_viterbi_decoder_t1_input.dat" + }; + static const unsigned char raw_output[NCODERS * NELEM (expected_out[0].data)] = { +#include "qa_atsci_viterbi_decoder_t1_output.dat" + }; + + + // load up input + const float *ri = &raw_input[0]; + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (decoder_in[i].data); j++){ + decoder_in[i].data[j] = *ri++; + } + decoder_in[i].pli.set_regular_seg (false, i); + } + + // load up expected output + const unsigned char *ro = &raw_output[0]; + for (int i = 0; i < NCODERS; i++){ + for (unsigned int j = 0; j < NELEM (expected_out[i].data); j++){ + expected_out[i].data[j] = *ro++; + } + expected_out[i].pli.set_regular_seg (false, i); + } + + viterbi.reset (); + + // this has only the previous (non-existant) output + viterbi.decode (decoder_out_pad, decoder_in); + + // now we'll see the real output + pad_decoder_input (decoder_in_pad); + viterbi.decode (decoder_out, decoder_in_pad); + + for (int i = 0; i < NCODERS; i++){ // check the result + CPPUNIT_ASSERT (expected_out[i] == decoder_out[i]); + } +} diff --git a/gr-atsc/src/lib/qa_atsci_viterbi_decoder.h b/gr-atsc/src/lib/qa_atsci_viterbi_decoder.h new file mode 100644 index 00000000..78b57de9 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_viterbi_decoder.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ATSC_VITERBI_DECODER_H_ +#define _QA_ATSC_VITERBI_DECODER_H_ + +#include +#include + +#include +#include + +class qa_atsci_viterbi_decoder : public CppUnit::TestCase { + + public: + + void setUp (void) + { + viterbi.reset (); + } + + CPPUNIT_TEST_SUITE (qa_atsci_viterbi_decoder); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + atsci_viterbi_decoder viterbi; + + void t0 (); + void t1 (); +}; + + +#endif /* _QA_ATSC_VITERBI_DECODER_H_ */ diff --git a/gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_input.dat b/gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_input.dat new file mode 100644 index 00000000..b2f356c8 --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_input.dat @@ -0,0 +1,9984 @@ + 5 + -0.863407, + -5 + 0.630254, + -5 + 0.766777, + 5 + -0.587788, + -3 + 0.197374, + -7 + -0.928392, + 1 + 0.846137, + -3 + -0.148515, + 5 + 0.20529, + -3 + 0.957658, + 1 + 0.712777, + -3 + -0.783731, + -7 + -0.649688, + -3 + 0.364183, + -3 + 0.766379, + 5 + -0.254228, + -5 + 0.265344, + 1 + -0.0926997, + 5 + -0.729882, + -5 + -0.946608, + 7 + 0.941424, + -1 + 0.00502258, + 5 + 0.353994, + -1 + -0.431315, + -3 + 0.802947, + 7 + 0.0174765, + -1 + 0.107732, + 7 + -0.426013, + -3 + 0.179269, + 1 + -0.334729, + -5 + 0.363112, + 1 + -0.793512, + -1 + -0.386831, + 7 + -0.469307, + 7 + -0.592471, + 3 + -0.0650877, + 7 + 0.465307, + -1 + 0.0575076, + 3 + 0.804467, + 7 + 0.766673, + -3 + 0.177288, + -3 + 0.254259, + -7 + 0.0933109, + 3 + -0.132741, + -7 + 0.226975, + 1 + 0.805, + 3 + 0.474327, + 3 + -0.147847, + -1 + 0.3179, + -7 + -0.141455, + 3 + 0.322113, + -3 + 0.633945, + -1 + -0.950742, + -5 + -0.39542, + 3 + -0.0594983, + -3 + -0.772717, + -5 + 0.545784, + 7 + 0.398416, + 3 + -0.673597, + 3 + -0.790352, + -7 + -0.544624, + 7 + -0.633903, + -1 + -0.908654, + -3 + -0.311397, + -5 + 0.662512, + -3 + -0.135222, + -7 + 0.366291, + 1 + -0.741085, + -7 + -0.29157, + -5 + -0.673842, + 3 + 0.776452, + -5 + -0.0937042, + 3 + 0.683802, + -5 + -0.722854, + -7 + 0.0347072, + -5 + 0.40685, + -5 + 0.31874, + 5 + -0.947299, + 3 + -0.955457, + 1 + 0.742103, + -5 + -0.535021, + -5 + -0.67394, + -5 + -0.108192, + -1 + -0.968649, + 1 + 0.445698, + 3 + -0.476884, + 7 + 0.566045, + -7 + -0.137864, + -1 + -0.190159, + -5 + -0.0220287, + 5 + 0.307356, + 5 + 0.917233, + -7 + 0.320761, + 3 + -0.789388, + -5 + 0.117822, + 5 + -0.604396, + -1 + 0.552753, + 7 + -0.446649, + 7 + -0.810118, + 7 + -0.658175, + -7 + 0.553164, + -7 + -0.344854, + -3 + 0.280593, + 7 + -0.884303, + 7 + 0.720506, + -1 + -0.987799, + 7 + 0.793155, + 1 + -0.850125, + 7 + 0.115369, + 5 + 0.544406, + 5 + -0.276058, + -1 + -0.231108, + -5 + 0.376881, + 3 + -0.559075, + 7 + -0.915446, + -1 + -0.460641, + 3 + 0.818044, + -3 + -0.991244, + 1 + 0.420497, + 1 + 0.485863, + -3 + -0.376003, + 5 + -0.350986, + 5 + 0.430744, + -3 + 0.463798, + 5 + 0.42518, + 5 + -0.290836, + -5 + -0.691567, + -7 + 0.824346, + 3 + 0.450636, + -3 + 0.043629, + 7 + 0.316293, + 5 + -0.120924, + 1 + 0.726472, + -1 + -0.543775, + 3 + 0.933344, + -3 + 0.132114, + -3 + -0.310619, + 5 + 0.911921, + -1 + -0.497207, + 3 + -0.637383, + -5 + -0.732262, + 7 + 0.107649, + 3 + 0.520015, + -1 + 0.157455, + -3 + -0.894858, + -1 + 0.0945327, + 1 + -0.691426, + 7 + 0.144207, + 3 + 0.445607, + -1 + 0.255407, + -7 + 0.306034, + -3 + -0.371352, + -1 + 0.124452, + -5 + 0.359695, + -5 + -0.888643, + 3 + 0.290357, + 3 + -0.0254667, + -3 + 0.407853, + -5 + 0.679174, + -5 + 0.0575717, + -3 + 0.137283, + 3 + 0.729587, + 7 + 0.31509, + -3 + -0.348804, + 1 + 0.57604, + -5 + 0.345748, + 7 + -0.327496, + -5 + -0.425651, + -7 + 0.140657, + -3 + 0.238764, + -7 + -0.143133, + 3 + 0.337288, + 1 + 0.959842, + 7 + -0.977864, + 3 + -0.317419, + 3 + -0.198654, + 3 + 0.955435, + 3 + -0.23876, + 1 + -0.88292, + -5 + -0.511151, + 3 + 0.779996, + 3 + -0.443377, + -1 + -0.192438, + -5 + 0.811447, + -7 + 0.634155, + 1 + -0.762404, + 3 + 0.731365, + 5 + 0.783236, + 5 + -0.307317, + 7 + 0.482175, + 7 + -0.539608, + 7 + -0.775192, + 1 + -0.560785, + -7 + 0.206625, + -5 + -0.038118, + -5 + -0.228189, + 1 + 0.462362, + -5 + 0.72833, + -1 + 0.622996, + -3 + 0.998274, + 5 + 0.142163, + -7 + 0.618011, + 3 + 0.122273, + -7 + -0.483532, + -1 + -0.854097, + -5 + 0.108088, + 7 + -0.193228, + 3 + 0.648767, + -3 + -0.656924, + -7 + -0.991222, + -3 + -0.25652, + 3 + -0.269033, + -1 + 0.324665, + -1 + 0.107827, + -5 + -0.0475933, + -5 + -0.99274, + -5 + -0.30318, + -3 + -0.747831, + -3 + -0.203781, + 3 + -0.010757, + 7 + 0.0734757, + 7 + -0.761203, + -7 + 0.389509, + 1 + -0.25976, + -1 + 0.965806, + 7 + 0.526324, + -1 + -0.298331, + -3 + 0.410725, + -1 + 0.00752225, + 5 + -0.455632, + 1 + -0.884761, + 7 + 0.602377, + 7 + 0.555917, + 3 + -0.160695, + -7 + -0.567533, + 3 + 0.758232, + 1 + -0.587694, + -7 + 0.414466, + -7 + -0.652491, + 1 + 0.0124494, + -7 + 0.389889, + 7 + 0.227003, + 1 + 0.242753, + -7 + 0.913462, + -3 + 0.691642, + -5 + 0.75989, + 1 + -0.596777, + -3 + -0.752662, + 3 + -0.108642, + 7 + -0.60189, + 7 + 0.511322, + -3 + -0.24478, + 7 + -0.849058, + -1 + -0.845527, + -7 + -0.572068, + -5 + -0.661012, + 5 + -0.701889, + 7 + 0.822228, + 1 + -0.00200901, + 5 + -0.71468, + 5 + 0.691151, + 7 + 0.561903, + 3 + -0.527991, + -1 + -0.867353, + 3 + -0.728324, + 5 + -0.813234, + 1 + -0.966217, + 1 + 0.0669532, + 7 + 0.905965, + -3 + -0.937283, + -3 + 0.774056, + 3 + -0.384885, + -7 + 0.175322, + -3 + 0.309913, + -5 + 0.251167, + -1 + 0.381753, + 3 + 0.00625176, + -7 + 0.56373, + -3 + 0.63392, + 3 + 0.762169, + 7 + 0.0347039, + -3 + -0.935108, + -1 + -0.114944, + 1 + -0.424213, + 1 + 0.0317198, + -3 + 0.2139, + -5 + 0.0530905, + -7 + -0.36603, + -5 + -0.851717, + -7 + 0.414219, + -1 + -0.397429, + -3 + -0.995697, + -7 + -0.328063, + -1 + -0.604664, + 7 + -0.45941, + 3 + 0.718596, + -7 + -0.377836, + -1 + 0.915331, + 7 + -0.730175, + -1 + -0.51083, + 7 + -0.923481, + 1 + 0.102495, + -1 + 0.1293, + -3 + 0.812872, + -5 + 0.066343, + -1 + -0.578684, + 1 + 0.926482, + -7 + 0.10389, + 5 + -0.462554, + -5 + -0.108, + 5 + -0.471902, + 7 + -0.34884, + 5 + 0.719192, + -7 + -0.763765, + -3 + 0.257366, + -5 + -0.623314, + -7 + 0.0467943, + 5 + -0.646451, + 7 + 0.54531, + 3 + -0.955682, + -5 + -0.432122, + 3 + -0.886357, + 1 + 0.088559, + 5 + -0.975894, + 5 + -0.105386, + -3 + 0.0978638, + 1 + -0.199998, + 5 + 0.0380346, + 3 + 0.427315, + -3 + 0.214304, + -5 + -0.566543, + -7 + -0.380715, + -3 + -0.877135, + -5 + 0.267701, + -3 + -0.03107, + -3 + 0.595488, + -1 + 0.322574, + -5 + 0.559362, + 1 + -0.0401364, + -7 + 0.528057, + 5 + -0.319427, + -1 + 0.357237, + 7 + 0.222854, + -5 + -0.432566, + 1 + -0.998243, + 7 + 0.742835, + 3 + -0.182255, + 3 + -0.471161, + 3 + 0.606823, + -7 + 0.974148, + 5 + -0.667598, + 1 + -0.811568, + 1 + -0.936551, + 7 + -0.530943, + 5 + 0.908057, + -7 + 0.895185, + 5 + 0.711135, + 1 + -0.95896, + 1 + 0.83532, + 1 + 0.14732, + 3 + 0.90921, + -1 + -0.30945, + -1 + -0.869543, + -7 + -0.360646, + 1 + 0.357157, + -3 + -0.514692, + 5 + 0.896144, + -1 + -0.196886, + -5 + -0.319624, + -1 + -0.472977, + -1 + -0.784624, + -1 + -0.281646, + -5 + -0.559682, + 3 + 0.391078, + 7 + 0.306199, + -3 + 0.962734, + -7 + -0.11162, + -7 + 0.357581, + 3 + 0.0805047, + 3 + -0.922337, + 1 + 0.232492, + -5 + -0.574144, + -1 + 0.710829, + 7 + -0.284843, + -1 + 0.831973, + -1 + -0.336799, + -3 + -0.745866, + -5 + -0.645711, + 5 + 0.0646029, + -3 + 0.252552, + 5 + -0.48003, + -5 + 0.299438, + 7 + 0.738929, + -5 + 0.40337, + 5 + 0.605547, + -3 + -0.525722, + 1 + -0.326724, + 1 + -0.515053, + 5 + 0.261516, + -7 + 0.320474, + -1 + -0.521487, + -5 + 0.903239, + -3 + -0.403525, + 7 + 0.0639151, + 3 + 0.359482, + 3 + 0.823776, + 5 + 0.0387504, + -7 + 0.109849, + 3 + -0.097467, + -5 + -0.832645, + -5 + 0.526237, + 7 + 0.438123, + 3 + -0.519244, + 1 + -0.0476922, + 3 + 0.191197, + -7 + -0.534928, + 3 + 0.462164, + 7 + -0.895527, + -1 + 0.473474, + -7 + 0.146189, + 5 + -0.179909, + -3 + -0.285322, + 5 + 0.613479, + -1 + -0.0315166, + 7 + 0.698841, + 3 + -0.774282, + 1 + 0.818017, + 7 + -0.932623, + 3 + 0.0664446, + -7 + 0.06308, + 3 + -0.519814, + 5 + -0.576546, + 5 + -0.267179, + -3 + -0.837482, + 5 + -0.255068, + 5 + -0.0568383, + -3 + 0.888405, + -3 + -0.366288, + -5 + -0.552696, + -1 + 0.541689, + 7 + -0.0454361, + -5 + 0.608489, + 3 + -0.922755, + -5 + 0.406846, + -5 + -0.506253, + 7 + -0.688017, + -5 + 0.776949, + 1 + -0.378568, + 5 + -0.727209, + -7 + 0.613322, + 5 + 0.962756, + -7 + -0.893482, + -7 + -0.987528, + -7 + 0.456806, + 7 + 0.786419, + 1 + 0.034181, + -7 + 0.790939, + -5 + -0.0300588, + 1 + 0.1652, + -7 + -0.481907, + 3 + 0.0991387, + -7 + -0.564886, + 5 + 0.85039, + -1 + 0.812973, + -1 + -0.407522, + 7 + -0.952524, + 5 + 0.765642, + -5 + -0.337741, + 7 + 0.957819, + 3 + -0.899041, + -1 + -0.671052, + -3 + 0.983954, + 1 + -0.89124, + -3 + 0.0940522, + -1 + 0.611417, + 7 + -0.937967, + -1 + 0.941416, + -1 + -0.359601, + 5 + 0.747211, + -7 + -0.111301, + 3 + -0.640113, + 7 + 0.0550081, + 7 + -0.189345, + 3 + 0.214366, + -5 + 0.135666, + -5 + 0.226602, + 3 + -0.410662, + 5 + -0.843728, + -3 + -0.371912, + -7 + -0.989917, + -1 + 0.690856, + -1 + 0.0420038, + 7 + 0.00959448, + 5 + -0.815518, + 1 + 0.430825, + -7 + 0.609881, + 5 + -0.688188, + 5 + -0.60674, + -1 + 0.0334734, + 1 + 0.722216, + -3 + 0.285942, + 7 + 0.519757, + 3 + -0.27104, + -1 + 0.509289, + -3 + -0.81976, + 5 + 0.481086, + 3 + -0.974128, + 7 + -0.337838, + 5 + 0.962801, + -3 + -0.798452, + -3 + 0.457351, + 1 + 0.103281, + -1 + -0.0256317, + 7 + 0.802218, + 7 + 0.689228, + -7 + -0.276751, + 5 + 0.404102, + -1 + -0.860859, + -7 + -0.0371287, + -1 + 0.370437, + -5 + -0.616334, + -5 + -0.758392, + 1 + -0.454585, + 1 + -0.137519, + 7 + -0.261276, + 5 + 0.558348, + 1 + -0.948463, + -5 + 0.523879, + -5 + 0.555652, + -1 + 0.840325, + 7 + 0.279812, + 5 + 0.617966, + 1 + 0.192231, + 5 + 0.132018, + -7 + -0.11959, + 1 + -0.894721, + -7 + -0.504819, + 5 + -0.419666, + 7 + -0.391328, + -3 + -0.24103, + -7 + -0.852627, + -7 + 0.990221, + 7 + 0.822151, + -7 + 0.170617, + 3 + 0.614475, + -7 + 0.446277, + -7 + -0.371819, + 1 + 0.831829, + -5 + 0.0787276, + -1 + -0.684313, + 3 + -0.611736, + 5 + 0.472613, + 7 + 0.730033, + -5 + -0.811217, + 1 + -0.760817, + -3 + 0.268843, + 5 + 0.584456, + 1 + 0.823053, + -7 + 0.80804, + -7 + 0.457053, + 5 + -0.577104, + -5 + -0.224893, + -5 + -0.107738, + -1 + -0.51484, + 3 + -0.198893, + -7 + 0.278753, + 7 + 0.502244, + -1 + 0.0510433, + 1 + -0.402208, + -7 + 0.343478, + 1 + -0.901047, + 1 + 0.369701, + -3 + -0.944263, + -5 + 0.386476, + 3 + -0.954781, + 7 + -0.688498, + 7 + -0.365083, + 3 + -0.776885, + -1 + -0.598649, + 3 + -0.87102, + 1 + 0.975515, + -3 + -0.467838, + 1 + 0.466075, + -7 + 0.271324, + -1 + 0.978247, + 7 + 0.112029, + -1 + 0.601593, + -3 + -0.412666, + 1 + -0.601096, + 5 + -0.0684049, + -7 + 0.552019, + -5 + 0.313324, + 5 + -0.836011, + -1 + 0.528016, + -3 + 0.284965, + -3 + 0.700575, + -5 + 0.0874079, + -7 + -0.0126598, + -7 + -0.276119, + 5 + -0.218603, + -5 + -0.0014039, + -3 + 0.189325, + 7 + 0.429569, + -5 + 0.837003, + 3 + 0.703335, + 7 + -0.216503, + 7 + 0.0920741, + 7 + 0.750109, + -1 + -0.322132, + 7 + -0.128556, + -1 + 0.00373274, + -1 + -0.17115, + 1 + 0.264227, + 3 + 0.988822, + -1 + 0.0243255, + -5 + 0.605084, + -7 + 0.295968, + 5 + 0.873413, + -1 + 0.434273, + -5 + -0.781778, + 5 + -0.0426681, + -5 + 0.167692, + -1 + -0.334183, + -1 + 0.07798, + -1 + -0.297114, + -3 + 0.816338, + 1 + -0.611242, + 3 + -0.423656, + 3 + -0.432077, + 1 + -0.145807, + 5 + 0.10632, + -5 + 0.756861, + -7 + -0.931971, + 7 + -0.397063, + 5 + 0.283628, + -7 + 0.721398, + 7 + 0.348194, + -3 + -0.33922, + 3 + 0.412108, + 7 + 0.510752, + -3 + -0.263234, + -7 + 0.485708, + 5 + 0.573377, + 3 + 0.244824, + -7 + 0.756185, + 5 + -0.981843, + -7 + 0.890249, + -5 + -0.785723, + 1 + 0.429159, + 7 + 0.891205, + 5 + -0.310018, + 5 + -0.0331806, + -7 + 0.567766, + -7 + -0.172382, + 3 + -0.0973954, + -1 + -0.726783, + -7 + 0.86626, + -3 + 0.640023, + 5 + -0.104726, + -3 + -0.213919, + -5 + -0.131563, + 3 + 0.108026, + 1 + 0.426832, + -7 + 0.631181, + -3 + -0.911012, + 5 + 0.232769, + -3 + -0.124074, + 5 + -0.263584, + -3 + 0.246066, + 7 + 0.833384, + -5 + -0.798822, + 1 + -0.281957, + 1 + -0.527281, + 3 + 0.918325, + 5 + -0.872591, + -3 + 0.987781, + 7 + -0.724259, + 7 + 0.73749, + 5 + -0.179643, + 1 + -0.480496, + -1 + -0.0747694, + 3 + -0.162109, + 1 + 0.655518, + 5 + 0.815859, + 7 + -0.422858, + -1 + 0.19599, + 3 + -0.601651, + 7 + -0.598413, + -5 + -0.951473, + 7 + 0.684015, + 7 + 0.121945, + 5 + 0.330604, + -1 + 0.800472, + -5 + -0.892743, + -5 + -0.0700532, + -1 + 0.143832, + -1 + 0.713388, + 1 + -0.253503, + 1 + -0.0462767, + 3 + 0.140933, + -5 + 0.94534, + -7 + 0.665662, + -5 + 0.207102, + 3 + -0.327194, + 5 + 0.110171, + -5 + 0.225803, + 1 + -0.900872, + -5 + 0.0169889, + 5 + 0.152721, + 7 + 0.125242, + -1 + 0.63948, + 7 + 0.0639926, + -5 + -0.869524, + 7 + -0.160608, + -1 + -0.465428, + 5 + -0.2185, + -7 + -0.465846, + -1 + 0.0973919, + 3 + 0.450568, + -5 + -0.451587, + -7 + -0.83918, + -1 + 0.709855, + 3 + -0.86862, + 5 + 0.676479, + 7 + -0.125049, + -1 + -0.191198, + 5 + -0.925049, + 1 + -0.521026, + -3 + -0.0364143, + -7 + 0.600769, + -7 + 0.164072, + -5 + 0.416589, + -7 + -0.595857, + -3 + 0.220567, + 3 + 0.0636474, + -7 + 0.644101, + 5 + -0.775524, + -3 + -0.192748, + 1 + 0.0538391, + 1 + 0.29524, + -5 + 0.882538, + -5 + -0.816844, + -5 + 0.862396, + -5 + 0.314402, + 1 + -0.392808, + -3 + 0.651255, + -1 + -0.231968, + 1 + 0.738021, + 5 + 0.84997, + -3 + 0.186296, + 1 + 0.741231, + 1 + -0.177977, + 5 + 0.522434, + -7 + 0.597047, + -3 + 0.0266608, + -5 + -0.152547, + 5 + -0.579447, + -1 + -0.357272, + -7 + -0.497293, + 5 + 0.869424, + -5 + -0.0230876, + -5 + -0.132476, + -3 + 0.936738, + 5 + 0.558816, + -3 + -0.0384813, + -1 + 0.483534, + -7 + 0.867384, + -1 + 0.42158, + 3 + 0.420513, + 7 + -0.0754159, + -5 + -0.379954, + 7 + 0.769618, + -7 + 0.340938, + -7 + -0.869991, + 3 + 0.830734, + 3 + 0.94181, + 3 + -0.130749, + 3 + 0.517635, + -3 + -0.252298, + -3 + -0.0496521, + 1 + 0.684225, + 1 + 0.172965, + 1 + 0.417296, + 7 + -0.466398, + 7 + -0.114508, + -1 + -0.109476, + -7 + 0.00148834, + 1 + 0.0949139, + 1 + 0.432791, + -1 + -0.240929, + -1 + 0.652485, + 5 + -0.217385, + 7 + -0.8724, + -1 + 0.387098, + 3 + -0.444865, + -3 + 0.184706, + 7 + -0.730551, + 7 + 0.754565, + 7 + -0.604301, + 3 + -0.119371, + -1 + -0.28214, + 5 + 0.143776, + 3 + 0.957703, + 3 + -0.104371, + -5 + -0.261664, + -1 + 0.495793, + 1 + -0.734588, + -3 + 0.628134, + -3 + 0.817538, + -7 + 0.361645, + 3 + 0.162489, + 5 + -0.536024, + 7 + -0.486136, + 5 + -0.776124, + -5 + -0.629988, + 1 + -0.0367843, + -5 + -0.493533, + -7 + -0.725222, + -5 + 0.492433, + 7 + 0.288113, + -3 + -0.784857, + -5 + 0.824698, + -1 + -0.545993, + -3 + -0.306256, + 1 + -0.877171, + -1 + 0.567034, + 3 + -0.440337, + -1 + 0.14643, + 7 + -0.755017, + -1 + -0.832763, + 5 + -0.498979, + 3 + 0.763625, + 5 + 0.566975, + -5 + 0.0534092, + -5 + -0.963171, + 5 + 0.0216508, + 7 + 0.597324, + 7 + -0.441571, + 7 + 0.0347587, + 3 + 0.983787, + 1 + 0.188113, + -1 + -0.171194, + -7 + -0.641733, + 7 + 0.36138, + -1 + -0.566453, + 1 + 0.882606, + 1 + 0.61524, + -1 + -0.773541, + 3 + 0.153026, + 5 + -0.621578, + -7 + -0.904904, + -5 + 0.0406272, + -5 + 0.415864, + 5 + -0.60085, + 1 + 0.727596, + -7 + -0.0860673, + -1 + -0.785685, + -5 + -0.889453, + 7 + -0.141489, + -5 + 0.04296, + -5 + 0.564742, + -7 + -0.12966, + -1 + 0.841196, + -5 + 0.71528, + 1 + -0.104704, + 1 + -0.263372, + -7 + 0.680698, + 3 + 0.756433, + -3 + -0.200798, + 1 + 0.027729, + -1 + -0.464512, + 7 + -0.60066, + -1 + 0.104495, + -3 + 0.713626, + -5 + -0.776119, + 3 + 0.168751, + -1 + -0.905566, + 5 + -0.955254, + -7 + -0.407108, + -3 + 0.170629, + -3 + -0.453202, + -1 + -0.907515, + 5 + -0.210368, + -3 + -0.98412, + -3 + -0.798125, + 3 + -0.414919, + -1 + -0.236897, + 3 + -0.491091, + -5 + -0.77713, + 3 + 0.230108, + 1 + -0.796737, + 5 + -0.26121, + 3 + 0.397635, + -1 + 0.85451, + -3 + -0.393889, + 5 + 0.983874, + 5 + 0.942163, + -3 + 0.74394, + 1 + 0.242709, + 3 + -0.779053, + -1 + 0.341856, + -7 + -0.116747, + -7 + -0.640877, + -1 + -0.318128, + -7 + 0.00367009, + -3 + 0.617172, + 7 + -0.204651, + -5 + 0.0780388, + 7 + 0.626396, + 1 + -0.638141, + -1 + -0.882934, + -5 + -0.704026, + -3 + 0.851265, + 7 + 0.0141939, + -7 + 0.611678, + -1 + 0.341055, + 3 + -0.405282, + -7 + 0.993071, + -5 + -0.0799289, + 1 + -0.967094, + -5 + -0.893374, + 5 + -0.606802, + -1 + -0.296088, + 3 + 0.578082, + 1 + 0.630626, + -1 + -0.256433, + -7 + 0.023755, + 5 + -0.565901, + 1 + -0.87536, + -7 + 0.591114, + 3 + -0.0151382, + 3 + -0.218575, + -1 + -0.571426, + 7 + -0.817884, + 1 + -0.105616, + -5 + 0.226052, + 1 + -0.197419, + 1 + -0.804454, + 1 + -0.957871, + -7 + 0.869702, + 7 + -0.118016, + -7 + 0.231177, + -1 + 0.143965, + -7 + -0.544014, + -7 + -0.125394, + -5 + 0.66333, + -5 + 0.0453925, + 3 + -0.445539, + -3 + -0.841133, + -1 + 0.406819, + 1 + 0.066009, + -7 + -0.141267, + 7 + 0.20172, + 1 + -0.397711, + -3 + -0.341991, + 3 + -0.66472, + -1 + 0.1133, + -1 + -0.0874664, + 1 + 0.460378, + -5 + 0.833044, + -1 + 0.694845, + -5 + -0.814154, + 5 + 0.190124, + 5 + 0.90168, + -3 + 0.150333, + 5 + -0.832164, + 5 + -0.623571, + 5 + 0.116979, + 7 + -0.623282, + -3 + 0.724953, + 3 + -0.656996, + 7 + 0.0645319, + 3 + 0.0895726, + 7 + -0.776726, + -1 + 0.318608, + 3 + 0.0496206, + -3 + 0.0368759, + -1 + 0.555521, + -5 + -0.673436, + 1 + 0.0103849, + -3 + 0.0743446, + -3 + -0.259726, + 5 + 0.0216708, + 1 + 0.769972, + -5 + -0.441797, + -3 + 0.719177, + 3 + 0.576816, + 1 + -0.95444, + 3 + 0.385715, + 7 + 0.215961, + -7 + -0.0887377, + -3 + 0.9093, + 5 + 0.231244, + -5 + 0.878044, + 1 + 0.237768, + -5 + -0.224173, + 7 + 0.115184, + 5 + -0.507669, + 3 + -0.4694, + -5 + -0.559494, + -7 + 0.256493, + -3 + 0.691867, + 7 + 0.760056, + -5 + -0.0235437, + -1 + -0.491056, + -7 + -0.632234, + -7 + 0.688073, + -3 + 0.448912, + 1 + 0.806255, + 3 + 0.174302, + -1 + 0.924295, + 1 + -0.0079971, + 7 + 0.585534, + 5 + -0.106368, + 7 + -0.647104, + -3 + -0.232442, + -1 + 0.103303, + 3 + -0.545308, + -7 + 0.171427, + 1 + -0.150061, + -5 + 0.124142, + 1 + 0.609533, + 1 + -0.51341, + 3 + 0.372706, + -5 + 0.406665, + 3 + -0.277069, + -3 + 0.316304, + -7 + -0.233404, + -7 + 0.0158354, + -3 + -0.376876, + 1 + -0.914291, + -3 + -0.819444, + -7 + 0.566109, + -5 + -0.582836, + -5 + -0.839922, + 5 + 0.186932, + -5 + -0.675285, + 5 + -0.957952, + -7 + -0.784832, + -3 + 0.403649, + 3 + 0.798144, + -3 + -0.880645, + -3 + 0.528126, + -1 + -0.657318, + 3 + 0.890482, + 5 + -0.46684, + 5 + -0.566931, + -7 + 0.81062, + -1 + -0.0238388, + -7 + -0.377402, + -3 + -0.21429, + -5 + -0.505753, + -7 + -0.951982, + -1 + -0.515628, + 3 + -0.871026, + -1 + -0.838789, + -7 + -0.725925, + 1 + 0.77047, + -3 + 0.858867, + 5 + 0.600752, + -3 + 0.0665514, + 1 + -0.317725, + 3 + -0.843704, + 5 + 0.219384, + -5 + -0.586559, + 7 + -0.240551, + -3 + -0.209033, + -7 + 0.493641, + 7 + 0.152856, + -7 + -0.597324, + -1 + -0.276392, + -1 + 0.831608, + 5 + 0.470546, + 5 + 0.330143, + -7 + 0.642262, + -7 + 0.977435, + -7 + 0.313444, + -7 + -0.10048, + 5 + 0.563594, + -1 + -0.186187, + -1 + -0.365659, + 1 + -0.837578, + -5 + 0.140403, + 7 + -0.78022, + -1 + 0.844668, + 7 + 0.375148, + 7 + -0.0498808, + 1 + 0.40211, + -1 + 0.744509, + 3 + 0.079077, + 7 + 0.296291, + 7 + -0.27219, + -7 + -0.660157, + -3 + 0.915867, + -1 + 0.102478, + 1 + -0.851214, + 7 + -0.634492, + -5 + -0.253903, + -5 + -0.598679, + -7 + -0.223802, + 3 + 0.0226067, + 1 + 0.696982, + -5 + -0.0351859, + 5 + -0.481739, + -1 + -0.00746336, + 3 + 0.416315, + 5 + 0.321218, + 3 + -0.283638, + -7 + 0.752743, + 3 + -0.774599, + -1 + 0.30598, + 5 + -0.0478183, + 7 + 0.791332, + -5 + -0.235768, + 3 + 0.292966, + -3 + 0.414722, + 3 + -0.665212, + 5 + -0.710929, + -3 + -0.588074, + -3 + 0.331691, + 7 + 0.882629, + 3 + -0.550038, + 1 + -0.957022, + -5 + 0.990136, + 5 + -0.558498, + -3 + -0.842342, + -1 + 0.000248163, + -5 + 0.131952, + 7 + -0.167911, + 1 + -0.425364, + 7 + -0.372087, + 1 + 0.526899, + -1 + -0.638801, + -5 + -0.386877, + 7 + 0.871863, + -7 + 0.459965, + 5 + -0.165079, + 5 + 0.296509, + -3 + 0.833452, + -7 + 0.744527, + -3 + 0.626609, + 1 + -0.814472, + 3 + 0.998261, + -7 + 0.270782, + 1 + -0.904688, + -5 + 0.723069, + -1 + -0.664172, + -5 + -0.019654, + -1 + 0.757106, + 7 + 0.780875, + 1 + -0.898937, + 3 + -0.485577, + -3 + -0.140519, + -3 + -0.240458, + -1 + 0.353802, + -7 + -0.918099, + 3 + -0.32276, + 3 + 0.672086, + -3 + -0.335273, + 1 + -0.999146, + -1 + -0.630338, + 7 + -0.544571, + -7 + 0.470793, + -3 + -0.581126, + -1 + 0.135819, + -1 + 0.0451301, + 5 + 0.479837, + -3 + 0.172697, + 5 + 0.796663, + -1 + -0.566894, + 1 + 0.470888, + 3 + 0.0653015, + -7 + 0.792323, + 1 + -0.867727, + -3 + 0.829587, + -3 + -0.740408, + 3 + -0.830687, + 3 + 0.957641, + -7 + -0.423364, + 3 + -0.893497, + 1 + -0.853771, + -3 + 0.92187, + 1 + -0.929865, + -3 + 0.198643, + 7 + 0.961747, + -1 + -0.431994, + 7 + 0.35683, + -1 + -0.871135, + 7 + 0.727451, + 7 + 0.458093, + -3 + 0.22682, + -3 + -0.827643, + -3 + -0.189953, + 5 + -0.688236, + -3 + -0.294562, + 5 + -0.903106, + -5 + 0.444196, + -1 + 0.2121, + -5 + -0.214493, + -5 + -0.392994, + -3 + 0.665017, + 1 + 0.269187, + 7 + -0.745741, + 1 + -0.185388, + -5 + -0.795616, + -5 + -0.989525, + -5 + -0.0291574, + 7 + 0.577641, + 3 + -0.98546, + 5 + 0.696809, + -5 + 0.649647, + 3 + -0.401609, + -7 + 0.29181, + -1 + -0.336865, + 3 + -0.279985, + -7 + 0.819639, + 1 + -0.69903, + 5 + -0.956345, + -3 + 0.917636, + 3 + -0.539845, + 3 + -0.58337, + 5 + 0.0319712, + 3 + -0.682523, + 3 + -0.160175, + 1 + -0.707552, + 3 + -0.197245, + -1 + 0.583643, + -7 + 0.128135, + 3 + 0.240791, + -7 + -0.289134, + -7 + 0.955084, + -5 + 0.495007, + -1 + 0.955188, + 3 + 0.523281, + -1 + 0.468672, + -5 + -0.467838, + -3 + 0.654833, + -5 + 0.85963, + -3 + 0.532693, + -3 + -0.11304, + 5 + 0.947132, + 5 + 0.395143, + 1 + -0.114501, + -5 + 0.275912, + -7 + -0.816982, + -3 + 0.280537, + 1 + -0.290476, + 3 + 0.753207, + 3 + -0.37078, + -5 + -0.73641, + 1 + 0.720629, + -1 + 0.61751, + 5 + -0.114619, + 3 + -0.509509, + 1 + 0.349672, + 7 + 0.426544, + -5 + -0.567438, + -7 + -0.52387, + 3 + -0.376306, + 3 + -0.49252, + 5 + 0.441628, + 3 + 0.703002, + -7 + 0.62187, + 3 + 0.754402, + -1 + -0.344451, + 5 + -0.0148834, + -7 + 0.449515, + 5 + 0.230859, + 1 + 0.724024, + 5 + 0.190704, + 1 + -0.69348, + -5 + 0.586233, + 5 + 0.0794267, + -5 + -0.631736, + 1 + 0.105417, + -5 + 0.136263, + 7 + -0.642064, + 1 + 0.0430542, + -7 + -0.41497, + 5 + 0.775936, + -1 + 0.687085, + -5 + 0.925474, + -5 + 0.0990985, + 3 + -0.277763, + -1 + 0.299999, + 3 + 0.392572, + -7 + -0.546367, + 7 + 0.403084, + 5 + -0.0418944, + -7 + 0.446579, + -7 + 0.372017, + -1 + 0.459786, + 7 + -0.0032825, + 5 + 0.189248, + 5 + -0.155126, + 3 + 0.53685, + 3 + 0.933272, + 3 + -0.384181, + 5 + 0.204225, + 1 + -0.327539, + -7 + 0.348723, + 1 + -0.685387, + -7 + -0.750799, + -1 + -0.627168, + -7 + 0.610837, + 5 + -0.957175, + -3 + 0.834856, + -1 + 0.528653, + 7 + -0.780567, + 7 + 0.0884855, + 3 + 0.648985, + -1 + 0.218943, + -7 + 0.832075, + 5 + 0.811807, + -3 + -0.685713, + -3 + -0.296578, + 3 + 0.000125931, + -5 + -0.996983, + -5 + -0.193044, + 5 + -0.0545228, + 1 + 0.893854, + 5 + 0.97836, + -3 + -0.748222, + -1 + 0.196022, + 1 + 0.163083, + -5 + -0.180233, + -1 + 0.209452, + -3 + 0.744591, + -3 + -0.1817, + 1 + -0.447565, + 5 + 0.528624, + -7 + -0.692082, + 7 + -0.428345, + -7 + 0.0934917, + 1 + 0.678237, + -7 + -0.298993, + -3 + 0.654322, + -3 + -0.942614, + 7 + 0.783697, + 3 + 0.395035, + 1 + -0.372332, + 3 + -0.859733, + 1 + 0.4468, + 5 + 0.822121, + -5 + 0.201003, + -7 + -0.74061, + 5 + -0.568736, + 3 + 0.904994, + -5 + 0.325172, + 5 + 0.292775, + 5 + 0.511914, + -7 + 0.675604, + 5 + 0.907106, + -7 + 0.676053, + -3 + -0.64883, + -1 + -0.451512, + 3 + -0.841985, + -7 + 0.0817016, + -1 + 0.111568, + -7 + -0.594469, + -3 + -0.844349, + 3 + -0.26745, + -3 + -0.559703, + 7 + 0.53067, + 3 + -0.256771, + -1 + -0.170001, + -1 + -0.775529, + -1 + -0.456536, + 3 + -0.998071, + 1 + 0.941052, + 7 + 0.130878, + 7 + 0.838738, + 1 + 0.856186, + 1 + 0.846151, + -1 + -0.737487, + 3 + -0.76553, + -3 + 0.222, + -1 + -0.387758, + 7 + -0.269319, + -3 + 0.0668951, + 3 + 0.731949, + 5 + -0.741075, + -7 + -0.219907, + 3 + 0.487581, + 1 + -0.973969, + 7 + 0.639967, + 3 + 0.809232, + 3 + -0.642748, + 5 + -0.453162, + -7 + -0.474022, + -3 + -0.631836, + -3 + 0.0981818, + 7 + 0.684498, + -1 + -0.654845, + -5 + -0.612608, + 7 + 0.610862, + -3 + -0.369351, + 3 + -0.261936, + 7 + -0.814926, + 7 + 0.390131, + -5 + 0.531136, + 3 + 0.974289, + -3 + -0.111925, + 3 + 0.376471, + -3 + -0.941562, + 7 + -0.410982, + -7 + 0.875953, + 5 + -0.448872, + -1 + -0.806028, + -1 + -0.814961, + 5 + 0.395374, + -7 + 0.814904, + 1 + 0.383855, + 1 + -0.252184, + 3 + 0.524843, + -7 + -0.233859, + -7 + 0.764495, + -7 + 0.817705, + -5 + 0.641853, + -3 + -0.758414, + -1 + -0.260464, + -7 + -0.240351, + -3 + 0.0476139, + -1 + -0.220685, + -1 + -0.993293, + 7 + 0.627481, + -3 + -0.950516, + -5 + -0.0848613, + 5 + 0.670037, + 7 + 0.825011, + -7 + 0.111405, + 7 + 0.0703245, + -3 + 0.177663, + 7 + -0.739343, + 3 + -0.673892, + 7 + -0.947279, + -5 + 0.732764, + 7 + -0.807932, + 1 + -0.494108, + 1 + 0.611574, + -1 + 0.205265, + -1 + -0.485118, + -5 + 0.0552847, + -5 + -0.176059, + 5 + 0.00244508, + 7 + -0.773636, + 5 + 0.951496, + -7 + 0.525518, + -5 + 0.968101, + -7 + 0.10137, + 5 + -0.4487, + 7 + 0.215142, + -5 + -0.162651, + 5 + -0.520808, + 1 + -0.89087, + -1 + -0.804296, + 7 + -0.341382, + -7 + 0.793131, + 5 + -0.724335, + 7 + 0.0832606, + 3 + -0.819473, + 7 + -0.613928, + -1 + -0.975915, + 7 + 0.555494, + -1 + -0.753698, + 1 + -0.570132, + -5 + -0.00221921, + 1 + 0.010534, + -5 + -0.825051, + -5 + 0.528378, + 3 + 0.559274, + -5 + 0.826081, + 7 + -0.349553, + 3 + 0.36511, + -5 + -0.881283, + 1 + 0.833997, + 1 + 0.00815386, + -3 + -0.820684, + 1 + 0.952573, + -5 + 0.378794, + -5 + 0.465909, + 1 + -0.166333, + 1 + 0.0746185, + -1 + 0.431021, + 5 + 0.266922, + -1 + 0.339902, + -1 + 0.372874, + 7 + -0.0149696, + -1 + 0.0317811, + 7 + -0.691387, + -1 + 0.929823, + 5 + -0.295751, + 7 + -0.851862, + -1 + 0.33382, + 7 + -0.589562, + -7 + -0.217095, + -7 + 0.115214, + -7 + 0.220949, + 1 + 0.800567, + 3 + -0.251049, + -5 + -0.626753, + 7 + -0.450723, + 7 + 0.22979, + -3 + -0.342451, + -3 + 0.997709, + -1 + 0.582385, + -5 + 0.191317, + 7 + -0.873862, + 5 + 0.213097, + 7 + -0.762892, + 7 + 0.954305, + 7 + 0.188828, + 7 + 0.931783, + -7 + -0.839115, + 5 + -0.738813, + 3 + 0.926841, + 5 + 0.399905, + -7 + 0.0123429, + -5 + 0.545699, + 3 + -0.661568, + 3 + -0.261673, + -5 + -0.81428, + 7 + 0.866628, + 5 + -0.048188, + -3 + 0.165017, + 7 + -0.698899, + -7 + 0.0783355, + -7 + 0.693822, + 7 + 0.726706, + -1 + 0.148921, + 7 + -0.685703, + 3 + 0.548864, + -7 + -0.878148, + 3 + 0.205964, + 5 + -0.271077, + -7 + -0.15239, + 1 + -0.949635, + -1 + 0.961041, + -7 + 0.0868696, + 3 + -0.361298, + 3 + 0.624626, + 3 + -0.0838945, + 5 + 0.132301, + -1 + 0.192646, + -5 + -0.579731, + -5 + -0.101051, + 5 + 0.870131, + 1 + 0.535988, + 5 + 0.255953, + 1 + 0.314134, + -7 + 0.762894, + -7 + 0.127185, + 7 + -0.222042, + -5 + -0.529038, + -3 + 0.231572, + 1 + 0.788721, + 5 + -0.891869, + -5 + -0.472732, + 3 + -0.0128941, + 1 + -0.623197, + 7 + -0.490687, + -1 + -0.441505, + 1 + -0.0410075, + -5 + 0.847264, + -7 + -0.371955, + -1 + 0.41401, + -1 + -0.742, + 3 + 0.0546079, + 5 + -0.529726, + 7 + -0.0630406, + 1 + 0.196568, + -3 + 0.488722, + -5 + -0.357116, + 3 + -0.179397, + -3 + 0.358234, + -7 + 0.821111, + 7 + -0.634397, + 5 + -0.490498, + -5 + -0.103393, + -7 + -0.996996, + -5 + 0.358586, + -7 + 0.785637, + -5 + 0.46574, + -1 + -0.714036, + 7 + 0.73281, + -1 + -0.980125, + -5 + 0.152175, + -1 + -0.468575, + -1 + -0.154831, + 5 + -0.257122, + 3 + -0.414745, + 3 + 0.663051, + -3 + 0.787162, + -1 + 0.773088, + 5 + -0.0174988, + 7 + 0.348241, + 1 + 0.856018, + -7 + -0.177525, + 1 + 0.409387, + 3 + 0.0205055, + -3 + 0.212273, + 7 + -0.35314, + -1 + 0.253691, + -7 + 0.988757, + 1 + 0.915514, + 7 + -0.0632796, + -3 + -0.0794022, + 5 + 0.905145, + 3 + -0.678132, + 7 + 0.842035, + -1 + 0.189324, + -1 + 0.431813, + 5 + 0.855323, + 3 + -0.285528, + -3 + -0.740299, + 3 + 0.526598, + -3 + -0.807057, + -3 + -0.907001, + -1 + 0.673215, + 1 + -0.806326, + -7 + -0.0179321, + 7 + 0.0822508, + -1 + 0.850969, + 5 + 0.18839, + 3 + -0.692543, + -5 + 0.064437, + -7 + -0.112983, + -3 + -0.0709171, + -5 + 0.327346, + 1 + -0.595314, + -1 + 0.878245, + 1 + 0.291632, + -1 + -0.922109, + -3 + -0.872261, + -7 + -0.212876, + 1 + -0.348517, + 5 + -0.24286, + 3 + 0.777443, + 5 + 0.00615786, + 5 + 0.834023, + 1 + -0.590069, + -7 + 0.653321, + 1 + -0.234737, + -7 + 0.664936, + 7 + 0.411378, + -7 + -0.88205, + -1 + -0.855369, + 1 + 0.377919, + -7 + -0.456485, + -5 + -0.949986, + -5 + -0.0158651, + 3 + 0.535672, + -1 + -0.687636, + 1 + 0.736756, + 7 + -0.696999, + 1 + 0.847792, + -3 + -0.349274, + 1 + -0.544481, + 7 + 0.608189, + -7 + 0.608384, + 5 + -0.323123, + 7 + -0.947181, + 5 + 0.753829, + 5 + -0.573138, + 5 + -0.485321, + -5 + 0.480423, + -5 + -0.371829, + 5 + -0.853753, + -7 + 0.878959, + -7 + 0.0642654, + 1 + 0.680307, + 1 + 0.291632, + 7 + -0.853807, + 5 + 0.644158, + 5 + -0.355364, + 1 + 0.190966, + 3 + -0.294411, + -7 + -0.67303, + -5 + -0.965702, + -3 + 0.55212, + 1 + -0.804562, + -7 + -0.494127, + -5 + -0.983771, + 1 + -0.133138, + -1 + -0.607814, + 1 + -0.742387, + -5 + -0.411707, + -3 + -0.816862, + 7 + 0.426785, + 5 + -0.089001, + 3 + -0.966127, + 3 + -0.784032, + 5 + -0.356036, + 5 + 0.475987, + 1 + 0.970457, + -3 + 0.678356, + 1 + -0.430618, + 5 + 0.942241, + -3 + -0.913966, + 7 + -0.730373, + -3 + 0.640682, + 7 + -0.024488, + -5 + 0.462632, + -3 + -0.609614, + -1 + -0.482857, + -5 + 0.535506, + 7 + 0.821051, + -1 + 0.793945, + 3 + -0.0835013, + -5 + -0.393026, + 1 + -0.415528, + -5 + 0.182819, + 1 + -0.561988, + -5 + -0.417262, + 7 + 0.708211, + 1 + -0.207354, + -5 + -0.844518, + -7 + 0.604461, + 7 + 0.787027, + 7 + 0.763122, + 1 + 0.300372, + -3 + -0.0203687, + -7 + -0.500432, + 7 + -0.5601, + 5 + -0.682225, + -5 + -0.547398, + -3 + 0.769381, + -3 + 0.750163, + -5 + -0.820679, + 3 + 0.236003, + 1 + -0.316465, + -3 + 0.802262, + 3 + -0.399964, + 5 + -0.166494, + 1 + 0.776745, + 5 + 0.716541, + 7 + -0.251088, + -5 + -0.42548, + -3 + -0.761153, + 7 + -0.0766243, + 3 + -0.180629, + 5 + -0.166458, + -5 + -0.833394, + -7 + 0.0297446, + -7 + -0.362676, + 7 + -0.644897, + -7 + 0.283366, + 5 + -0.665628, + 3 + -0.488068, + -1 + -0.902438, + -5 + -0.355751, + 3 + -0.419479, + 7 + -0.370073, + -3 + 0.480753, + 1 + -0.420338, + -7 + -0.24157, + 7 + 0.207747, + -1 + -0.777488, + 5 + 0.341417, + -1 + -0.33618, + -5 + 0.598459, + -3 + -0.280681, + 1 + -0.0398586, + 7 + 0.717195, + 5 + 0.431427, + -5 + -0.839676, + -1 + -0.74745, + 1 + 0.73193, + -1 + 0.729311, + 5 + 0.561066, + -5 + -0.670177, + -1 + -0.254041, + 3 + 0.0451663, + -7 + -0.160697, + 7 + 0.13319, + -3 + 0.360953, + -3 + 0.264897, + 1 + -0.566809, + -5 + 0.291045, + 1 + -0.573798, + -3 + 0.854987, + -3 + -0.973763, + -7 + -0.958898, + 1 + -0.945093, + -1 + -0.72672, + 5 + 0.814473, + 7 + -0.794704, + -3 + 0.229887, + -1 + 0.801239, + -5 + 0.531782, + -1 + 0.247072, + 1 + -0.179189, + -3 + 0.401884, + 7 + 0.236019, + -1 + 0.725281, + -5 + 0.74655, + 5 + -0.427725, + -1 + 0.967868, + -7 + -0.432802, + -1 + 0.541378, + 7 + -0.555299, + -3 + 0.166895, + -7 + 0.921733, + -3 + 0.840396, + -5 + -0.602658, + -1 + -0.189227, + -5 + 0.605957, + 5 + -0.525512, + 5 + 0.433278, + -1 + 0.554043, + -1 + 0.353735, + 3 + -0.493134, + -7 + 0.86014, + -3 + 0.543759, + -1 + 0.248284, + -5 + -0.502769, + 5 + -0.984136, + 5 + 0.407552, + -1 + 0.869081, + -3 + -0.7676, + -1 + 0.940972, + 1 + -0.511719, + 7 + 0.870979, + 3 + -0.0582847, + 7 + -0.628254, + 7 + -0.780393, + 3 + -0.227097, + 1 + -0.738505, + 1 + 0.364707, + 1 + -0.522339, + -3 + -0.123359, + -5 + 0.911237, + 7 + -0.856169, + -5 + 0.878138, + 1 + -0.761068, + 3 + 0.341228, + 7 + 0.0689835, + 3 + -0.15808, + 7 + -0.138551, + 3 + 0.368672, + 5 + -0.617489, + 1 + 0.404668, + -7 + -0.699522, + 5 + -0.997434, + 5 + 0.36597, + 5 + 0.785275, + 3 + -0.231849, + 3 + -0.0999933, + 1 + -0.109, + 3 + -0.686237, + 1 + -0.902631, + -7 + 0.51259, + -5 + 0.0942837, + 1 + 0.708383, + -3 + -0.861124, + -3 + -0.179481, + -3 + 0.779682, + 1 + -0.493657, + 1 + -0.418592, + -1 + 0.856146, + 3 + -0.0875076, + 7 + -0.483033, + -1 + 0.646554, + -1 + 0.974864, + -3 + -0.841565, + -7 + 0.228352, + -1 + -0.0205758, + 7 + -0.359954, + 7 + 0.314803, + 1 + -0.357785, + 7 + 0.751935, + 1 + 0.215695, + 5 + -0.190122, + -7 + 0.428353, + -1 + -0.890184, + 7 + 0.122886, + 1 + -0.557184, + 5 + -0.556109, + 7 + 0.828952, + -5 + -0.989435, + 7 + 0.830655, + -3 + -0.217279, + -1 + -0.835888, + -1 + 0.254548, + 5 + 0.523081, + 3 + 0.584681, + 1 + -0.0839997, + 5 + -0.186458, + 1 + 0.0540011, + -1 + 0.274899, + -7 + 0.116505, + 3 + 0.723544, + 5 + 0.136319, + 7 + -0.419947, + 5 + 0.476982, + 3 + 0.243726, + 3 + 0.0739162, + -3 + -0.028526, + -1 + -0.915011, + -7 + 0.764662, + 5 + -0.449836, + -1 + 0.54113, + -5 + 0.435229, + 3 + 0.0290581, + -7 + -0.416793, + 7 + 0.733392, + 1 + -0.222058, + -1 + -0.70491, + 1 + -0.738726, + 5 + 0.467214, + -5 + -0.820001, + 5 + -0.100838, + 3 + -0.867579, + -3 + 0.682739, + 5 + -0.418042, + -1 + 0.451298, + 5 + 0.494458, + 1 + -0.849409, + 1 + -0.69703, + 1 + 0.852578, + -1 + -0.781506, + -1 + 0.477606, + 3 + -0.215093, + -1 + 0.741802, + -7 + 0.574622, + 5 + 0.855315, + 5 + 0.655386, + 1 + -0.0553299, + -1 + -0.801709, + -1 + 0.610893, + 1 + -0.996069, + -1 + -0.632696, + 7 + 0.337866, + -5 + -0.444426, + 7 + 0.557502, + 3 + 0.171951, + 7 + 0.0341445, + 3 + 0.332677, + 3 + 0.169284, + 3 + -0.273138, + -5 + 0.31627, + -1 + -0.456444, + 5 + -0.892569, + 3 + 0.936689, + 5 + -0.406369, + -5 + 0.589934, + -3 + -0.20777, + -1 + 0.757187, + -5 + 0.629676, + 5 + 0.365524, + 5 + 0.289739, + -7 + -0.182101, + -1 + 0.784527, + -3 + 0.382947, + 3 + -0.380673, + 3 + -0.748491, + 1 + 0.642036, + -1 + 0.423028, + -3 + -0.740949, + -7 + 0.0430477, + -5 + 0.916659, + 1 + -0.858744, + 1 + 0.354461, + -5 + 0.197777, + 1 + 0.132034, + 5 + -0.935967, + -7 + 0.920792, + 3 + -0.456423, + 1 + -0.288826, + 1 + -0.600615, + 7 + -0.975289, + -5 + -0.259924, + -1 + -0.640925, + -3 + 0.531508, + 1 + 0.560676, + 1 + -0.36099, + -5 + 0.122059, + -5 + -0.701523, + 3 + -0.620508, + 3 + -0.918876, + 5 + -0.716268, + 7 + -0.885677, + 7 + -0.812334, + 5 + -0.427292, + -7 + -0.543744, + 3 + -0.917745, + 1 + 0.285421, + 7 + -0.938258, + -3 + 0.845977, + 5 + -0.817096, + -3 + -0.81931, + 7 + 0.384529, + -5 + 0.923807, + -5 + -0.835286, + -3 + 0.495043, + -7 + 0.610036, + 3 + 0.691557, + 1 + 0.262664, + -7 + 0.312157, + -5 + -0.629477, + -7 + -0.396994, + 5 + -0.749666, + -3 + -0.693143, + 5 + 0.427751, + 1 + 0.18179, + -5 + 0.994096, + 5 + -0.868472, + -3 + -0.000652722, + 5 + -0.826959, + 7 + 0.810413, + -7 + 0.624387, + 3 + -0.0808038, + -3 + 0.766962, + 7 + -0.576073, + -1 + 0.549271, + -7 + -0.831344, + 7 + -0.693934, + -1 + 0.494453, + -1 + 0.201426, + 7 + 0.722833, + 5 + -0.156928, + -5 + 0.470001, + 5 + 0.928162, + 3 + 0.282769, + -1 + 0.914984, + 7 + 0.453746, + 7 + 0.641607, + -7 + -0.00260904, + -5 + -0.1964, + -3 + 0.251894, + 7 + 0.528101, + 3 + 0.110567, + 3 + 0.589285, + 3 + -0.820993, + -1 + 0.933257, + 3 + 0.400226, + 3 + 0.307276, + 5 + -0.485213, + -7 + 0.442066, + 1 + -0.967156, + 3 + 0.725474, + 1 + -0.699786, + -7 + 0.506006, + 7 + 0.513752, + -3 + -0.55039, + -5 + 0.997721, + -1 + 0.875475, + 3 + 0.935239, + -5 + 0.114364, + 1 + -0.956559, + 7 + -0.360408, + 1 + 0.198951, + -1 + -0.202082, + 5 + 0.6909, + -1 + 0.530785, + -7 + 0.117763, + 1 + -0.671653, + -1 + -0.301334, + -3 + -0.0852486, + -5 + 0.24372, + 7 + -0.937574, + -3 + 0.970979, + -5 + -0.307326, + -3 + 0.755383, + -7 + -0.0614709, + 7 + -0.354787, + 3 + -0.195025, + 7 + -0.294593, + 1 + 0.679208, + 5 + 0.876946, + 1 + 0.896838, + -1 + 0.343962, + -7 + -0.0557097, + 3 + 0.335734, + -1 + 0.00658689, + 7 + -0.707898, + -1 + 0.355665, + -1 + -0.598976, + -5 + -0.591982, + 7 + -0.485165, + 1 + -0.624015, + -3 + -0.545053, + -3 + -0.584821, + 1 + -0.748295, + -1 + 0.603633, + 5 + -0.281878, + -3 + 0.887608, + -5 + -0.701604, + 3 + 0.583568, + -7 + -0.987855, + 7 + 0.0166069, + -3 + 0.156798, + -7 + 0.693214, + 7 + 0.197865, + 7 + 0.461644, + 7 + -0.751676, + -1 + 0.989154, + -3 + -0.828416, + 5 + 0.478627, + -5 + -0.225786, + 3 + 0.146553, + 3 + 0.242108, + 1 + -0.991743, + 5 + -0.23658, + 1 + 0.712781, + -1 + -0.320432, + -1 + -0.272036, + 3 + 0.601587, + 5 + -0.176224, + 7 + -0.599448, + -5 + 0.821199, + -5 + -0.650962, + -5 + 0.54749, + -7 + 0.846249, + -5 + 0.895817, + 3 + -0.368985, + 1 + -0.479081, + -3 + 0.780251, + -3 + 0.30783, + -5 + -0.0721856, + -7 + -0.0359803, + 3 + -0.559485, + 1 + 0.296459, + 7 + 0.19517, + -5 + -0.686891, + 3 + 0.126611, + 5 + -0.0218955, + 5 + -0.0897653, + 5 + -0.476869, + 5 + -0.36738, + 1 + -0.905938, + -5 + 0.769578, + -7 + -0.911913, + -5 + 0.243897, + 3 + 0.688956, + 5 + 0.278523, + -5 + 0.119666, + 5 + -0.0967183, + -7 + -0.925501, + 1 + -0.609733, + -1 + 0.538315, + 3 + -0.49403, + -7 + 0.00403903, + -1 + 0.422778, + 1 + -0.676254, + -5 + -0.495082, + -3 + 0.887213, + -7 + -0.210539, + -5 + 0.802399, + -3 + -0.205944, + 5 + -0.684772, + -7 + 0.844196, + -5 + -0.69577, + 5 + -0.822575, + -7 + -0.158769, + 5 + 0.942987, + -7 + -0.739025, + 3 + 0.791325, + 1 + -0.931093, + -7 + -0.8201, + 3 + -0.732275, + -1 + 0.945871, + 3 + -0.891814, + -7 + 0.0258538, + 3 + 0.892123, + 1 + -0.880949, + -3 + -0.633805, + -3 + -0.709181, + -3 + -0.383623, + 3 + -0.150093, + -7 + -0.117931, + 1 + -0.307017, + 3 + 0.380702, + -5 + -0.594801, + 5 + -0.43212, + 5 + 0.920089, + 7 + -0.804395, + 1 + -0.918654, + -1 + -0.904769, + 7 + -0.78175, + 7 + 0.322011, + 3 + -0.294538, + -7 + 0.930585, + 1 + -0.477718, + -5 + -0.989844, + -1 + 0.902946, + -7 + -0.350604, + 7 + 0.126035, + -7 + -0.920143, + -7 + 0.851657, + 3 + -0.136341, + 3 + 0.593154, + -5 + -0.803969, + -5 + 0.503475, + 5 + 0.0188022, + 5 + 0.631931, + 7 + 0.91577, + -7 + -0.549304, + 1 + -0.723671, + -1 + -0.305956, + -5 + 0.74761, + -3 + 0.355676, + -1 + 0.855675, + 3 + 0.613764, + 7 + 0.700543, + -5 + -0.132191, + -1 + -0.0646009, + -5 + 0.590769, + -3 + -0.49326, + -1 + 0.216807, + -3 + -0.946063, + 1 + 0.186966, + -7 + 0.790963, + -1 + 0.45715, + 1 + 0.743977, + -5 + -0.136574, + -3 + -0.888679, + -5 + -0.732167, + 7 + -0.397459, + -7 + -0.0469681, + -7 + 0.615953, + -5 + 0.439568, + 3 + 0.273846, + 7 + 0.314949, + 3 + 0.911291, + -5 + -0.453662, + 3 + 0.80863, + 3 + -0.0106643, + 5 + 0.607597, + 7 + 0.356758, + 1 + -0.6931, + -5 + 0.371134, + -3 + -0.711628, + 7 + 0.944743, + -7 + 0.202408, + -1 + 0.728236, + -3 + 0.684351, + 3 + -0.40255, + 1 + -0.186503, + -1 + 0.0150248, + 3 + 0.185297, + -7 + 0.36002, + 3 + 0.750152, + 5 + -0.381467, + 7 + 0.334737, + -3 + 0.0568684, + 3 + -0.567396, + 5 + -0.995164, + 1 + 0.602424, + 7 + 0.0454783, + 3 + 0.516061, + 5 + -0.199994, + 1 + 0.737877, + 7 + 0.411311, + 5 + -0.853456, + 5 + -0.121685, + 7 + -0.507778, + -7 + 0.152738, + -7 + 0.094981, + 1 + -0.681713, + 5 + 0.442789, + 5 + 0.973592, + 1 + -0.323444, + 1 + 0.863931, + -1 + 0.396984, + 7 + 0.249854, + 1 + 0.807021, + 7 + 0.644638, + -7 + -0.422386, + 1 + 0.0698824, + -1 + 0.24009, + -3 + -0.406826, + 3 + -0.997362, + -7 + -0.410919, + 3 + 0.0102449, + 5 + -0.495212, + 3 + 0.260833, + -7 + -0.397034, + 1 + -0.379961, + 3 + 0.483326, + 7 + -0.909255, + -7 + 0.950334, + -1 + -0.970264, + -1 + 0.276129, + -7 + -0.0553154, + -7 + 0.322334, + -3 + -0.902084, + 7 + 0.29514, + -5 + 0.864139, + 3 + 0.925323, + -3 + 0.338491, + 3 + -0.0651398, + 3 + 0.912289, + -3 + 0.52022, + -3 + -0.709139, + 3 + -0.742856, + 7 + 0.565104, + 5 + 0.894589, + 5 + -0.556394, + -1 + -0.864631, + -5 + 0.794986, + -7 + -0.869075, + 7 + 0.774674, + 3 + 0.428512, + -5 + 0.839244, + -1 + 0.357717, + -7 + 0.199788, + -1 + -0.458671, + 7 + 0.526558, + -1 + -0.318607, + -5 + 0.630471, + -3 + -0.441537, + -1 + -0.580994, + -1 + 0.690485, + 3 + -0.547178, + 7 + 0.0732123, + 7 + -0.552486, + 3 + -0.133145, + 5 + -0.933638, + 1 + 0.255392, + -3 + -0.280157, + -5 + -0.150034, + 5 + -0.122912, + 5 + 0.941452, + -3 + 0.188547, + 3 + -0.211247, + 7 + 0.946076, + -3 + 0.92071, + 1 + 0.972226, + -5 + 0.852144, + 3 + 0.377145, + -1 + 0.413943, + -7 + 0.439598, + -5 + -0.13615, + 5 + 0.171454, + -5 + 0.845844, + -7 + 0.783942, + 3 + -0.618869, + -7 + 0.760145, + 5 + -0.0578561, + -1 + -0.582842, + 3 + -0.155049, + 5 + -0.220217, + 7 + -0.73738, + 1 + -0.767926, + -1 + -0.1484, + 7 + 0.834785, + 1 + 0.101825, + -7 + -0.449194, + 3 + 0.11657, + -1 + 0.904672, + -5 + 0.054498, + 3 + 0.924094, + -5 + -0.0965653, + 1 + -0.613703, + -7 + 0.4126, + -3 + 0.584113, + -7 + 0.159096, + -5 + -0.485646, + 3 + -0.0365765, + -3 + -0.417187, + 7 + 0.916336, + -1 + 0.725319, + 1 + 0.494014, + -5 + -0.532621, + -1 + 0.646111, + -7 + -0.417253, + -1 + -0.0992868, + -1 + 0.654899, + 3 + -0.444689, + 3 + 0.800794, + 1 + -0.112122, + -1 + -0.712385, + -3 + 0.166391, + 5 + 0.314575, + -5 + 0.950806, + 3 + -0.44719, + 1 + -0.175398, + 5 + -0.225897, + 3 + 0.258122, + -1 + -0.571683, + -3 + 0.745108, + 7 + -0.489975, + 3 + 0.869279, + 3 + -0.536627, + 5 + -0.828879, + -7 + -0.62512, + -7 + -0.456803, + 7 + 0.142581, + 7 + -0.220935, + 7 + 0.012534, + -5 + -0.681989, + -7 + 0.622798, + 1 + -0.557702, + -3 + 0.482869, + 5 + 0.197984, + 3 + 0.934018, + 7 + -0.094445, + -7 + 0.325073, + 7 + 0.917923, + -7 + 0.17338, + -5 + -0.354761, + -5 + 0.71292, + -1 + -0.877613, + 7 + -0.857628, + -7 + 0.5547, + 5 + 0.819892, + 5 + 0.550559, + 3 + -0.0277248, + 3 + 0.0711193, + -3 + -0.0491096, + -5 + -0.860672, + 3 + -0.0807872, + -5 + 0.651853, + 7 + 0.104082, + -7 + 0.236164, + -1 + -0.330286, + -7 + -0.480073, + 3 + 0.406925, + -5 + -0.518305, + -1 + -0.605615, + -1 + 0.381587, + -1 + -0.11044, + 3 + -0.160278, + 1 + -0.304637, + -1 + -0.527384, + -7 + 0.882399, + 3 + -0.777911, + -7 + -0.0419154, + 1 + -0.719173, + -7 + 0.936713, + -3 + -0.751213, + -3 + 0.441754, + 1 + -0.0637285, + -1 + 0.375699, + 7 + -0.153902, + 7 + -0.792171, + 5 + 0.655847, + 7 + 0.882999, + 5 + 0.0812634, + 3 + 0.546496, + -7 + -0.223494, + -1 + -0.356427, + 1 + 0.310918, + -7 + 0.571231, + -1 + 0.798337, + -3 + 0.598408, + -3 + 0.72025, + 3 + 0.51356, + -3 + -0.167374, + 3 + 0.240713, + 5 + 0.933577, + 5 + 0.267443, + -7 + 0.853163, + 7 + 0.751923, + 1 + -0.76546, + 1 + -0.464537, + -5 + -0.307334, + 1 + 0.78241, + -3 + -0.998566, + -1 + 0.35207, + -5 + 0.427847, + -5 + 0.110459, + 3 + 0.834955, + -7 + 0.254993, + 5 + 0.368997, + 1 + 0.697111, + 5 + 0.458215, + 5 + 0.0957664, + 7 + -0.97862, + -7 + -0.615026, + 3 + 0.859467, + 5 + -0.306685, + 1 + 0.305295, + -5 + 0.093081, + -3 + 0.673005, + 1 + 0.985715, + -5 + -0.944994, + -5 + 0.817741, + 7 + -0.898887, + 7 + -0.742699, + -7 + 0.298725, + 5 + -0.180113, + -7 + 0.18706, + 1 + 0.185461, + -1 + -0.522394, + -1 + -0.117225, + -7 + -0.143794, + -3 + -0.273471, + 1 + 0.139797, + 5 + -0.265773, + 3 + 0.427259, + 3 + -0.869272, + -5 + -0.144366, + -1 + 0.337665, + -1 + 0.171026, + 5 + -0.79788, + -5 + 0.192947, + -5 + -0.311556, + 5 + 0.785642, + -1 + -0.505434, + -1 + 0.233518, + 1 + 0.420173, + -1 + 0.163412, + 7 + 0.605216, + 1 + -0.593143, + -1 + -0.957213, + -1 + -0.515973, + 1 + 0.525257, + -5 + 0.446536, + 1 + 0.486375, + -3 + -0.5737, + 3 + -0.217493, + -1 + 0.517623, + -7 + 0.920525, + 5 + 0.365421, + 5 + 0.00848039, + -5 + 0.153402, + 1 + 0.13929, + 5 + 0.977456, + -7 + 0.22807, + -1 + -0.119464, + -1 + -0.351284, + -1 + -0.991155, + 7 + 0.889795, + -3 + 0.691846, + 1 + -0.746596, + -3 + 0.586713, + 5 + 0.596188, + -7 + -0.477961, + 3 + -0.620132, + 5 + -0.0775085, + 1 + -0.165338, + 5 + -0.211165, + 7 + -0.0470844, + 7 + -0.748061, + -3 + -0.810057, + 5 + -0.196284, + -7 + 0.0831261, + 7 + 0.823358, + 3 + -0.628647, + 7 + 0.576381, + -3 + -0.347779, + 7 + 0.223497, + -7 + -0.526754, + -7 + 0.806814, + -7 + -0.725776, + 5 + -0.793048, + -3 + -0.678268, + 7 + -0.718848, + 1 + 0.914832, + -5 + 0.808905, + 5 + 0.664148, + 3 + -0.151127, + -3 + -0.289634, + 7 + 0.276275, + 5 + 0.0411116, + -3 + 0.180697, + 7 + -0.957571, + 5 + -0.931349, + 3 + 0.346197, + 3 + 0.855933, + 1 + -0.9529, + -1 + -0.687524, + 1 + 0.393423, + 7 + 0.946512, + -5 + 0.361563, + 1 + 0.197133, + -5 + 0.313557, + 3 + -0.932788, + 3 + -0.342819, + 3 + 0.07439, + -7 + 0.703045, + -5 + -0.37896, + 1 + -0.175719, + 5 + 0.223835, + 5 + -0.516742, + -7 + 0.791386, + -3 + 0.594912, + 3 + 0.917958, + -3 + -0.550284, + 5 + 0.161439, + -1 + 0.308031, + -3 + 0.129603, + -5 + -0.755601, + -5 + -0.0725142, + -3 + 0.900576, + 5 + -0.0439364, + 3 + -0.571107, + -5 + -0.696274, + -7 + -0.101347, + 1 + 0.364593, + -7 + -0.428825, + -7 + 0.723648, + -7 + -0.196055, + 5 + -0.466505, + -3 + 0.906948, + 7 + 0.869376, + -1 + 0.965839, + 3 + -0.279962, + 1 + 0.734883, + 5 + 0.829225, + -3 + 0.931521, + 3 + 0.362365, + -7 + 0.797885, + -7 + 0.497423, + 3 + 0.776487, + 7 + 0.636682, + 1 + 0.285877, + 5 + 0.662518, + 3 + -0.273415, + -3 + -0.609258, + 7 + -0.621225, + 5 + 0.795938, + -1 + 0.330694, + -3 + 0.690014, + 1 + -0.493836, + -7 + 0.308625, + -3 + -0.948984, + -1 + -0.553156, + 1 + -0.561592, + 5 + 0.835248, + 7 + -0.722998, + -3 + -0.147382, + 3 + -0.986829, + 3 + -0.428939, + 7 + -0.486681, + -3 + -0.512164, + -7 + -0.849359, + 1 + 0.169338, + -3 + 0.794093, + 5 + -0.54137, + 5 + -0.526859, + -1 + 0.452928, + 1 + -0.42493, + -1 + 0.121008, + 3 + 0.227603, + -3 + -0.933629, + -7 + -0.176661, + 7 + -0.444884, + 5 + 0.0810715, + 5 + -0.139102, + 7 + -0.726052, + -3 + 0.342913, + 3 + -0.586903, + 7 + 0.619812, + 7 + 0.513767, + 3 + 0.179749, + -5 + 0.28388, + 5 + 0.494988, + 7 + -0.697871, + -1 + 0.320561, + 3 + 0.336703, + -5 + 0.277044, + -5 + 0.637778, + 3 + -0.778878, + -7 + 0.563479, + 5 + 0.933587, + -1 + -0.0155785, + 7 + 0.967945, + 7 + -0.441443, + -1 + 0.476776, + -1 + 0.784109, + 1 + 0.282272, + -3 + 0.120237, + 5 + 0.909491, + 7 + 0.0166548, + 1 + 0.0874624, + 7 + -0.943263, + -7 + 0.404136, + -3 + -0.425458, + 5 + -0.279096, + -7 + 0.297659, + -5 + -0.909941, + -3 + 0.417617, + 3 + 0.541595, + 5 + 0.553146, + -7 + -0.758788, + -3 + 0.810651, + 3 + 0.824127, + 3 + -0.860216, + 1 + -0.301784, + -7 + 0.774392, + -3 + -0.409294, + -1 + -0.233762, + 7 + -0.169785, + -3 + 0.0785076, + 5 + 0.612462, + 3 + -0.436439, + -7 + 0.879343, + 1 + 0.639467, + 1 + 0.052389, + -5 + -0.0166562, + -3 + 0.341038, + 5 + -0.828713, + 3 + 0.794875, + -1 + 0.45125, + -3 + 0.681263, + -5 + 0.420113, + -7 + -0.367513, + -7 + 0.706676, + -3 + -0.494458, + -3 + -0.834332, + -5 + -0.683485, + -1 + -0.0354494, + -5 + -0.604827, + 3 + 0.413222, + -3 + 0.275839, + 1 + 0.456946, + -7 + -0.171177, + -7 + -0.518215, + -7 + 0.0480101, + 3 + -0.543404, + 3 + 0.634555, + 7 + 0.509344, + 5 + 0.032606, + -7 + 0.847702, + -7 + -0.382019, + 1 + -0.893403, + -3 + 0.0839257, + -5 + -0.605519, + 5 + -0.398689, + -1 + 0.777001, + 1 + 0.557634, + 5 + -0.203117, + -7 + 0.388056, + -1 + -0.841352, + 5 + 0.571447, + -1 + 0.540101, + 7 + 0.707744, + 3 + 0.0310338, + -1 + -0.222217, + -3 + 0.878539, + 7 + 0.0656955, + -1 + 0.579365, + -7 + 0.77745, + 5 + -0.330132, + -1 + -0.181327, + 5 + -0.936911, + 7 + -0.28417, + -1 + 0.184943, + 3 + 0.470113, + -3 + -0.668268, + 3 + 0.443922, + -7 + -0.254059, + -5 + -0.998164, + -7 + -0.293805, + -7 + 0.0910158, + 7 + 0.692813, + -1 + -0.0799075, + -7 + 0.721993, + -1 + 0.385094, + 5 + -0.00619203, + 7 + 0.552784, + 1 + -0.596967, + -5 + -0.00704482, + 1 + -0.110811, + 3 + 0.121887, + 3 + 0.674047, + -3 + 0.170743, + 3 + 0.760664, + -3 + 0.42977, + 1 + 0.315997, + 5 + 0.154003, + -3 + 0.369766, + -3 + 0.646692, + -3 + -0.0673465, + 3 + -0.0560396, + -7 + 0.138723, + 7 + -0.0105182, + -7 + -0.742613, + -1 + -0.0661037, + 3 + 0.00532501, + 5 + -0.755478, + -3 + 0.363332, + -7 + -0.299669, + -1 + 0.27668, + 1 + -0.117032, + -1 + -0.0241725, + 3 + 0.0823766, + -7 + -0.207114, + 5 + -0.0581861, + -5 + 0.689536, + -5 + -0.206481, + 3 + -0.457966, + 7 + -0.489086, + -5 + 0.467335, + -3 + -0.360001, + -1 + -0.138445, + -7 + -0.914763, + 7 + 0.588969, + -5 + 0.283839, + -7 + 0.959326, + -7 + -0.67792, + -7 + -0.334574, + 7 + 0.370579, + 7 + -0.171007, + 3 + -0.868796, + -3 + -0.319757, + 3 + -0.879288, + -3 + -0.435152, + 1 + -0.700487, + 5 + -0.313853, + -5 + 0.0436639, + -3 + -0.579779, + -3 + -0.778584, + -5 + -0.789192, + -7 + -0.0165036, + 5 + -0.746662, + 3 + 0.423599, + 1 + -0.896458, + 1 + 0.884175, + -7 + -0.861808, + 1 + 0.0740701, + -7 + 0.338526, + 7 + 0.292062, + 3 + 0.948647, + 3 + -0.473585, + 5 + -0.420246, + 3 + -0.949748, + -3 + -0.593698, + -1 + -0.996076, + 1 + -0.862255, + 7 + 0.137548, + -7 + -0.28388, + 5 + 0.534124, + 5 + 0.434866, + 5 + 0.139012, + 5 + -0.468484, + -7 + 0.740186, + -7 + -0.376626, + -3 + -0.183861, + -1 + 0.669948, + 5 + 0.859722, + 1 + -0.138174, + -5 + -0.573832, + 5 + -0.940617, + 7 + -0.267174, + 7 + -0.3461, + -7 + -0.741914, + -3 + -0.322358, + -5 + 0.718059, + -7 + -0.97611, + -3 + 0.154576, + -1 + -0.183644, + 1 + -0.575116, + -3 + 0.825954, + 3 + -0.751385, + 7 + -0.607166, + -5 + -0.500472, + 7 + 0.882115, + -7 + 0.0493956, + -5 + 0.362625, + -3 + 0.492293, + 5 + 0.389105, + -5 + 0.800949, + 1 + 0.94705, + -7 + -0.377441, + 7 + 0.351678, + 7 + -0.44366, + -1 + 0.320667, + -1 + 0.752543, + 1 + 0.969968, + -7 + 0.0223379, + 5 + -0.91498, + -7 + -0.172866, + -5 + -0.173087, + 5 + 0.996417, + -1 + -0.490241, + -3 + 0.91821, + 7 + -0.563976, + 5 + -0.485962, + -7 + 0.892581, + -3 + -0.460805, + 3 + 0.941525, + 1 + -0.174042, + -3 + 0.838862, + -7 + -0.156077, + -7 + 0.466488, + 1 + -0.724364, + 7 + 0.587571, + 3 + -0.274185, + 5 + -0.514854, + -3 + 0.254629, + 7 + -0.291446, + 5 + -0.0912776, + -3 + -0.54812, + 5 + -0.0964439, + -1 + -0.952324, + -3 + 0.477252, + -5 + -0.75421, + -7 + -0.536212, + 1 + 0.97589, + 1 + -0.534707, + 1 + -0.610279, + -5 + -0.380512, + 3 + -0.213305, + 7 + 0.951862, + 1 + 0.514467, + 3 + -0.52728, + 7 + -0.107415, + -1 + 0.530744, + -7 + -0.780547, + -7 + 0.601507, + -1 + -0.884028, + -5 + 0.295033, + 5 + 0.216542, + -3 + 0.803556, + -5 + 0.408551, + -1 + 0.0640241, + -7 + 0.337687, + -3 + 0.973948, + -7 + -0.112561, + 3 + 0.497891, + -1 + -0.360651, + 1 + 0.429832, + 3 + 0.599578, + -7 + 0.62018, + -5 + 0.00679079, + -7 + 0.214149, + 7 + 0.840447, + -3 + -0.167543, + 5 + 0.0564775, + -7 + 0.824302, + 3 + 0.0793194, + 3 + 0.999321, + -1 + -0.446545, + -3 + 0.703463, + 7 + 0.991686, + -1 + -0.894842, + -7 + -0.011711, + 5 + 0.280148, + -7 + 0.854388, + -7 + -0.187445, + -1 + 0.594443, + -7 + 0.933654, + 1 + 0.297684, + 7 + 0.305794, + 5 + -0.871352, + -5 + -0.415714, + -3 + -0.437484, + -5 + 0.425868, + 3 + 0.413091, + -5 + 0.413299, + 7 + -0.94675, + 1 + 0.403995, + 7 + 0.792962, + -3 + -0.663822, + -1 + 0.782255, + 5 + 0.740358, + 5 + 0.64335, + -3 + -0.677456, + -7 + 0.318753, + 3 + 0.637624, + 5 + 0.716802, + -3 + 0.506525, + -5 + -0.0154431, + 5 + -0.413524, + -3 + -0.97805, + 3 + -0.715193, + -1 + 0.855351, + -3 + -0.547344, + -1 + 0.707832, + -7 + -0.100186, + -3 + 0.1044, + -1 + 0.834975, + 5 + 0.950804, + -3 + -0.146867, + 7 + -0.922332, + -5 + 0.361724, + 1 + -0.376783, + 1 + -0.979652, + -3 + -0.860688, + 7 + -0.0470151, + 7 + -0.29374, + 1 + -0.820914, + -1 + -0.811114, + 5 + -0.585238, + 3 + 0.0997306, + -5 + -0.789875, + 5 + -0.240234, + 5 + -0.795669, + -3 + 0.834812, + -5 + -0.0813862, + 5 + -0.154017, + -5 + 0.414384, + 1 + 0.878358, + -7 + -0.0818945, + 3 + -0.239543, + -3 + -0.203324, + -3 + -0.921207, + 5 + 0.69081, + 1 + -0.727172, + 1 + 0.287061, + 3 + 0.216088, + 1 + -0.47675, + -1 + 0.679726, + -1 + 0.147156, + 3 + 0.785956, + 5 + -0.0128753, + -1 + -0.198679, + 7 + 0.16421, + -7 + -0.41241, + -7 + 0.785757, + 1 + 0.502945, + -3 + -0.611199, + 1 + 0.589565, + -1 + -0.0650551, + -5 + -0.575992, + -3 + -0.744359, + 5 + -0.856259, + -1 + 0.95337, + -7 + 0.285215, + 3 + -0.692112, + 1 + 0.427753, + 5 + -0.771773, + 1 + 0.469569, + -1 + -0.428564, + 7 + 0.465778, + 7 + -0.468184, + 7 + 0.958522, + 1 + -0.129728, + -7 + 0.48096, + 7 + -0.127209, + 7 + -0.725595, + -5 + -0.100204, + -3 + 0.231591, + 7 + 0.54961, + 5 + 0.714396, + -5 + -0.891057, + 7 + 0.0990063, + 5 + -0.0485793, + 5 + 0.350462, + -7 + 0.683771, + 1 + -0.69861, + 1 + 0.0453779, + -1 + -0.609794, + 3 + -0.30366, + -1 + -0.0804034, + -1 + -0.119469, + 3 + 0.0833771, + -1 + 0.365207, + -3 + 0.569098, + 1 + 0.122556, + -3 + 0.383273, + -3 + 0.873332, + 5 + -0.992991, + -5 + -0.888515, + 5 + 0.0792137, + 7 + -0.949043, + -5 + -0.311345, + 1 + 0.129391, + -7 + 0.514229, + -7 + -0.889496, + 1 + -0.188848, + 5 + -0.47186, + -5 + -0.0947434, + -5 + -0.860318, + -5 + 0.240262, + 5 + -0.855161, + -7 + -0.682376, + 5 + -0.268279, + -1 + 0.574063, + -1 + -0.607989, + 3 + 0.563884, + -1 + -0.28172, + 5 + 0.889506, + 3 + 0.961434, + 1 + 0.701135, + -3 + -0.36667, + -7 + -0.665516, + 5 + -0.982884, + -7 + -0.444751, + -3 + -0.0457394, + 1 + 0.686493, + 3 + -0.763344, + -3 + -0.969778, + -5 + 0.557193, + 3 + -0.70817, + -3 + -0.0794386, + 7 + -0.674222, + 1 + 0.776054, + 3 + 0.0315101, + -5 + 0.629314, + -3 + 0.0376186, + -1 + 0.363226, + 7 + -0.829763, + 7 + -0.252856, + 5 + -0.622667, + 3 + -0.409799, + 1 + 0.33154, + 5 + 0.731536, + 7 + 0.702268, + 5 + 0.926338, + 5 + 0.843521, + -3 + -0.505366, + 3 + 0.034738, + 7 + 0.935227, + 3 + -0.633068, + 5 + 0.612473, + 7 + -0.0785781, + 7 + -0.209858, + 3 + -0.519326, + -1 + -0.900059, + 5 + 0.167903, + 7 + -0.237923, + 1 + 0.568017, + -3 + 0.338209, + 1 + -0.262908, + 1 + 0.0486361, + 7 + 0.05413, + 5 + -0.900298, + -1 + 0.13673, + 5 + 0.256166, + 5 + 0.302061, + -5 + 0.399097, + 5 + -0.379186, + -5 + 0.623826, + 5 + -0.436995, + 3 + 0.15716, + -1 + -0.839201, + -5 + -0.0482146, + 5 + -0.580043, + -5 + -0.276397, + -7 + -0.224163, + -7 + 0.569099, + 1 + 0.112961, + 7 + 0.695617, + -5 + -0.985498, + -5 + 0.624633, + -5 + -0.698944, + 1 + 0.290597, + -1 + 0.492301, + 5 + -0.873225, + 5 + 0.517916, + 1 + -0.739614, + -5 + -0.118872, + -7 + 0.429263, + 5 + -0.374059, + -3 + -0.196779, + 5 + 0.845428, + 3 + -0.825515, + 1 + -0.324621, + 3 + -0.321085, + 5 + 0.659568, + -7 + 0.507627, + 3 + -0.762506, + -5 + 0.0177499, + 1 + -0.969493, + 5 + -0.989013, + 7 + 0.639013, + 5 + -0.293451, + -3 + -0.399314, + 3 + -0.164182, + -5 + -0.0115777, + -7 + 0.728109, + 1 + 0.0601385, + -3 + 0.53905, + -3 + 0.557821, + -3 + 0.267226, + 7 + 0.484006, + 3 + -0.462906, + 7 + 0.593879, + 7 + 0.70928, + 3 + 0.783019, + 7 + -0.390819, + 5 + 0.447453, + -1 + -0.327203, + -7 + -0.249398, + -5 + -0.100986, + 1 + -0.155282, + -7 + -0.798511, + -5 + -0.415777, + 1 + 0.971724, + -3 + -0.087326, + 7 + 0.946116, + -7 + -0.681513, + 1 + -0.564743, + 5 + 0.939016, + 3 + -0.437047, + -7 + -0.551414, + -3 + 0.489793, + 5 + -0.535763, + -3 + -0.98994, + 7 + 0.192269, + -5 + 0.802636, + -3 + 0.335588, + -7 + -0.346334, + 7 + 0.710128, + 7 + 0.359396, + 7 + 0.167325, + -1 + -0.359781, + 5 + -0.450043, + -3 + -0.399062, + -1 + 0.220616, + -1 + -0.713507, + 5 + -0.323577, + -3 + -0.324612, + -5 + -0.0478501, + 7 + 0.0652244, + -1 + 0.694262, + -5 + 0.234324, + -1 + 0.684074, + -3 + 0.885926, + -1 + 0.709219, + 7 + -0.403976, + -5 + 0.0613845, + -5 + 0.578585, + 5 + 0.531759, + 5 + -0.823466, + 1 + 0.885001, + -5 + 0.678863, + 1 + 0.235131, + -5 + 0.741793, + -7 + 0.831432, + -3 + 0.524304, + 3 + -0.740704, + 7 + 0.507732, + 3 + -0.0357639, + 7 + 0.863181, + -1 + 0.576264, + 3 + 0.516363, + 3 + -0.764998, + -1 + -0.362159, + -5 + 0.197446, + 3 + -0.446453, + 3 + 0.981725, + 7 + 0.0734841, + 3 + 0.256196, + -3 + -0.77722, + -5 + 0.791577, + -7 + 0.402091, + 7 + 0.553504, + 1 + -0.93853, + -7 + 0.584471, + -3 + -0.437479, + 5 + 0.997935, + -5 + 0.682598, + -7 + 0.641139, + 3 + -0.732735, + -1 + 0.930625, + -7 + -0.488808, + 7 + -0.985779, + 7 + 0.526349, + 1 + 0.412067, + 7 + 0.405549, + 3 + 0.95903, + -3 + 0.304788, + 5 + -0.344784, + 7 + -0.707093, + 7 + 0.508233, + 3 + 0.704947, + 1 + 0.790839, + -7 + -0.789173, + -3 + -0.320104, + -5 + -0.0990607, + -1 + -0.181266, + 3 + 0.413149, + 5 + -0.445842, + 7 + 0.114297, + -1 + -0.0193645, + -3 + -0.630197, + 7 + 0.549956, + 3 + 0.832843, + -1 + 0.709999, + 5 + 0.35154, + -3 + 0.488788, + -1 + -0.367693, + 7 + 0.81898, + 3 + -0.977579, + -7 + 0.677679, + 3 + 0.0798718, + -5 + -0.361776, + -7 + 0.029239, + -3 + 0.752219, + -5 + 0.36909, + -1 + -0.845805, + -5 + 0.552649, + 7 + -0.320622, + 5 + -0.0791636, + -7 + 0.155842, + -5 + -0.383591, + -7 + -0.921708, + 7 + 0.262659, + -5 + -0.311854, + -3 + 0.909658, + 5 + 0.220908, + -5 + -0.24149, + 5 + 0.424055, + -7 + -0.115968, + -1 + -0.837231, + -3 + -0.943953, + -1 + -0.501246, + 3 + -0.30943, + -7 + 0.726022, + 5 + 0.468604, + 7 + -0.536298, + -5 + 0.180367, + -5 + 0.478635, + -5 + -0.983354, + -7 + 0.948823, + 7 + -0.964671, + -7 + 0.83219, + -1 + -0.00482819, + -5 + 0.910779, + 7 + 0.0379913, + 5 + 0.958815, + -7 + 0.37621, + 5 + -0.348852, + 1 + 0.251557, + 5 + 0.421582, + 7 + 0.100173, + -3 + -0.343514, + 7 + 0.866663, + -1 + 0.442026, + 7 + 0.0442502, + 3 + -0.617214, + 1 + -0.743735, + -5 + 0.458965, + 5 + -0.572788, + 5 + 0.040819, + 3 + -0.445056, + 5 + -0.58016, + 5 + 0.386475, + -5 + 0.470098, + 5 + -0.00197146, + 7 + -0.614743, + -7 + 0.632339, + 5 + -0.445174, + -5 + -0.462788, + -5 + 0.994442, + 5 + -0.0414883, + -5 + 0.882532, + 1 + 0.694469, + -5 + -0.36298, + -7 + 0.836014, + 1 + 0.247427, + 5 + -0.623588, + -3 + 0.509161, + 3 + -0.0136789, + -5 + 0.551708, + -5 + 0.714889, + 5 + 0.948555, + 7 + -0.542934, + -3 + 0.284379, + -1 + 0.445103, + 5 + -0.302788, + -3 + 0.782427, + -1 + -0.137974, + -1 + 0.874363, + -3 + -0.450784, + 1 + -0.962429, + -5 + 0.938102, + -7 + -0.879492, + 5 + 0.666352, + -5 + 0.146655, + -3 + 0.505806, + 3 + -0.90168, + 5 + -0.00662362, + -5 + 0.401645, + -5 + 0.516729, + 7 + -0.325518, + 7 + -0.670081, + 3 + -0.898185, + 7 + 0.725776, + -1 + -0.519448, + -1 + 0.101936, + 3 + -0.800607, + 7 + -0.407942, + 7 + -0.249011, + 7 + 0.974777, + -7 + 0.984282, + -1 + 0.177661, + -3 + 0.165499, + -5 + -0.145106, + 1 + 0.092101, + -3 + -0.287475, + -1 + -0.160128, + -5 + 0.20695, + -1 + 0.278086, + 7 + 0.376328, + -7 + 0.854766, + 7 + 0.242705, + -5 + -0.623362, + 1 + -0.755314, + -3 + -0.498729, + -5 + -0.742776, + 3 + -0.17839, + -7 + -0.141452, + -7 + 0.0890251, + 3 + -0.761854, + -7 + 0.316197, + 1 + 0.531921, + -1 + 0.763375, + -7 + 0.398482, + 1 + -0.930327, + -5 + 0.559533, + 3 + -0.782727, + -1 + -0.809251, + -3 + -0.827661, + -7 + -0.790187, + 3 + 0.886559, + 3 + -0.312838, + 7 + -0.205646, + 3 + 0.538917, + -5 + -0.151619, + 7 + -0.498444, + -1 + -0.777891, + -7 + 0.709902, + 5 + -0.842215, + -3 + -0.0873613, + -3 + 0.88423, + 1 + 0.50133, + 5 + 0.87654, + -1 + 0.775389, + -1 + 0.274183, + -7 + -0.1128, + 7 + 0.129837, + 7 + -0.138116, + 7 + 0.697651, + 3 + -0.363404, + 5 + -0.51758, + 5 + 0.276224, + -5 + -0.843988, + 5 + 0.965171, + 5 + -0.433201, + 5 + 0.77057, + 5 + -0.347871, + -1 + -0.337877, + 5 + 0.0192994, + 5 + -0.00149202, + 5 + -0.705596, + -7 + 0.848062, + 3 + -0.780618, + 3 + 0.33526, + -3 + -0.0251735, + 7 + -0.148926, + -1 + -0.655041, + -3 + -0.559493, + -3 + -0.604536, + 3 + -0.0386967, + -3 + 0.830413, + 1 + -0.428, + 5 + -0.0231212, + 7 + -0.199671, + 5 + -0.396984, + -3 + 0.687779, + -7 + -0.126673, + 3 + -0.14281, + 3 + -0.663755, + -1 + 0.590741, + 7 + -0.259138, + -1 + 0.36915, + 7 + -0.193918, + -3 + 0.074994, + 3 + 0.0734893, + 3 + -0.87442, + 5 + -0.277579, + -7 + 0.874191, + 1 + 0.603273, + -1 + -0.933543, + 7 + 0.952655, + 3 + -0.0753299, + -1 + -0.0547395, + 1 + 0.298926, + 7 + 0.89666, + -1 + -0.169361, + -7 + -0.0164988, + -1 + 0.536616, + 3 + 0.123214, + -3 + -0.686119, + -3 + 0.207928, + 1 + 0.690104, + -7 + -0.840309, + -1 + 0.22515, + 5 + -0.848586, + 7 + -0.266778, + -7 + -0.573275, + -1 + 0.792824, + 7 + -0.984161, + -3 + -0.188004, + 5 + -0.461688, + -1 + -0.62303, + 3 + -0.513087, + -1 + -0.0713464, + 7 + -0.4341, + 1 + 0.791935, + -7 + -0.216476, + -5 + -0.472753, + 7 + 0.887405, + 5 + -0.629382, + -1 + 0.960013, + -7 + -0.225607, + 5 + -0.783357, + 3 + 0.238133, + 1 + -0.939504, + 7 + 0.300807, + 7 + 0.714341, + -1 + 0.0662017, + -3 + 0.709742, + -1 + 0.80212, + -5 + 0.78005, + -3 + 0.252241, + -3 + -0.848605, + -7 + -0.928371, + -1 + 0.6205, + 3 + -0.355202, + 3 + -0.884526, + 1 + 0.766157, + 1 + -0.48066, + -5 + 0.148214, + -5 + 0.416083, + 1 + 0.141582, + 3 + 0.954276, + 7 + -0.598539, + 1 + 0.302432, + -7 + -0.302829, + -5 + 0.365095, + -5 + 0.291996, + -7 + -0.853708, + 3 + -0.27352, + 3 + 0.544414, + -1 + -0.459018, + 1 + 0.184556, + 3 + -0.52332, + -1 + -0.191827, + -1 + 0.670293, + 1 + 0.519123, + 5 + 0.841211, + -1 + -0.940759, + -1 + -0.251439, + -1 + 0.695483, + -3 + 0.557767, + -3 + 0.26932, + 1 + 0.0599606, + -5 + -0.731488, + -3 + -0.559606, + -7 + -0.161615, + -7 + -0.269363, + -3 + 0.700813, + -5 + -0.598768, + -3 + 0.805228, + 5 + -0.856961, + -1 + -0.385613, + -3 + -0.323487, + -7 + 0.411967, + -5 + 0.21551, + -7 + 0.010317, + -3 + 0.573196, + 3 + -0.360943, + -1 + 0.564722, + 7 + 0.0449874, + 5 + -0.230872, + -3 + -0.394789, + -3 + 0.992717, + 5 + 0.241152, + -1 + -0.849168, + 5 + 0.828781, + 5 + -0.408953, + -1 + -0.289148, + -1 + 0.222295, + 1 + -0.537086, + 3 + 0.306834, + -1 + -0.585661, + -7 + 0.538775, + 3 + -0.204193, + 7 + -0.77022, + 1 + -0.540422, + -5 + 0.104483, + 3 + 0.0113785, + -3 + 0.358089, + 7 + 0.83108, + 7 + -0.810261, + -1 + 0.0540461, + -1 + 0.87434, + -7 + -0.379698, + 5 + -0.722662, + -7 + -0.587491, + 3 + -0.152501, + 1 + -0.137736, + -1 + 0.137048, + -7 + -0.993715, + -5 + -0.817584, + -7 + 0.192652, + -7 + 0.965716, + 3 + -0.497121, + -3 + -0.583623, + 3 + 0.724106, + 3 + 0.906286, + 3 + 0.369401, + -5 + -0.333858, + -7 + 0.201107, + 1 + -0.481391, + 3 + 0.214079, + 1 + -0.634333, + 3 + 0.32668, + -5 + 0.438198, + 3 + 0.0183425, + -7 + -0.854446, + -3 + -0.749623, + 5 + 0.260525, + -3 + -0.246166, + 7 + -0.256046, + 5 + -0.0506104, + -5 + -0.546944, + -3 + 0.70895, + 7 + 0.671615, + -7 + -0.178744, + -7 + -0.296848, + 3 + -0.786894, + 1 + 0.486466, + 5 + 0.984005, + -3 + 0.755768, + -3 + 0.60431, + -7 + -0.658241, + 7 + -0.99308, + -7 + 0.730603, + 1 + -0.147345, + 3 + -0.914348, + -5 + 0.176437, + -5 + -0.883513, + -5 + -0.746214, + 1 + 0.599807, + -1 + -0.826388, + -1 + -0.231019, + 7 + -0.427187, + 3 + 0.436418, + -5 + -0.0296006, + 3 + 0.342193, + 5 + -0.02255, + -1 + 0.332447, + 1 + 0.627013, + -7 + -0.257934, + -5 + -0.61819, + -7 + 0.660406, + 7 + -0.749068, + -1 + -0.826357, + 7 + 0.259934, + 1 + 0.624619, + -5 + -0.409846, + -7 + 0.175771, + 7 + 0.841248, + -7 + -0.182872, + 7 + 0.728087, + 3 + -0.272224, + -1 + 0.694387, + 1 + 0.87123, + -7 + -0.36121, + -3 + 0.231829, + -3 + -0.288232, + -1 + 0.860921, + 3 + -0.667815, + -1 + -0.9711, + 3 + -0.778314, + 3 + -0.298502, + 7 + 0.460686, + -7 + -0.972103, + 1 + -0.791205, + -7 + -0.527057, + 3 + 0.680872, + 1 + 0.854739, + -7 + -0.673826, + -1 + 0.137268, + -1 + 0.333986, + -1 + 0.901741, + -1 + -0.202348, + -3 + -0.774122, + 1 + 0.589625, + 3 + -0.849021, + 7 + -0.456618, + 5 + 0.567717, + 5 + -0.636284, + 1 + 0.365766, + 1 + -0.511727, + -7 + 0.166757, + 5 + 0.919885, + 1 + -0.642062, + 5 + -0.296797, + -7 + -0.385574, + 7 + 0.591877, + -7 + 0.436025, + 3 + 0.451077, + -1 + -0.716762, + -3 + 0.374155, + 5 + 0.337632, + -7 + 0.723804, + -5 + 0.383933, + -3 + -0.0862489, + 3 + 0.990362, + 5 + 0.133119, + 1 + -0.12971, + 3 + 0.044241, + 3 + -0.964742, + -5 + 0.702827, + -5 + 0.52507, + 7 + 0.813182, + 7 + 0.456129, + -7 + -0.564425, + -3 + 0.681494, + -1 + 0.503007, + 1 + 0.488921, + -5 + -0.978964, + 5 + -0.978504, + -5 + 0.458051, + -7 + 0.0654869, + 3 + -0.245564, + -1 + -0.337528, + -5 + -0.55446, + -5 + 0.273099, + -7 + 0.215733, + 1 + -0.138924, + 7 + -0.219671, + 3 + -0.887201, + -7 + -0.516248, + -5 + -0.396037, + -5 + 0.818756, + 3 + -0.712209, + 7 + -0.282743, + -3 + 0.707385, + 7 + 0.359774, + -5 + -0.845302, + 1 + -0.1686, + -7 + -0.483578, + 1 + 0.720247, + 1 + 0.626128, + 7 + -0.2298, + -7 + -0.491252, + -1 + 0.568972, + 1 + 0.348875, + 5 + -0.21767, + 5 + -0.844788, + -7 + 0.212711, + -5 + -0.728646, + 5 + -0.257998, + -3 + 0.91577, + 3 + -0.356945, + -5 + -0.727851, + 3 + -0.839908, + -5 + -0.87513, + 5 + 0.492427, + 7 + 0.859239, + 5 + 0.63738, + 7 + -0.567552, + 7 + -0.311746, + -5 + -0.293624, + -5 + -0.0892278, + -1 + 0.68692, + -3 + -0.584071, + -7 + -0.368564, + 3 + 0.685985, + 1 + -0.443952, + 5 + -0.799968, + -5 + 0.849293, + 7 + 0.419622, + 7 + -0.719699, + -5 + 0.776349, + 7 + 0.353652, + -3 + -0.957607, + 7 + -0.233657, + -3 + 0.110137, + -5 + -0.825374, + -5 + 0.936229, + 3 + 0.611605, + -5 + 0.598961, + 3 + 0.914424, + -5 + 0.185668, + 1 + -0.506371, + -1 + 0.19368, + -3 + 0.135954, + 5 + 0.0317122, + -3 + 0.926598, + 3 + 0.841409, + -7 + -0.995628, + 7 + -0.516938, + 1 + -0.327213, + -7 + -0.988622, + 7 + 0.0436381, + -1 + -0.736482, + 3 + 0.0252206, + -7 + -0.999107, + 1 + 0.287324, + 3 + -0.710148, + -3 + -0.863982, + 5 + -0.110109, + -1 + -0.382303, + 1 + -0.00955381, + 7 + 0.574434, + 3 + 0.772632, + -3 + 0.427061, + -3 + -0.47615, + 1 + 0.159639, + -1 + 0.0973485, + -7 + 0.670094, + -3 + 0.66009, + 3 + -0.966069, + 5 + 0.729848, + -1 + -0.165828, + -5 + -0.991247, + 3 + -0.796155, + -3 + -0.665567, + 1 + 0.705734, + -3 + -0.0729422, + -5 + 0.569012, + -5 + 0.532164, + -3 + 0.114169, + -3 + -0.79896, + 5 + -0.434429, + 3 + 0.0409003, + 5 + -0.656138, + 1 + 0.80331, + -1 + -0.832592, + 1 + -0.512036, + 5 + 0.821594, + -5 + 0.153262, + -7 + 0.742653, + 7 + 0.775938, + 7 + 0.794682, + -1 + 0.436735, + 1 + 0.232814, + 5 + 0.173647, + -7 + 0.0346826, + -5 + -0.764013, + -3 + 0.414464, + -7 + -0.107918, + -5 + -0.909358, + -3 + -0.855809, + 3 + 0.321112, + -7 + -0.853217, + -1 + 0.240779, + -5 + 0.308181, + -3 + -0.101137, + -3 + 0.0592809, + 1 + -0.475771, + 1 + -0.805118, + 1 + -0.497502, + 1 + 0.0533702, + 1 + 0.256822, + 1 + 0.943496, + 5 + 0.195682, + 3 + 0.84158, + -7 + 0.691885, + 7 + 0.702398, + -5 + -0.0240126, + 3 + 0.0729154, + 1 + 0.683697, + -5 + 0.261411, + 5 + 0.953329, + 5 + -0.728981, + -5 + -0.635009, + 5 + -0.630682, + -7 + 0.122834, + -3 + 0.959923, + -1 + 0.374435, + 1 + 0.720612, + 5 + 0.664998, + 1 + 0.00891615, + -7 + 0.432124, + -3 + 0.0339184, + -1 + -0.257549, + 7 + 0.584476, + -3 + 0.0935045, + -1 + -0.804627, + 1 + -0.992967, + -3 + 0.538947, + 7 + 0.180181, + -5 + -0.90103, + -3 + -0.368599, + 7 + 0.775146, + -3 + -0.990663, + 5 + -0.991429, + 3 + 0.229796, + 3 + 0.933547, + -7 + 0.629628, + 7 + -0.128119, + -3 + 0.993864, + 3 + -0.518632, + 1 + 0.431409, + 5 + 0.162359, + -1 + 0.340156, + 7 + 0.99834, + -1 + -0.37602, + 7 + 0.798388, + -5 + -0.977304, + -1 + -0.714549, + -7 + 0.371461, + -3 + 0.429763, + -5 + -0.176519, + 1 + 0.130875, + 3 + -0.192991, + -3 + 0.926126, + 3 + -0.756796, + -3 + 0.0799201, + -5 + -0.885874, + -5 + -0.922719, + -1 + 0.788957, + 1 + 0.876735, + 1 + 0.505541, + 1 + 0.0568082, + 5 + -0.546276, + -5 + 0.987925, + 1 + 0.559679, + -5 + 0.240393, + 7 + 0.460363, + 5 + 0.194578, + 3 + 0.987203, + 7 + 0.781711, + -7 + -0.0489823, + -1 + -0.776679, + -7 + -0.496617, + 5 + -0.488827, + -3 + -0.501392, + 5 + 0.703741, + 7 + -0.0924905, + 5 + -0.948555, + -3 + -0.508697, + -5 + -0.211705, + -1 + -0.0656021, + 1 + 0.526428, + 3 + 0.977313, + 7 + 0.717488, + 1 + 0.987358, + -1 + -0.492118, + -1 + 0.765235, + 1 + -0.576154, + 3 + 0.52365, + -7 + 0.253303, + 1 + -0.492177, + 5 + 0.865942, + 5 + 0.977195, + 7 + 0.161001, + 5 + -0.907593, + -7 + -0.557902, + -7 + 0.825849, + 7 + -0.120301, + -5 + 0.531996, + 1 + 0.80755, + 7 + 0.969872, + -7 + -0.738685, + -3 + 0.636749, + 1 + -0.655666, + -3 + 0.999979, + 7 + -0.843387, + -3 + 0.693217, + 7 + 0.615595, + -3 + -0.585734, + 5 + -0.349962, + -5 + -0.708827, + 5 + 0.767043, + -3 + -0.561155, + 5 + 0.0547506, + 7 + -0.00058388, + 5 + 0.683614, + -5 + 0.933133, + -7 + -0.705963, + -1 + 0.432718, + -5 + -0.745574, + -1 + 0.578781, + -3 + 0.265256, + -1 + -0.723166, + 3 + -0.609362, + -3 + 0.897704, + -1 + 0.630349, + -5 + 0.582721, + -5 + -0.0955401, + 5 + -0.235266, + -1 + 0.829279, + -5 + -0.824548, + 3 + -0.803079, + 3 + -0.505004, + -1 + -0.492252, + 1 + -0.92866, + 1 + -0.193727, + 7 + 0.855165, + -5 + -0.409258, + 3 + 0.483943, + 5 + -0.711778, + 1 + -0.291856, + -1 + -0.309453, + -1 + -0.961907, + 3 + 0.239915, + 3 + 0.333033, + -5 + -0.520074, + 7 + 0.80808, + 7 + -0.392463, + -5 + -0.268562, + 7 + 0.963694, + -5 + -0.27416, + -3 + 0.136372, + -3 + -0.533467, + 5 + 0.0336407, + 5 + 0.269954, + -1 + 0.481331, + -5 + 0.883264, + -5 + 0.917248, + -5 + 0.841082, + 7 + -0.272449, + -1 + 0.612493, + -7 + -0.0456689, + 3 + -0.468522, + -5 + -0.783857, + -5 + -0.963398, + -7 + 0.0600612, + -3 + 0.80801, + -3 + -0.969476, + -5 + 0.949233, + 7 + -0.954761, + 7 + -0.0774834, + 5 + -0.245508, + 5 + 0.345368, + 3 + -0.476338, + -5 + -0.322511, + -3 + 0.450538, + -7 + -0.678719, + -3 + -0.172123, + -5 + -0.209171, + -3 + -0.420884, + -1 + 0.00383168, + -3 + -0.312955, + -7 + -0.0884187, + -7 + 0.201349, + 5 + -0.601248, + 5 + -0.413319, + 3 + -0.246626, + 5 + 0.977104, + -5 + 0.0133906, + 7 + 0.349431, + 5 + 0.216145, + -1 + -0.529927, + 1 + -0.249291, + 1 + 0.658874, + 7 + 0.43074, + 5 + 0.124815, + 7 + -0.553229, + 1 + 0.116857, + -5 + 0.734356, + -1 + -0.647581, + 5 + -0.323226, + -5 + -0.810003, + -3 + 0.822276, + -1 + -0.591676, + -5 + -0.434047, + 1 + 0.15821, + 7 + 0.165069, + 3 + 0.253866, + 3 + 0.973848, + -7 + 0.713996, + -5 + 0.215808, + -1 + 0.0812883, + -3 + 0.846565, + -5 + -0.947667, + 3 + 0.409641, + 5 + -0.385462, + -3 + 0.787733, + 1 + 0.844418, + 1 + 0.349241, + 5 + -0.586969, + 7 + 0.257519, + 1 + -0.315586, + -1 + -0.327033, + 1 + 0.767669, + -1 + -0.292183, + 3 + 0.389264, + -7 + 0.339534, + -3 + 0.477526, + -3 + 0.11475, + -7 + -0.119439, + 3 + 0.406966, + 5 + 0.419678, + 1 + 0.76062, + -7 + 0.536916, + -7 + -0.510681, + -5 + 0.905296, + 7 + 0.13423, + -5 + 0.748596, + 3 + -0.431882, + 7 + 0.33909, + 3 + 0.341309, + 5 + -0.172616, + -7 + -0.778667, + -5 + -0.984483, + 7 + 0.04289, + -3 + 0.791158, + -1 + -0.606419, + -3 + 0.939034, + 5 + -0.688122, + 7 + -0.0797096, + -3 + -0.176378, + 3 + -0.200208, + -3 + 0.539966, + -5 + 0.55811, + -1 + -0.965644, + -7 + -0.62776, + 3 + -0.327998, + 3 + -0.518732, + 3 + 0.713363, + 5 + 0.082287, + -7 + -0.799949, + 5 + -0.144101, + -7 + -0.416404, + 3 + 0.926589, + -3 + -0.0426248, + -3 + 0.823828, + 3 + -0.899492, + -1 + 0.925421, + -5 + -0.987104, + -3 + -0.667032, + -1 + -0.376583, + -1 + 0.776434, + 5 + 0.838315, + -3 + -0.411202, + -7 + -0.918427, + -5 + 0.627889, + 7 + -0.542975, + -3 + -0.0689918, + -5 + -0.55104, + -5 + 0.829815, + 7 + 0.466128, + -7 + -0.910729, + -3 + 0.587943, + -5 + -0.989778, + 3 + 0.429693, + -5 + 0.363276, + 5 + 0.48865, + -1 + 0.462889, + -1 + 0.933537, + -1 + -0.237365, + 7 + -0.503287, + 3 + 0.898831, + 5 + -0.88925, + 1 + 0.491187, + -3 + 0.819494, + 7 + -0.841093, + 5 + -0.172405, + -3 + 0.296082, + -5 + 0.230588, + 1 + -0.135964, + -7 + -0.24852, + 7 + 0.779819, + 1 + -0.0197039, + 3 + 0.690689, + 5 + 0.201188, + -3 + 0.316178, + 3 + -0.790151, + -3 + 0.353513, + 1 + 0.482168, + -7 + 0.5088, + 5 + -0.619387, + 3 + -0.572638, + -1 + 0.737113, + -3 + -0.330907, + 3 + -0.642647, + 7 + -0.587751, + 7 + 0.705296, + -1 + 0.765705, + -7 + 0.342622, + 1 + -0.443867, + -7 + 0.64285, + 5 + 0.119933, + 1 + 0.146719, + -3 + 0.808331, + 5 + 0.362826, + -5 + 0.649288, + -5 + -0.919914, + 5 + 0.530805, + 7 + 0.836641, + -1 + -0.33567, + 7 + -0.814941, + -3 + 0.521328, + -7 + -0.0633902, + 3 + 0.637973, + 5 + -0.448024, + -7 + 0.529787, + -1 + 0.158647, + 1 + -0.343875, + 5 + 0.862299, + -7 + 0.269423, + -3 + 0.205924, + -3 + 0.543444, + -1 + -0.0442747, + -1 + -0.514346, + -7 + -0.538346, + 5 + -0.134437, + 3 + -0.242908, + -3 + 0.960616, + -3 + 0.613265, + 5 + -0.578398, + 5 + -0.196621, + -1 + 0.99966, + -7 + -0.206926, + -7 + 0.149597, + 1 + -0.618079, + 7 + -0.779085, + 5 + 0.78756, + -3 + -0.461424, + 1 + -0.8271, + 7 + -0.779893, + 1 + -0.034591, + 3 + -0.618594, + 7 + -0.508509, + 3 + 0.858569, + -3 + -0.292217, + -3 + 0.638647, + 7 + 0.429429, + -3 + 0.0850469, + 3 + 0.840684, + -5 + -0.361285, + -1 + -0.0439304, + -5 + -0.464768, + 5 + 0.814776, + -7 + 0.838205, + -1 + 0.932473, + 3 + 0.0800499, + 3 + 0.430625, + -1 + -0.379486, + -5 + 0.566269, + 1 + -0.191075, + 1 + 0.426799, + -3 + -0.865195, + -1 + -0.286844, + -5 + -0.347813, + -1 + 0.254653, + -5 + -0.0217081, + -7 + 0.712565, + -5 + 0.626585, + -3 + 0.407399, + -1 + -0.495544, + 7 + 0.988263, + 5 + 0.752268, + 7 + -0.57751, + 1 + -0.699522, + -3 + -0.559222, + -5 + -0.142211, + -5 + -0.984406, + -7 + 0.478908, + 3 + -0.492842, + -1 + -0.75382, + 1 + 0.00969996, + 1 + -0.893656, + -7 + 0.928332, + 7 + -0.310557, + 3 + -0.203997, + -3 + -0.119623, + -3 + 0.23919, + -5 + 0.89898, + 3 + -0.000236075, + -1 + -0.75715, + 5 + -0.946444, + 5 + 0.830343, + 5 + 0.170209, + -5 + 0.0682683, + 7 + 0.490712, + 3 + 0.0912319, + 7 + -0.939061, + -5 + -0.27871, + 3 + 0.292512, + 3 + 0.7815, + 3 + 0.780423, + 3 + -0.995218, + 1 + -0.971244, + 5 + 0.863878, + 3 + 0.605471, + 1 + 0.615707, + -1 + -0.430001, + 7 + 0.137532, + -7 + 0.420738, + 5 + -0.511889, + -7 + -0.894203, + -1 + -0.442678, + 7 + 0.58245, + -1 + -0.302989, + -7 + 0.046658, + -1 + 0.213312, + -3 + -0.40466, + 3 + 0.119842, + -3 + -0.209236, + 1 + 0.489636, + -1 + 0.0750853, + 1 + -0.138393, + 3 + 0.197677, + 1 + 0.801, + 5 + -0.737093, + 5 + 0.0908536, + -7 + -0.604504, + -5 + 0.56203, + -3 + 0.309546, + 1 + -0.966521, + 5 + 0.977852, + 7 + 0.73063, + -5 + -0.256762, + -3 + -0.431265, + 5 + 0.661912, + -1 + 0.865871, + -3 + 0.10026, + -3 + 0.979883, + -3 + -0.50973, + 7 + -0.387004, + -5 + 0.872216, + -1 + -0.552574, + 3 + -0.00281111, + -5 + -0.433458, + 3 + 0.228333, + -5 + -0.784953, + 5 + 0.571488, + -5 + -0.107047, + 3 + 0.598395, + 7 + -0.209076, + 7 + 0.968037, + -7 + 0.133602, + -3 + 0.197601, + -1 + -0.737348, + -7 + -0.0987225, + -1 + -0.680374, + -5 + 0.902133, + 5 + -0.065214, + 7 + 0.820436, + -1 + -0.994703, + 5 + 0.928257, + 3 + 0.387782, + -1 + -0.867014, + -1 + -0.343716, + -3 + -0.0119044, + 5 + -0.882348, + 3 + -0.349223, + -3 + -0.423901, + -1 + -0.358375, + -7 + 0.877898, + -1 + -0.0346012, + -3 + -0.731243, + 1 + -0.0103546, + -1 + -0.662776, + 1 + 0.486511, + -1 + -0.0129122, + -5 + 0.0121863, + -3 + 0.550817, + -3 + 0.0375324, + 5 + 0.371006, + 5 + -0.111812, + 5 + 0.963243, + 1 + 0.36354, + -3 + -0.0390213, + -7 + -0.512331, + -3 + 0.530897, + -1 + -0.961326, + 1 + -0.128698, + 5 + -0.0345879, + 7 + -0.724934, + -7 + -0.990395, + 7 + -0.0956077, + 5 + 0.998217, + -1 + -0.38503, + -5 + 0.431693, + 3 + -0.322315, + 1 + -0.520076, + -3 + -0.403514, + 3 + -0.638799, + -1 + -0.665616, + -7 + 0.866326, + 7 + -0.314543, + -3 + -0.752403, + 7 + 0.180847, + 7 + -0.924565, + 3 + 0.431162, + -7 + -0.844134, + 5 + -0.621084, + 1 + 0.678683, + 7 + -0.643627, + -1 + 0.464485, + 3 + 0.311484, + 1 + 0.61938, + 1 + -0.362697, + -1 + -0.545854, + -7 + -0.693428, + 3 + -0.162961, + 3 + 0.362332, + -5 + -0.0418496, + -3 + -0.790282, + 1 + -0.362329, + -5 + -0.679632, + -7 + 0.193632, + 7 + 0.169699, + 5 + -0.0276975, + 3 + 0.145423, + 7 + -0.526892, + 7 + 0.23963, + -5 + -0.0191274, + 3 + 0.267953, + 5 + -0.963432, + 7 + 0.72934, + 5 + -0.0415711, + 3 + -0.0615771, + -1 + -0.441843, + 5 + -0.196666, + -5 + 0.656983, + 5 + 0.764159, + -7 + -0.0188419, + -1 + 0.515285, + -5 + 0.77527, + -1 + -0.362528, + 1 + 0.360052, + 3 + 0.134359, + -5 + 0.37625, + 7 + -0.511201, + 7 + -0.846493, + 5 + 0.94168, + 1 + -0.100134, + 5 + -0.157002, + 3 + -0.374631, + -7 + -0.364117, + -1 + -0.142558, + -7 + 0.0265685, + -3 + 0.138828, + -5 + -0.289868, + 1 + 0.664193, + -7 + 0.887828, + 1 + -0.652588, + 3 + -0.527631, + -1 + 0.284251, + -5 + 0.278712, + 1 + -0.105013, + -1 + 0.853542, + 1 + -0.436623, + -5 + -0.867476, + 3 + 0.96232, + 7 + 0.427617, + 3 + -0.501165, + -5 + 0.411637, + 7 + 0.891616, + -7 + 0.664072, + -1 + -0.888475, + 5 + 0.548079, + 3 + 0.503912, + -5 + -0.612317, + -1 + -0.180983, + 1 + -0.239876, + 1 + 0.596635, + -3 + -0.0827705, + -7 + 0.277359, + 5 + -0.941413, + -5 + 0.697875, + 3 + 0.714356, + 1 + -0.558584, + 1 + -0.0174082, + 5 + -0.587225, + -5 + -0.512741, + 7 + -0.434388, + 7 + -0.473811, + -1 + 0.285865, + 5 + 0.988991, + -5 + -0.991867, + -3 + 0.864291, + -5 + 0.661288, + 5 + -0.460111, + 7 + 0.366331, + -7 + 0.784093, + 5 + 0.918848, + 7 + 0.965396, + -3 + -0.161624, + 7 + -0.476323, + -5 + 0.501047, + 7 + 0.964268, + 1 + -0.388995, + -1 + 0.308069, + 7 + 0.449621, + -3 + 0.517261, + -1 + -0.931887, + -3 + -0.314139, + -1 + -0.88269, + 1 + -0.641202, + -7 + 0.426506, + -7 + 0.765908, + 3 + -0.839435, + -1 + 0.85062, + -5 + -0.068266, + 7 + -0.336073, + 5 + -0.552052, + 7 + 0.968225, + 5 + -0.489061, + -1 + 0.549817, + 7 + 0.155363, + 7 + 0.287813, + 5 + -0.0712527, + 7 + -0.539294, + 3 + 0.515963, + -7 + 0.309448, + 5 + -0.400565, + -3 + 0.772515, + -3 + 0.47223, + -5 + -0.377265, + -3 + -0.277457, + 3 + -0.0481647, + 1 + 0.253072, + 7 + -0.701416, + 3 + -0.983524, + -1 + 0.859256, + 3 + 0.684439, + 7 + -0.715583, + 1 + -0.927083, + 5 + -0.820364, + 3 + -0.818987, + -1 + 0.0484889, + -5 + 0.88172, + -1 + 0.642372, + 7 + -0.486761, + 1 + -0.154892, + -3 + 0.620922, + -7 + -0.307461, + -5 + 0.958143, + -5 + -0.945751, + -7 + 0.420205, + 3 + 0.212257, + -7 + 0.343969, + -7 + -0.56883, + -7 + 0.542757, + 1 + 0.338133, + -1 + 0.205287, + 3 + -0.678275, + -3 + 0.162556, + 7 + 0.7356, + -1 + -0.366469, + -5 + 0.818684, + 1 + -0.375059, + -7 + -0.326917, + -1 + 0.21386, + -1 + 0.933421, + -5 + -0.0965871, + -1 + -0.327707, + -3 + -0.293112, + 5 + -0.399372, + -1 + -0.243464, + -1 + -0.477791, + 5 + 0.160018, + 3 + 0.0379489, + -7 + -0.468135, + -5 + -0.924231, + 7 + -0.559268, + -1 + -0.869929, + 1 + 0.644987, + 7 + -0.416144, + -3 + -0.64862, + 1 + 0.0932449, + -1 + -0.941752, + -7 + -0.448205, + 5 + 0.816932, + -1 + -0.010022, + -3 + -0.611324, + 5 + -0.688206, + 1 + 0.868089, + -3 + -0.454031, + 3 + -0.633225, + 5 + -0.11036, + 7 + 0.119173, + -7 + -0.663239, + -7 + 0.86954, + 7 + 0.335132, + -1 + 0.512855, + 1 + -0.130088, + 3 + -0.225548, + 5 + -0.745615, + 7 + 0.963223, + -3 + -0.678778, + -7 + -0.430329, + -3 + 0.964206, + 7 + 0.808534, + 5 + -0.632605, + -5 + -0.728056, + -5 + -0.0283051, + -1 + -0.292853, + 3 + -0.960114, + 1 + 0.266249, + 7 + -0.94076, + 7 + -0.680042, + -1 + 0.678469, + 3 + 0.553279, + 7 + 0.392802, + 1 + -0.308376, + 7 + -0.588163, + 5 + -0.235282, + 7 + -0.490381, + 5 + 0.412499, + -7 + -0.148118, + 7 + -0.20069, + -1 + -0.256974, + 1 + -0.946528, + -5 + -0.190544, + 1 + -0.774484, + -1 + 0.939011, + 3 + 0.401197, + 7 + 0.763682, + -7 + 0.970152, + 5 + -0.471915, + -3 + -0.0230657, + -1 + 0.666549, + 3 + -0.312851, + 5 + 0.909774, + -5 + 0.608703, + -1 + -0.398985, + -1 + -0.579955, + -3 + 0.427466, + -3 + -0.406024, + 5 + -0.923879, + 5 + -0.124516, + -7 + 0.389177, + -1 + 0.978163, + 7 + 0.321733, + -5 + -0.401276, + -3 + -0.669763, + 5 + 0.837051, + -3 + -0.507979, + -5 + 0.650163, + 5 + -0.533125, + -7 + -0.352708, + -3 + 0.975917, + -1 + 0.333199, + 1 + 0.786429, + 7 + 0.588826, + -3 + -0.254794, + -5 + 0.577074, + 3 + -0.445216, + -3 + -0.913091, + 1 + 0.833436, + 3 + 0.879009, + 7 + -0.420452, + -7 + -0.841488, + 3 + 0.941771, + -5 + -0.516194, + 1 + -0.111796, + 1 + 0.913016, + -3 + 0.831405, + 7 + -0.456459, + 5 + 0.52518, + 7 + 0.407003, + 5 + 0.477567, + -1 + 0.420401, + -1 + 0.437449, + -7 + -0.0206778, + -3 + 0.132506, + 3 + -0.0369548, + -3 + -0.66723, + 3 + 0.639026, + -5 + 0.818826, + -3 + 0.521142, + -7 + 0.239988, + 7 + 0.798847, + 3 + 0.568449, + -7 + -0.322325, + 1 + 0.74602, + 5 + -0.820488, + 5 + 0.422569, + -5 + 0.154974, + 3 + -0.598438, + -3 + -0.0493216, + 5 + -0.437171, + -7 + 0.91565, + 1 + -0.76322, + -7 + 0.655683, + 1 + -0.221855, + 3 + 0.499042, + 7 + -0.551781, + -1 + 0.776521, + 3 + 0.364049, + 7 + 0.76778, + 1 + 0.98362, + 1 + 0.901754, + -7 + -0.301171, + -7 + -0.154012, + -3 + -0.967804, + -1 + 0.205987, + 7 + -0.231608, + 1 + 0.577335, + -5 + 0.133768, + -5 + 0.959646, + -3 + -0.0372217, + -3 + 0.404834, + -1 + 0.457923, + 1 + 0.0552233, + -3 + 0.2, + 5 + -0.787169, + -1 + 0.572437, + 7 + -0.18741, + -1 + 0.0523727, + -1 + -0.804208, + 7 + -0.303471, + 7 + 0.73635, + -3 + -0.804122, + 1 + 0.962955, + 7 + 0.065147, + -7 + -0.464851, + 7 + 0.410402, + -1 + -0.213138, + 7 + 0.323269, + 5 + -0.812589, + 1 + -0.924136, + 3 + -0.0515391, + 5 + -0.942719, + -7 + 0.0813437, + -5 + -0.919358, + -3 + 0.09817, + -3 + 0.204768, + -3 + 0.895305, + -5 + 0.426145, + -1 + -0.654514, + 1 + -0.527968, + 1 + -0.93447, + 7 + -0.259295, + -5 + -0.357566, + -3 + 0.820761, + 3 + 0.061946, + 1 + -0.365104, + -1 + -0.484186, + 5 + -0.0747202, + 7 + 0.373292, + 3 + -0.225615, + 1 + 0.387072, + -1 + 0.0964885, + 5 + 0.318965, + -5 + -0.574407, + -1 + -0.5876, + 3 + -0.0651205, + -7 + -0.131517, + -5 + -0.700999, + -1 + 0.431009, + -5 + -0.378572, + -5 + -0.438665, + 3 + -0.0663064, + -1 + 0.303877, + 7 + 0.252822, + -5 + 0.127981, + -5 + -0.979741, + -7 + -0.977809, + 1 + -0.939208, + -5 + -0.619289, + -3 + -0.817288, + -7 + -0.682975, + 5 + 0.945473, + 3 + 0.696275, + -1 + 0.466816, + 3 + -0.632966, + -3 + 0.078222, + 5 + 0.546507, + -1 + 0.977089, + 7 + -0.133295, + -5 + -0.604371, + -3 + 0.365631, + -3 + 0.673212, + -1 + 0.180141, + 5 + 0.223484, + -1 + 0.146777, + 1 + -0.319683, + -1 + 0.857262, + 5 + -0.356152, + 5 + -0.598653, + 1 + 0.975409, + -5 + -0.881246, + -7 + -0.472377, + -3 + 0.0214979, + 7 + -0.788032, + 7 + -0.333508, + 7 + -0.750094, + -3 + -0.814424, + 7 + -0.965833, + 5 + -0.36787, + 3 + -0.612635, + -5 + 0.236003, + -5 + -0.785485, + -5 + 0.745934, + 3 + 0.841095, + 3 + 0.331357, + 3 + -0.341722, + 1 + 0.0449292, + 7 + -0.256584, + -3 + -0.666529, + 7 + -0.203782, + 1 + -0.442113, + 5 + 0.281735, + -7 + -0.600958, + 5 + -0.297631, + 7 + 0.834514, + 1 + -0.965433, + -7 + 0.980322, + -5 + -0.275104, + -5 + 0.501189, + 1 + 0.861033, + 3 + -0.186388, + -7 + -0.783021, + -3 + -0.331772, + -7 + -0.923864, + 7 + 0.981171, + -7 + 0.677146, + 5 + -0.764622, + 7 + 0.544671, + 3 + -0.149741, + -1 + -0.115158, + 5 + 0.315554, + 3 + -0.0435786, + -7 + -0.198421, + 3 + 0.728623, + 3 + 0.917598, + -7 + -0.222429, + -1 + -0.839337, + 1 + -0.837996, + 5 + 0.7184, + 3 + 0.279682, + 5 + 0.89931, + 1 + -0.0903269, + -3 + 0.311248, + -3 + -0.0615842, + -5 + 0.978228, + 5 + -0.0288547, + -7 + -0.319235, + 1 + 0.459872, + -7 + -0.762583, + 1 + 0.430673, + 7 + -0.202576, + 7 + -0.508028, + 5 + -0.563939, + 7 + 0.431253, + 3 + 0.924691, + -7 + -0.929823, + -7 + -0.745149, + -3 + -0.54763, + 7 + -0.233056, + -3 + 0.0728049, + 3 + 0.173541, + 5 + -0.99085, + -5 + -0.509606, + -7 + -0.0573629, + -5 + 0.146235, + 7 + -0.530049, + 5 + -0.92378, + 5 + -0.150627, + 7 + -0.632136, + 3 + -0.544558, + -1 + -0.559563, + -5 + -0.183858, + -3 + -0.0823922, + 3 + -0.845123, + -5 + 0.740183, + -1 + -0.864943, + -7 + -0.517753, + -7 + 0.273158, + -7 + 0.597718, + 7 + -0.960088, + -1 + 0.628689, + 5 + -0.100486, + 5 + -0.28978, + -3 + 0.591832, + 5 + -0.225949, + 1 + 0.434438, + 3 + 0.701275, + -5 + -0.110868, + 3 + -0.993528, + -1 + -0.279674, + -7 + -0.695508, + 3 + 0.208776, + 5 + 0.280286, + -7 + 0.098819, + 1 + -0.270841, + -3 + 0.163315, + 7 + -0.339504, + -1 + 0.503129, + -5 + -0.42331, + -5 + 0.289597, + 5 + -0.48842, + -1 + -0.301035, + -7 + 0.307344, + 3 + 0.149469, + -7 + -0.91815, + -7 + 0.735915, + -7 + 0.651662, + -5 + -0.367747, + 3 + 0.571618, + 3 + -0.0886024, + 7 + -0.287501, + 3 + -0.332199, + -3 + 0.103811, + 1 + 0.281067, + 1 + -0.380718, + -1 + 0.343006, + -7 + -0.940098, + -3 + 0.722196, + 5 + 0.874495, + 1 + 0.990522, + 3 + -0.915597, + -5 + -0.278943, + -7 + 0.203699, + -5 + 0.170043, + 7 + 0.536621, + -5 + 0.824829, + 5 + -0.832656, + -7 + 0.333, + -3 + -0.667407, + 7 + 0.105231, + 7 + -0.905234, + -1 + -0.810245, + 3 + 0.294136, + -1 + -0.514902, + 3 + -0.2467, + 3 + -0.587121, + 3 + 0.60538, + -3 + 0.0694657, + -5 + 0.0962229, + 7 + -0.291999, + -5 + 0.450209, + 3 + -0.147034, + -1 + -0.0838816, + 3 + 0.112086, + -5 + 0.194085, + 5 + -0.0903105, + -7 + -0.919954, + -5 + -0.967825, + -1 + -0.441373, + 5 + 0.768526, + 5 + 0.38484, + 3 + -0.947454, + 5 + -0.262922, + 7 + -0.593716, + -3 + 0.219333, + 3 + 0.076773, + 7 + 0.192425, + 1 + 0.970687, + 7 + -0.00340885, + 3 + -0.199764, + -3 + 0.255666, + -5 + 0.439951, + 1 + 0.505418, + 3 + -0.356007, + 5 + -0.318271, + -3 + 0.788047, + 5 + -0.924415, + -1 + 0.394691, + 1 + 0.972997, + 1 + 0.357046, + 3 + 0.419342, + -5 + -0.774465, + -7 + 0.0996104, + 5 + -0.458399, + -3 + -0.133173, + -1 + -0.671463, + 7 + -0.916153, + -7 + 0.110461, + 3 + 0.409689, + -3 + -0.355372, + -5 + -0.896134, + -7 + -0.950039, + 7 + 0.386037, + 3 + -0.798405, + -3 + -0.744455, + 1 + -0.572819, + -1 + 0.839239, + -3 + 0.570676, + 3 + -0.835377, + -7 + 0.034378, + 5 + 0.724415, + 5 + -0.252927, + -3 + 0.287315, + -3 + 0.334237, + 5 + -0.118203, + -1 + 0.502825, + -5 + -0.154511, + 5 + -0.127665, + 7 + 0.0817964, + 1 + 0.132329, + -5 + -0.546248, + -3 + 0.874254, + -3 + 0.421468, + 3 + -0.928829, + 5 + 0.620968, + 7 + 0.0580643, + -7 + -0.687253, + -7 + -0.628005, + 5 + -0.883083, + -5 + -0.270135, + 1 + -0.623219, + -7 + 0.277921, + 3 + 0.116588, + -5 + 0.264649, + -1 + -0.593871, + -7 + 0.329278, + -1 + -0.0926952, + -1 + 0.64349, + 1 + -0.10689, + 3 + -0.541441, + 1 + 0.499186, + -3 + 0.920398, + -1 + 0.381933, + 5 + -0.518618, + -5 + 0.618314, + 1 + 0.110954, + -1 + 0.576074, + 3 + 0.45385, + -5 + -0.917242, + 5 + -0.451152, + 5 + -0.705703, + -5 + -0.97524, + -5 + -0.732996, + 5 + 0.702813, + 3 + -0.229341, + 7 + -0.13257, + 7 + 0.994484, + 7 + -0.0231948, + 5 + 0.538224, + 1 + -0.838791, + 7 + 0.848763, + -7 + -0.539283, + -3 + 0.321736, + 5 + 0.22943, + 1 + -0.626804, + 5 + 0.209983, + -5 + 0.977037, + 3 + 0.448198, + 5 + -0.419565, + 7 + 0.666147, + -7 + 0.412532, + 7 + -0.0260039, + 1 + 0.545681, + 1 + 0.657399, + -5 + 0.275525, + 5 + 0.563082, + 1 + 0.88785, + -5 + 0.855898, + -1 + -0.758617, + -1 + 0.0505126, + 5 + 0.0387102, + 5 + 0.574784, + 1 + 0.1487, + 7 + -0.234118, + -1 + 0.458783, + 5 + -0.798949, + -7 + -0.300432, + 3 + -0.455072, + 1 + 0.24667, + -3 + 0.034758, + 1 + -0.491485, + 1 + 0.27987, + -5 + -0.92334, + 1 + 0.486993, + 5 + -0.624284, + -3 + 0.259474, + 3 + 0.384827, + 7 + -0.744943, + 3 + 0.669036, + -7 + -0.171024, + 1 + -0.963747, + -3 + -0.457945, + -1 + -0.271542, + 3 + -0.642662, + 5 + 0.867933, + -7 + 0.872486, + -5 + -0.0610653, + -3 + 0.0567537, + -5 + -0.384634, + -1 + -0.810843, + 1 + -0.210336, + 7 + -0.782186, + -3 + 0.206301, + 3 + -0.532726, + -1 + 0.792476, + 1 + -0.0254994, + 1 + -0.38317, + 5 + -0.444631, + -3 + 0.202259, + 7 + 0.906256, + -5 + -0.283238, + 1 + 0.761982, + -1 + 0.456456, + 7 + -0.213898, + 7 + -0.98443, + -7 + -0.984132, + -3 + -0.549083, + 7 + 0.946917, + 1 + -0.817794, + 3 + -0.902041, + -7 + 0.667457, + 7 + 0.476978, + -1 + 0.864841, + -1 + -0.100561, + -1 + 0.589944, + 1 + -0.417731, + -5 + -0.291668, + 3 + -0.341364, + 1 + -0.116372, + -5 + -0.678389, + 5 + -0.621016, + -7 + -0.557662, + 5 + -0.916104, + 1 + 0.416737, + -3 + -0.397013, + 3 + -0.767577, + 1 + 0.340769, + 7 + -0.54333, + -5 + 0.825698, + -7 + -0.0227328, + 1 + 0.688705, + -5 + 0.783876, + -5 + 0.36354, + 3 + -0.405894, + -1 + -0.505203, + 3 + -0.280375, + -7 + -0.0717587, + -5 + 0.254936, + -5 + -0.792482, + 7 + -0.425804, + 3 + 0.295604, + -5 + 0.294844, + -3 + 0.730185, + 3 + 0.0271969, + 5 + -0.303161, + -3 + 0.883759, + 3 + 0.827756, + -7 + 0.450664, + 5 + 0.435759, + 3 + 0.360285, + -7 + 0.409698, + 1 + 0.230758, + 7 + -0.352144, + 1 + -0.389721, + 7 + -0.718911, + 3 + 0.41957, + -3 + 0.620353, + -7 + 0.254944, + -1 + 0.81995, + 3 + -0.280774, + 3 + 0.906947, + 7 + -0.349169, + -1 + -0.00793728, + -5 + -0.64104, + -7 + 0.445183, + 3 + 0.914473, + 3 + -0.570084, + -1 + 0.594879, + -5 + -0.521969, + 1 + 0.0416743, + -3 + -0.799298, + 5 + -0.041766, + -7 + -0.218755, + 1 + 0.173665, + 7 + -0.880771, + -7 + 0.339146, + -1 + 0.961946, + 1 + 0.859441, + -5 + 0.0599979, + -3 + -0.243646, + 1 + 0.642304, + 5 + 0.427633, + -3 + 0.337803, + 5 + -0.876868, + -5 + 0.124084, + 7 + -0.390476, + 5 + -0.889517, + 7 + -0.0881519, + -5 + -0.985327, + -1 + 0.364205, + -1 + 0.481156, + 1 + 0.878136, + 3 + 0.270873, + -1 + -0.133771, + 7 + -0.599314, + 7 + 0.784159, + 1 + 0.555296, + 7 + -0.974226, + 5 + 0.520163, + -5 + 0.046348, + -5 + -0.487602, + 3 + 0.0383354, + -7 + -0.969134, + 5 + -0.00830264, + 5 + 0.582434, + -5 + 0.498667, + -5 + 0.0475678, + 7 + -0.011481, + -5 + 0.0134767, + 1 + 0.897857, + -1 + 0.859261, + 3 + -0.741447, + -5 + 0.61813, + 3 + 0.976057, + -5 + 0.671342, + -1 + -0.480269, + -7 + -0.183415, + 3 + -0.955847, + 3 + 0.770801, + -3 + 0.470981, + -7 + -0.778816, + 3 + -0.906343, + -1 + -0.727997, + 7 + -0.39431, + 7 + 0.80919, + 7 + -0.973433, + -3 + -0.627311, + 3 + 0.373299, + 5 + 0.907636, + -5 + 0.658848, + 7 + 0.681815, + 5 + 0.589045, + -5 + 0.0950571, + -7 + 0.112081, + 5 + 0.34511, + -3 + 0.315859, + 5 + -0.181386, + -3 + -0.714938, + 1 + 0.308135, + 7 + 0.535557, + 7 + -0.0709868, + -1 + 0.552407, + -7 + -0.847801, + 7 + 0.160415, + 5 + -0.51117, + 3 + -0.951139, + -3 + 0.0406191, + 5 + -0.895575, + 5 + 0.0746354, + -3 + 0.915248, + -3 + 0.842174, + -7 + 0.595946, + 3 + 0.700337, + -3 + -0.23779, + 3 + -0.655733, + -5 + -0.894634, + -3 + -0.695807, + 5 + -0.476673, + 7 + -0.279169, + -5 + 0.507948, + -5 + 0.499507, + 3 + 0.0916842, + 3 + -0.837399, + -5 + 0.143527, + 3 + 0.58052, + -7 + 0.378768, + 5 + 0.811361, + -1 + 0.0748057, + 3 + 0.453959, + -7 + 0.990606, + 3 + -0.450379, + 5 + 0.395584, + -7 + -0.114441, + 5 + 0.426232, + 1 + -0.711673, + 1 + 0.077825, + -5 + -0.584918, + 1 + -0.457057, + -3 + -0.366392, + -7 + 0.00484131, + -3 + 0.215838, + -3 + -0.19239, + -5 + 0.300349, + 5 + 0.925702, + 7 + 0.693147, + -3 + -0.771327, + 7 + 0.850479, + 7 + 0.55379, + -5 + -0.622361, + -7 + -0.797468, + -1 + 0.865325, + -1 + 0.594149, + -3 + 0.402537, + 3 + 0.5647, + -5 + 0.408661, + 7 + 0.434393, + -5 + 0.369053, + 7 + 0.193313, + 7 + 0.0768285, + -5 + -0.966767, + 7 + 0.316068, + 5 + 0.393416, + -1 + 0.678055, + -1 + -0.426397, + 7 + -0.0972791, + 5 + 0.863534, + 7 + 0.857534, + 3 + -0.591288, + -1 + -0.978807, + -5 + 0.47735, + 1 + -0.387742, + 7 + 0.418231, + -7 + -0.918646, + 3 + -0.487032, + -7 + 0.169229, + 5 + 0.963037, + 3 + -0.651308, + 1 + -0.963926, + -7 + -0.870113, + -1 + -0.598625, + 1 + 0.578904, + -1 + -0.0948276, + -5 + 0.227649, + 1 + 0.555606, + -1 + -0.668322, + 1 + 0.0749024, + -5 + -0.607571, + 5 + -0.349931, + -1 + -0.898107, + 5 + 0.312465, + 7 + 0.772347, + 5 + 0.0899041, + -1 + -0.741034, + -3 + 0.26158, + 1 + -0.539694, + 7 + -0.115106, + -1 + -0.411724, + 3 + 0.0316011, + -7 + -0.810337, + -5 + 0.181813, + 5 + 0.318575, + -5 + -0.176396, + -1 + -0.639559, + 1 + 0.966577, + 7 + -0.685124, + -3 + -0.036449, + -5 + -0.456288, + -1 + 0.80942, + 1 + -0.842449, + -7 + 0.390273, + 3 + -0.931459, + 5 + 0.693488, + -7 + 0.247743, + -3 + -0.848713, + -3 + 0.137249, + -7 + -0.213185, + -7 + -0.755191, + 7 + -0.639001, + 5 + 0.91416, + 5 + -0.193425, + -5 + 0.80731, + -1 + -0.716912, + 5 + -0.503475, + 5 + -0.0585372, + 5 + -0.0209306, + 5 + -0.150028, + -3 + 0.634776, + 5 + 0.538764, + 7 + 0.704398, + -1 + -0.61061, + -7 + -0.624288, + 1 + -0.926651, + -7 + 0.580724, + 3 + 0.24162, + 1 + 0.447202, + 7 + -0.76537, + 7 + -0.753749, + 7 + -0.93289, + 7 + 0.570568, + -1 + 0.901893, + -1 + -0.297356, + 5 + -0.189813, + -3 + 0.21001, + -3 + 0.541859, + -5 + -0.73421, + 7 + 0.928552, + -7 + -0.355678, + -5 + -0.221657, + -5 + -0.0512875, + 3 + -0.298442, + -1 + -0.820576, + 7 + -0.771328, + 1 + -0.961217, + 5 + -0.161851, + -1 + -0.405209, + 3 + -0.662432, + -3 + 0.528404, + 1 + -0.226934, + -3 + 0.0363932, + 7 + 0.886687, + 3 + 0.393918, + -5 + -0.507128, + 1 + -0.189558, + -7 + -0.823271, + 7 + -0.180617, + -1 + 0.321553, + -1 + 0.989206, + -7 + -0.874277, + 1 + -0.113906, + 7 + 0.161257, + 3 + 0.670416, + -3 + -0.763578, + -1 + 0.424893, + 3 + -0.0447045, + -5 + -0.957789, + -1 + 0.196626, + -5 + 0.00535004, + 3 + 0.254757, + -7 + -0.927024, + 3 + -0.959979, + 1 + -0.949363, + -5 + 0.674222, + 1 + -0.848884, + -7 + 0.0919615, + 1 + -0.58394, + -1 + -0.515551, + -7 + -0.961024, + 7 + -0.978422, + 7 + 0.86705, + 7 + -0.323448, + -5 + -0.916549, + -3 + -0.512443, + -3 + -0.892435, + -1 + 0.0811992, + 7 + -0.1951, + 1 + -0.31832, + 7 + 0.389861, + -7 + -0.429737, + 7 + 0.14079, + -7 + -0.306634, + 1 + -0.0533624, + 1 + -0.438584, + -7 + -0.63111, + -7 + -0.559344, + -5 + 0.783094, + -7 + -0.735777, + 7 + -0.58636, + -7 + -0.116192, + -5 + -0.801831, + -5 + 0.969511, + -5 + 0.144718, + -5 + 0.363059, + -1 + -0.667404, + 3 + -0.134134, + -1 + 0.734085, + 5 + -0.165216, + 1 + 0.149468, + -5 + -0.15301, + -3 + 0.83035, + -3 + -0.27281, + -1 + 0.688733, + 5 + -0.406828, + -5 + -0.018298, + 5 + 0.219722, + -5 + 0.840822, + -7 + 0.256695, + -1 + -0.300632, + -5 + 0.403999, + -5 + 0.574885, + -3 + -0.92988, + 1 + -0.837794, + 3 + 0.510347, + 1 + 0.946242, + 1 + -0.558269, + 7 + -0.945935, + -7 + -0.106771, + 3 + -0.383966, + -5 + 0.370004, + -7 + 0.428693, + 5 + 0.936122, + 1 + -0.782085, + -7 + 0.528864, + 1 + 0.697761, + -7 + -0.681381, + -5 + 0.152231, + 5 + -0.900638, + 5 + -0.334353, + 1 + 0.862458, + -5 + -0.694343, + -7 + -0.938721, + -5 + 0.119729, + -7 + -0.874769, + -5 + -0.120494, + -3 + 0.506938, + 5 + 0.965172, + -1 + -0.888394, + -3 + -0.595798, + -5 + 0.802503, + -3 + -0.789257, + -3 + 0.351862, + 3 + -0.750966, + -1 + 0.584273, + -3 + -0.0831131, + -7 + -0.28384, + -3 + 0.806411, + 7 + -0.200101, + 3 + 0.640918, + -1 + 0.977479, + 1 + 0.865009, + -3 + -0.368203, + 7 + 0.556652, + -1 + -0.991885, + -5 + 0.332904, + 3 + 0.470344, + -7 + 0.205081, + -7 + -0.314842, + -3 + -0.62, + 3 + 0.34363, + 1 + -0.425907, + -7 + -0.702084, + -3 + -0.288143, + -7 + 0.243932, + -1 + 0.0855131, + -5 + -0.139345, + 3 + -0.959163, + 3 + 0.431497, + -7 + 0.261823, + -3 + 0.914225, + -1 + 0.325961, + 3 + -0.359881, + 7 + -0.468639, + 7 + -0.803865, + -1 + 0.343444, + 1 + 0.736499, + 5 + 0.382909, + -1 + -0.721058, + -1 + -0.823382, + 3 + -0.176144, + 5 + 0.251272, + -1 + -0.786581, + -5 + 0.273133, + 7 + -0.41622, + 3 + 0.121719, + 7 + 0.620911, + -1 + 0.237504, + 1 + -0.335624, + -7 + 0.42324, + -3 + 0.729575, + -7 + -0.723781, + 3 + 0.273075, + 3 + -0.229695, + 3 + 0.507748, + -5 + 0.294614, + -7 + -0.490011, + 3 + 0.297713, + -3 + -0.330685, + -7 + 0.441233, + 5 + -0.622061, + 5 + -0.208099, + 5 + -0.710362, + -1 + 0.154774, + -5 + 0.486696, + 5 + -0.168477, + 7 + -0.653855, + 7 + -0.0172002, + -1 + -0.1059, + 3 + 0.654305, + 1 + -0.459053, + 7 + 0.751362, + 7 + 0.407269, + 7 + 0.871658, + 7 + 0.654213, + 7 + 0.0624889, + 7 + -0.583527, + 1 + -0.252231, + 1 + -0.320237, + 5 + -0.0136125, + 7 + -0.729181, + -5 + -0.0353086, + 5 + -0.0951113, + 3 + -0.0836304, + -1 + -0.11923, + 7 + 0.962136, + -5 + -0.830669, + 1 + 0.29644, + 5 + 0.045498, + 1 + 0.76292, + -5 + -0.929796, + 5 + -0.083544, + -7 + 0.472663, + 7 + -0.746787, + 3 + 0.662228, + -5 + -0.41748, + -7 + 0.850784, + -7 + -0.130054, + -1 + 0.432904, + 7 + -0.787268, + -3 + -0.248262, + 5 + 0.406222, + 5 + -0.775207, + 7 + -0.0549824, + -1 + 0.930082, + -3 + 0.651628, + -7 + -0.373963, + 7 + -0.38767, + -5 + -0.199335, + 3 + -0.0845591, + -3 + -0.400573, + -1 + -0.423932, + 3 + 0.496079, + 3 + -0.0049753, + 5 + -0.937373, + -1 + 0.00805519, + 7 + -0.387026, + -7 + 0.379173, + 3 + -0.509631, + -3 + 0.0652572, + -7 + 0.292195, + -3 + -0.0630124, + -3 + 0.210706, + -7 + 0.0474516, + -3 + 0.088253, + 5 + -0.729131, + -1 + -0.118407, + 5 + 0.587638, + -7 + 0.963741, + -3 + 0.912494, + -7 + 0.723939, + 5 + 0.977461, + 3 + 0.230908, + -7 + 0.0875093, + -5 + 0.827526, + 7 + -0.821136, + -3 + 0.402932, + -7 + 0.441547, + 7 + 0.416953, + 5 + 0.70044, + 3 + 0.973559, + 3 + 0.407091, + -5 + -0.826277, + 3 + -0.389221, + 5 + -0.583906, + 1 + -0.0841909, + -7 + 0.530444, + -1 + -0.918261, + 3 + -0.638232, + 1 + -0.776938, + -7 + 0.706762, + -1 + 0.16429, + -7 + -0.306863, + -3 + -0.670615, + 1 + -0.819745, + 1 + -0.014878, + -3 + 0.178679, + 1 + 0.441678, + -1 + -0.193108, + -3 + -0.33399, + 5 + 0.275276, + -7 + 0.167054, + -5 + 0.134306, + 7 + -0.394252, + 3 + 0.941986, + -7 + -0.878877, + -5 + 0.770656, + -5 + 0.730814, + -1 + 0.143592, + -3 + 0.442492, + -1 + -0.712593, + 5 + 0.599122, + 1 + 0.263907, + -7 + 0.47737, + -7 + 0.0559669, + -3 + 0.208639, + 1 + 0.827161, + 1 + 0.886639, + 1 + 0.598246, + -7 + -0.191541, + 3 + 0.511962, + 3 + -0.645528, + 1 + -0.593154, + -5 + 0.52999, + 5 + -0.653963, + 1 + 0.574099, + -5 + -0.0896155, + 1 + -0.636268, + 7 + 0.343794, + -7 + 0.155548, + -1 + -0.121609, + -1 + -0.297629, + -5 + -0.468962, + 5 + -0.555227, + -1 + -0.296793, + -3 + -0.855934, + 7 + -0.739775, + 1 + -0.756048, + 1 + -0.46236, + -7 + -0.179736, + 3 + 0.125628, + 1 + 0.10038, + -5 + -0.380856, + 7 + 0.450066, + 7 + 0.959734, + -3 + 0.796831, + -1 + 0.23315, + -3 + 0.298099, + -5 + -0.383893, + -3 + -0.296636, + -5 + 0.138614, + 1 + -0.114746, + 7 + 0.555051, + 1 + -0.950471, + -1 + 0.124465, + 1 + 0.037862, + 1 + 0.719934, + 7 + -0.0167727, + -7 + -0.983453, + -5 + -0.418557, + 7 + -0.192828, + 7 + -0.0814223, + 1 + 0.224621, + 5 + -0.597524, + 5 + 0.415634, + 1 + -0.954608, + -3 + 0.227498, + -5 + -0.108549, + 7 + 0.0881721, + 3 + 0.845206, + 3 + -0.913562, + -7 + 0.24586, + -7 + 0.289418, + -1 + 0.194941, + 3 + 0.793157, + 7 + -0.434518, + -7 + 0.820917, + 5 + 0.2382, + 5 + -0.946464, + 1 + 0.686291, + 3 + -0.265611, + -1 + -0.215793, + 1 + 0.247293, + 3 + 0.370775, + -1 + -0.1934, + 5 + 0.306202, + 5 + -0.454743, + -1 + -0.529622, + 1 + 0.856026, + -5 + -0.672594, + -5 + -0.429688, + 7 + -0.898493, + 3 + -0.296784, + -7 + -0.839249, + 7 + -0.238149, + -3 + 0.87197, + 7 + -0.985437, + -3 + 0.243879, + 1 + -0.0590569, + -7 + 0.3087, + -7 + -0.415904, + -3 + 0.238146, + -3 + -0.00380364, + 7 + -0.524692, + -1 + 0.715206, + -1 + -0.382632, + 7 + -0.433315, + -3 + 0.671116, + 5 + 0.319951, + -5 + -0.467809, + 1 + -0.914862, + -1 + -0.848039, + -7 + 0.916399, + -3 + 0.158824, + -7 + 0.432194, + 5 + 0.939947, + -3 + -0.938313, + -1 + 0.111712, + 1 + -0.830159, + -1 + 0.269145, + -3 + -0.282773, + -7 + 0.397815, + -7 + 0.312644, + 7 + 0.101858, + 5 + 0.398991, + 7 + 0.931748, + 5 + -0.216404, + 5 + -0.739909, + -3 + 0.837449, + 5 + -0.292918, + 3 + -0.811216, + 3 + -0.54535, + 3 + -0.206546, + 7 + 0.287012, + 5 + 0.416343, + -7 + 0.226965, + 3 + 0.650639, + 7 + -0.513567, + 3 + 0.35494, + 7 + 0.251297, + 3 + 0.222854, + -3 + 0.631017, + 1 + -0.834925, + -5 + 0.302606, + 5 + -0.161238, + -1 + -0.717755, + -1 + 0.163733, + 7 + 0.683634, + -3 + -0.0890416, + 5 + -0.0241376, + -7 + -0.331885, + -1 + -0.566607, + 5 + -0.0680727, + -1 + 0.69374, + -5 + -0.441671, + 3 + -0.917287, + 5 + -0.447226, + 5 + 0.530121, + 3 + -0.393156, + 7 + -0.625747, + 1 + 0.660945, + 1 + 0.0093144, + 7 + -0.198812, + 5 + 0.442133, + 1 + -0.569587, + -1 + 0.969233, + -3 + 0.831887, + 7 + -0.129281, + -5 + 0.790104, + -3 + -0.329582, + 3 + -0.846209, + 5 + 0.921283, + 5 + 0.0625507, + -3 + 0.292014, + -5 + 0.833173, + -7 + -0.674783, + -3 + -0.846611, + 1 + 0.893338, + -7 + 0.983207, + -7 + -0.776993, + -7 + 0.250987, + -5 + 0.0683537, + 7 + -0.183423, + 1 + -0.0923144, + 3 + 0.316882, + 3 + 0.436083, + -1 + 0.561959, + 5 + 0.199397, + 3 + 0.998894, + -5 + -0.762317, + 1 + -0.264652, + -1 + 0.000935957, + -5 + -0.737429, + 5 + -0.449802, + -3 + -0.153005, + -7 + -0.825486, + -3 + 0.381528, + -3 + -0.834704, + 1 + -0.869081, + -5 + 0.658949, + -7 + 0.538412, + 1 + -0.274676, + -3 + -0.131948, + -5 + -0.89239, + 5 + -0.216419, + 5 + 0.0464617, + -5 + -0.202859, + -5 + 0.937449, + 5 + 0.424624, + 1 + 0.22882, + 7 + 0.683182, + 1 + -0.649762, + 3 + -0.764787, + 7 + -0.573145, + -5 + 0.304541, + 3 + 0.3929, + -7 + -0.210616, + -3 + 0.373165, + -7 + -0.21229, + -7 + 0.897832, + -7 + 0.909656, + 1 + 0.948898, + 3 + -0.42523, + 3 + 0.567772, + -3 + -0.527982, + 3 + -0.189502, + 5 + 0.970517, + 7 + 0.282051, + -3 + 0.430664, + 3 + -0.793949, + -7 + 0.545716, + -3 + 0.35154, + -3 + -0.821351, + 5 + -0.395689, + -5 + -0.620034, + 5 + -0.608408, + -3 + 0.94029, + -1 + 0.0666049, + 5 + -0.51607, + 1 + 0.991041, + 7 + 0.172753, + 5 + -0.0221328, + 5 + -0.193889, + -5 + -0.13076, + 3 + 0.138734, + 3 + 0.59089, + 3 + -0.887206, + -3 + 0.845891, + -1 + -0.347074, + 5 + -0.0834612, + 3 + -0.876824, + -1 + -0.810422, + -1 + -0.231434, + 1 + -0.239487, + -5 + 0.0323537, + 1 + -0.581238, + 5 + 0.00602403, + 5 + 0.0905542, + 3 + 0.498012, + -5 + 0.254225, + 3 + 0.314102, + 5 + 0.0299345, + 5 + -0.45939, + -1 + 0.448653, + -3 + 0.647585, + 1 + 0.318478, + 5 + 0.455767, + -1 + 0.133022, + 1 + 0.614847, + 1 + 0.120892, + -5 + 0.224634, + 5 + 0.132055, + -1 + 0.743952, + -5 + 0.425553, + 5 + -0.111105, + 1 + 0.174118, + 1 + 0.221772, + -7 + -0.845315, + -3 + 0.19196, + 7 + -0.840461, + 5 + -0.129635, + 1 + -0.596764, + 3 + -0.955832, + 1 + 0.585824, + 5 + 0.0742671, + 5 + -0.517633, + -1 + 0.48289, + 7 + 0.0644312, + 1 + -0.795109, + -7 + -0.782286, + -1 + 0.0230929, + 1 + -0.718512, + -1 + 0.764088, + 5 + 0.510258, + -5 + 0.657883, + -7 + -0.345766, + -3 + 0.430414, + 5 + 0.0833478, + -5 + -0.264892, + 3 + 0.710985, + 1 + 0.150336, + 5 + -0.861506, + 3 + -0.0429562, + -1 + 0.434927, + 7 + 0.815823, + -5 + -0.824405, + 7 + -0.262346, + -7 + -0.164051, + -5 + -0.646918, + 3 + -0.147091, + 3 + 0.13859, + -1 + -0.575533, + -3 + 0.103353, + -5 + 0.992246, + -1 + -0.611302, + 7 + -0.0318776, + 1 + 0.460203, + -3 + 0.548152, + -7 + 0.0172631, + -3 + -0.485489, + -7 + -0.980713, + -7 + -0.827265, + -1 + -0.864176, + -7 + 0.851271, + 7 + -0.466744, + -7 + 0.436088, + -3 + 0.576107, + -7 + -0.637538, + 7 + 0.655137, + 5 + -0.826798, + -5 + 0.848056, + 3 + 0.666798, + -1 + -0.180115, + 7 + 0.419637, + 5 + -0.0167801, + 3 + -0.68837, + 3 + 0.946745, + 3 + -0.0950071, + -7 + -0.827281, + -1 + 0.78343, + -5 + -0.582113, + 7 + 0.299523, + 1 + -0.488113, + 5 + -0.341736, + 7 + 0.530617, + 7 + -0.326339, + -7 + -0.817531, + -3 + -0.221869, + -5 + 0.416757, + 1 + 0.506333, + 1 + -0.2654, + 7 + 0.763487, + -5 + -0.943085, + 7 + 0.791527, + -5 + 0.0668543, + -7 + 0.938847, + -3 + 0.143887, + -3 + 0.381707, + -3 + 0.19505, + -3 + -0.920517, + -5 + 0.145063, + -5 + 0.237513, + -7 + -0.120207, + -7 + -0.0991134, + -5 + 0.0680013, + 1 + -0.0638738, + 5 + 0.970159, + 5 + 0.213576, + 1 + -0.263613, + -7 + -0.544301, + -5 + -0.828692, + -5 + 0.166918, + -5 + -0.761728, + 5 + 0.120694, + 5 + 0.903705, + -5 + 0.211521, + 3 + 0.290967, + 7 + -0.464751, + -7 + 0.186847, + 7 + 0.32524, + -7 + 0.111797, + 1 + -0.788556, + 1 + -0.14745, + -3 + -0.968889, + 3 + -0.37981, + 5 + 0.00729347, + 7 + 0.504821, + 1 + -0.961113, + 3 + 0.710415, + -5 + -0.613475, + 5 + -0.895771, + -1 + -0.895503, + 5 + -0.461719, + 5 + 0.0161815, + -5 + -0.24625, + -7 + -0.572922, + -1 + -0.459816, + 7 + -0.419624, + -5 + 0.696952, + -5 + 0.927165, + -5 + 0.243638, + 7 + 0.360799, + 3 + 0.347879, + -3 + -0.0232377, + 3 + 0.712201, + -1 + 0.759489, + -7 + 0.438561, + -7 + -0.572822, + 1 + -0.737766, + 3 + 0.0680258, + -1 + 0.686509, + 5 + -0.262713, + -5 + -0.79966, + 5 + -0.236232, + -7 + -0.0260004, + -7 + 0.218216, + -3 + 0.370607, + 3 + 0.816354, + 7 + 0.452291, + -3 + -0.822625, + 3 + 0.848817, + 7 + 0.365835, + 1 + -0.676283, + 1 + -0.0594598, + -5 + 0.521534, + 1 + -0.486592, + 7 + -0.986362, + -7 + 0.0779941, + -3 + -0.08751, + 7 + -0.491647, + 7 + -0.270531, + -1 + -0.204778, + 1 + -0.231377, + -7 + -0.469895, + -1 + -0.844354, + -7 + -0.264911, + -1 + -0.1599, + -7 + -0.44972, + -1 + 0.194789, + 1 + -0.104809, + 3 + -0.228419, + -7 + -0.803297, + -7 + 0.625464, + -1 + -0.352292, + -1 + -0.755153, + -1 + -0.67635, + 7 + 0.297913, + 5 + 0.57017, + 5 + -0.173484, + 5 + 0.668881, + 1 + 0.277459, + -3 + -0.784868, + 5 + -0.499577, + 3 + -0.10745, + 7 + 0.92074, + -3 + -0.987991, + 7 + 0.915782, + 3 + -0.98239, + 1 + -0.781632, + -5 + 0.853114, + 5 + -0.13405, + -5 + 0.870097, + 7 + -0.696323, + 7 + -0.94934, + -3 + -0.398685, + -7 + 0.869119, + -5 + -0.903581, + -7 + 0.131423, + -3 + 0.834563, + 7 + 0.143985, + 3 + 0.145958, + -3 + 0.536994, + -5 + -0.691582, + 5 + 0.556042, + 7 + -0.58014, + -5 + -0.103551, + -1 + 0.15221, + 3 + -0.757364, + -5 + 0.580815, + 5 + 0.852026, + -7 + -0.470408, + -3 + 0.0561844, + 5 + -0.515549, + 1 + 0.173103, + -3 + -0.168945, + 5 + -0.762956, + -3 + 0.793081, + -1 + -0.676991, + 3 + 0.665824, + 5 + 0.121066, + -5 + 0.731384, + -5 + 0.671191, + -7 + -0.175862, + -7 + 0.486734, + 5 + 0.163906, + -3 + -0.529629, + -3 + -0.741516, + -5 + 0.780671, + -7 + -0.230291, + -3 + 0.302234, + 7 + -0.987584, + -7 + 0.429419, + 7 + -0.123349, + -3 + -0.693596, + 1 + 0.156304, + -7 + -0.070418, + -5 + 0.939389, + 3 + -0.282077, + 7 + -0.461724, + -7 + -0.266467, + -3 + 0.973726, + 5 + 0.324534, + 1 + 0.798357, + -3 + -0.225007, + -3 + 0.326469, + 1 + 0.217389, + -7 + 0.771884, + 1 + -0.448262, + 1 + 0.834186, + 5 + -0.8447, + 7 + 0.265382, + 7 + 0.882236, + 7 + 0.951853, + 3 + -0.212489, + 7 + -0.900493, + -1 + 0.827988, + 5 + -0.96957, + 5 + -0.794382, + 1 + -0.360357, + -7 + 0.686111, + -5 + -0.770717, + -3 + 0.777591, + 1 + -0.164214, + -1 + 0.85202, + -1 + -0.838606, + 5 + 0.727194, + 3 + 0.628267, + 3 + 0.94657, + 3 + 0.664833, + -1 + -0.545169, + 1 + -0.791937, + 5 + -0.863989, + 1 + -0.433051, + 7 + 0.604505, + -5 + 0.469176, + 5 + 0.521661, + 5 + -0.652277, + 5 + -0.956757, + -1 + 0.179364, + 3 + 0.0835185, + 5 + 0.379708, + -5 + -0.00418501, + -3 + 0.802623, + -1 + 0.127959, + 3 + 0.740128, + 7 + 0.0877058, + -3 + -0.644691, + -7 + 0.803557, + -3 + 0.35763, + 7 + -0.896354, + 5 + -0.985988, + -5 + -0.475576, + -7 + -0.837911, + -5 + 0.399102, + -1 + 0.180557, + 7 + -0.257409, + -3 + 0.748304, + 1 + 0.488153, + 1 + -0.528074, + -7 + -0.568786, + -1 + -0.209861, + 7 + 0.758874, + -7 + 0.690599, + -5 + 0.29666, + -7 + 0.14263, + -5 + -0.580595, + -5 + 0.436222, + -7 + -0.230854, + 1 + -0.0199466, + 7 + 0.0582533, + 1 + -0.241347, + -7 + 0.120772, + -5 + 0.158568, + -7 + 0.590528, + 1 + 0.26066, + 7 + 0.696681, + -3 + 0.343628, + -1 + -0.341235, + -1 + 0.426748, + -5 + -0.39029, + -3 + 0.0793041, + -1 + 0.240872, + -7 + -0.986816, + 5 + -0.546091, + 7 + -0.435825, + -5 + 0.631116, + 5 + 0.793044, + -3 + -0.219459, + 7 + 0.140597, + 5 + 0.447243, + 1 + -0.968491, + 5 + 0.843524, + -5 + -0.860415, + 5 + -0.620946, + 1 + -0.41902, + 7 + -0.81125, + 5 + 0.753432, + -3 + -0.727435, + -1 + -0.141588, + -3 + -0.551413, + -5 + 0.381663, + 5 + -0.0711982, + -5 + 0.390526, + 1 + 0.783724, + -7 + 0.573399, + -3 + -0.939007, + -7 + 0.238314, + -1 + -0.521158, + 5 + 0.779281, + -7 + -0.53298, + 3 + 0.21555, + 3 + 0.482487, + 7 + -0.514751, + -1 + -0.800237, + 1 + -0.764197, + -3 + 0.647617, + 7 + 0.0499004, + -5 + 0.979748, + -3 + 0.67735, + -7 + 0.183253, + -5 + 0.362151, + 5 + -0.545888, + 3 + 0.771438, + -3 + 0.255733, + -7 + 0.115492, + 3 + 0.469995, + -1 + 0.129762, + 3 + -0.767167, + -1 + 0.59735, + -7 + 0.999858, + -5 + -0.412252, + -5 + -0.240744, + -7 + -0.94988, + 7 + -0.533656, + 3 + 0.842152, + 5 + -0.0103345, + 7 + 0.0454008, + 3 + 0.333439, + 3 + -0.456548, + -3 + -0.295064, + 1 + -0.0291067, + 3 + -0.980701, + 5 + 0.0998633, + -7 + -0.236756, + -1 + -0.209321, + 3 + -0.238139, + -1 + 0.873939, + 3 + -0.723713, + -5 + 0.814455, + 3 + 0.679885, + -5 + -0.309287, + 1 + 0.911921, + -5 + -0.330781, + 5 + 0.780826, + 1 + 0.715838, + 3 + -0.334343, + -1 + 0.986761, + -1 + -0.439617, + -3 + -0.590452, + 1 + -0.263775, + 7 + 0.667562, + -5 + -0.76034, + -5 + 0.362745, + 1 + -0.472352, + -7 + 0.206034, + -3 + 0.376895, + 5 + 0.551758, + -3 + 0.0431443, + 5 + -0.310862, + -3 + -0.430074, + 5 + 0.275111, + 7 + -0.912242, + 5 + -0.535872, + 3 + 0.320622, + 3 + 0.381784, + 5 + 0.39575, + -5 + 0.419947, + -1 + 0.632249, + 7 + 0.699329, + 5 + -0.53677, + -7 + 0.160241, + 5 + -0.293807, + -5 + 0.291076, + -5 + 0.691705, + 1 + 0.759055, + 3 + -0.907042, + -5 + -0.23742, + -1 + -0.718808, + -3 + 0.324324, + -5 + 0.768603, + -1 + -0.765854, + 3 + -0.270759, + -3 + -0.780064, + 7 + 0.530695, + 5 + -0.923683, + -1 + -0.209208, + 5 + -0.3521, + 7 + -0.81082, + 7 + -0.472168, + 7 + 0.56371, + 5 + -0.87698, + 3 + -0.0658053, + -3 + 0.646983, + 1 + -0.603423, + 7 + 0.458566, + 7 + 0.32752, + -7 + 0.852152, + 1 + 0.996179, + -1 + 0.686456, + -3 + -0.484814, + 5 + -0.675017, + 5 + -0.458211, + 3 + -0.984357, + -1 + 0.266912, + -7 + -0.589247, + -5 + 0.082882, + -5 + -0.885084, + -3 + -0.560765, + 5 + -0.942018, + 7 + 0.572901, + 7 + -0.171902, + -3 + 0.895929, + -7 + -0.655681, + 5 + -0.029179, + 1 + -0.978318, + 1 + -0.0494022, + -3 + 0.315903, + -7 + -0.249841, + 7 + -0.960858, + -3 + 0.444645, + 3 + -0.725221, + -1 + -0.250617, + 5 + 0.072717, + 3 + -0.348692, + -7 + 0.465731, + 7 + 0.770554, + -1 + 0.161133, + 3 + 0.0440529, + -1 + -0.245592, + -1 + -0.286838, + 1 + 0.710223, + 7 + -0.744359, + -7 + 0.754745, + -3 + 0.268595, + -7 + -0.952184, + 5 + -0.12754, + 1 + -0.113531, + 3 + -0.965244, + 3 + -0.295564, + 5 + -0.589246, + -5 + 0.901493, + 7 + 0.499927, + -1 + 0.205479, + -1 + 0.799496, + 7 + 0.159986, + 1 + 0.0494691, + 5 + 0.414586, + 1 + 0.160234, + 5 + -0.754135, + 7 + 0.533292, + 3 + 0.20959, + -3 + 0.265984, + -1 + -0.596171, + -3 + 0.59227, + -5 + 0.809165, + -3 + 0.731077, + -5 + 0.77249, + -3 + 0.114624, + 7 + -0.612689, + -3 + -0.226237, + -1 + -0.491637, + 5 + -0.902752, + 7 + -0.340862, + 7 + -0.764615, + 1 + 0.361337, + 5 + 0.907293, + -1 + -0.207671, + -7 + 0.749045, + 7 + -0.736116, + 7 + 0.331618, + -5 + -0.0821605, + 3 + -0.784978, + 3 + -0.962937, + 5 + 0.0240877, + -7 + -0.357058, + 7 + 0.582812, + -1 + 0.300038, + 3 + 0.442207, + 1 + 0.311886, + 1 + -0.0907658, + -3 + -0.190202, + 3 + 0.752307, + -5 + 0.110897, + -3 + -0.130689, + 3 + 0.604778, + -5 + 0.832513, + -5 + 0.20769, + 1 + 0.918947, + 7 + 0.635097, + -3 + -0.250696, + -5 + -0.673562, + -7 + 0.188827, + -7 + 0.859836, + -5 + -0.553663, + -1 + -0.693482, + -3 + -0.0370091, + -5 + -0.945403, + -3 + -0.0942642, + 5 + -0.788987, + 7 + 0.130865, + -3 + -0.0568169, + 1 + 0.469934, + -3 + 0.236228, + -3 + 0.969961, + -7 + 0.777844, + -1 + -0.863909, + 1 + -0.0100366, + 3 + -0.901984, + 7 + -0.188674, + -3 + -0.0859814, + -7 + 0.289988, + -5 + 0.216434, + 5 + 0.373371, + -3 + 0.756403, + -3 + -0.327696, + -1 + 0.500791, + 5 + 0.577182, + 1 + 0.846249, + 7 + -0.851769, + -7 + 0.957447, + -3 + -0.351796, + -1 + -0.985339, + -7 + -0.840053, + 7 + -0.911335, + 3 + 0.856743, + 3 + -0.901107, + 3 + -0.966849, + 7 + -0.885129, + -5 + -0.284155, + 7 + -0.344691, + -5 + 0.355503, + 7 + 0.752017, + 5 + -0.243656, + 3 + -0.928544, + 5 + 0.782105, + -7 + -0.759649, + 1 + -0.0744518, + -3 + 0.609258, + 5 + -0.125631, + 5 + 0.25112, + -7 + -0.339128, + 7 + 0.412046, + -5 + 0.555857, + 7 + -0.635087, + 7 + 0.516426, + -1 + 0.74659, + 3 + 0.969918, + -1 + 0.436694, + -5 + 0.0135384, + -3 + 0.340553, + 1 + -0.333334, + 5 + -0.401135, + 3 + 0.217065, + 5 + -0.585701, + 7 + 0.283774, + 1 + 0.436392, + 7 + 0.636664, + 5 + -0.0233952, + 5 + 0.966634, + -5 + 0.792896, + 5 + 0.946402, + -1 + -0.831078, + -7 + -0.944117, + 7 + 0.832928, + -3 + -0.37542, + -7 + -0.951767, + -7 + -0.414159, + 3 + -0.440777, + 5 + -0.591346, + -3 + -0.942129, + 1 + -0.475855, + -1 + -0.452418, + -7 + 0.0502203, + -1 + -0.715986, + 5 + -0.39207, + -1 + 0.00692897, + 1 + -0.305166, + -3 + -0.469096, + -1 + 0.214434, + -7 + 0.0882326, + -7 + -0.311931, + 7 + 0.289892, + 5 + 0.529032, + -3 + 0.543897, + -7 + 0.734108, + 5 + 0.760244, + 7 + -0.921361, + -7 + -0.499923, + 5 + 0.932586, + 3 + -0.492252, + -5 + 0.29961, + 3 + 0.40997, + 1 + 0.607012, + -1 + 0.0977883, + 7 + -0.666918, + 1 + 0.092606, + -3 + 0.48582, + -7 + -0.413194, + -1 + 0.657655, + 7 + -0.790176, + 3 + -0.79396, + 5 + -0.401432, + 3 + 0.241941, + -7 + -0.0372352, + 1 + -0.422785, + -7 + 0.412112, + 3 + -0.649941, + 5 + -0.885332, + -1 + 0.918587, + 5 + 0.580861, + 5 + -0.56943, + 7 + -0.313623, + 1 + 0.508329, + -7 + -0.311971, + -1 + 0.384163, + 7 + -0.407872, + 5 + 0.252608, + -5 + -0.748733, + 7 + -0.766854, + 7 + 0.963027, + 7 + 0.370056, + 7 + 0.91614, + 5 + -0.10655, + 5 + 0.114024, + 3 + 0.6354, + -3 + 0.526766, + -3 + 0.0656808, + -1 + 0.273656, + 3 + -0.518891, + 5 + 0.602608, + -3 + 0.14799, + -5 + -0.304276, + 5 + 0.282315, + -5 + 0.525241, + 3 + 0.917138, + 1 + -0.407829, + 1 + 0.148744, + 7 + 0.374387, + 1 + 0.719541, + 5 + -0.845279, + -7 + -0.271885, + -3 + 0.498453, + -3 + -0.108517, + 7 + -0.916167, + 1 + -0.00524844, + 3 + 0.230628, + 1 + 0.928817, + 5 + 0.961846, + 3 + -0.970376, + -5 + -0.991187, + 1 + -0.988078, + -3 + -0.321644, + 7 + 0.299365, + -1 + 0.260651, + -5 + 0.901838, + -7 + 0.905185, + -7 + -0.998068, + -1 + -0.717301, + 3 + -0.448447, + -5 + 0.853505, + 1 + 0.691012, + -5 + 0.858187, + -7 + 0.744305, + -1 + -0.546463, + -5 + 0.0513083, + -5 + 0.113148, + 1 + 0.753596, + -1 + 0.453985, + 1 + -0.558975, + -3 + -0.931769, + -7 + -0.421414, + -7 + -0.61578, + 3 + -0.601418, + -1 + 0.384031, + 1 + 0.180447, + -1 + 0.160505, + 7 + -0.14269, + 3 + 0.553436, + 3 + 0.842422, + -1 + -0.298941, + -3 + -0.704512, + 1 + -0.817883, + -5 + 0.689056, + 3 + 0.54275, + -7 + -0.244876, + -7 + 0.497505, + -3 + -0.385801, + -7 + -0.228079, + 1 + 0.607185, + 7 + -0.625709, + 5 + -0.851795, + -3 + 0.657661, + 7 + 0.568546, + 1 + -0.0359739, + 1 + 0.836243, + 1 + -0.747603, + -5 + 0.463366, + 7 + -0.62775, + -5 + -0.129517, + 7 + -0.0784853, + -5 + -0.338617, + 1 + -0.0951821, + -3 + -0.0586496, + 1 + 0.548171, + -5 + -0.142791, + 1 + -0.137619, + -5 + 0.86615, + 3 + 0.337578, + -7 + -0.0597365, + -5 + -0.843939, + -3 + -0.607342, + -1 + -0.630138, + -3 + -0.393534, + 7 + 0.354908, + -5 + 0.184251, + 5 + -0.154522, + -5 + 0.828516, + 5 + 0.817169, + -5 + 0.833938, + -5 + 0.689288, + 5 + -0.995259, + -1 + -0.932191, + -7 + 0.964076, + 1 + -0.85304, + -3 + -0.0782913, + 7 + -0.696813, + 5 + 0.231297, + 7 + 0.688421, + 7 + 0.0322752, + 1 + 0.839409, + 1 + -0.362455, + -3 + 0.561378, + 3 + -0.496498, + 1 + 0.841212, + -7 + -0.299443, + 7 + 0.527505, + -1 + 0.51827, + 5 + -0.348049, + -3 + -0.983604, + -1 + 0.694304, + 1 + -0.31786, + -3 + 0.643969, + -1 + -0.650723, + -7 + -0.14479, + -3 + 0.455813, + 7 + -0.627596, + -3 + -0.245695, + -5 + 0.0893783, + 3 + -0.236629, + 5 + -0.277597, + 7 + 0.481512, + -7 + 0.143052, + 3 + 0.615401, + 7 + -0.975698, + -1 + 0.50143, + -3 + 0.0737497, + 1 + 0.345961, + -1 + 0.944933, + -1 + 0.00710848, + 3 + -0.908855, + 3 + -0.104037, + -1 + -0.0996714, + -1 + 0.480154, + -5 + -0.684452, + -3 + -0.104955, + -1 + -0.972497, + 5 + 0.619405, + -5 + -0.361996, + 1 + -0.780079, + -7 + 0.443635, + 7 + 0.527956, + -1 + 0.927314, + 3 + 0.606136, + 3 + -0.22611, + 1 + -0.288871, + -3 + 0.683856, + 5 + 0.486252, + -7 + -0.781706, + 5 + 0.348522, + -7 + -0.743252, + 5 + 0.790582, + -1 + -0.417564, + 1 + 0.971814, + 1 + -0.394633, + 3 + -0.538042, + 7 + -0.82342, + -5 + 0.46215, + -3 + -0.725289, + -1 + -0.248699, + 3 + 0.194388, + -1 + 0.572686, + -1 + 0.57203, + -1 + -0.73258, + 3 + -0.841193, + 3 + 0.846292, + 7 + -0.106951, + -1 + -0.82125, + 5 + -0.565781, + -7 + -0.178221, + 3 + -0.396988, + -1 + -0.194377, + -7 + -0.184276, + 3 + 0.530178, + -1 + 0.0792818, + 3 + 0.698151, + 7 + 0.540132, + 5 + -0.0324876, + -5 + -0.539282, + 1 + -0.0612176, + 1 + -0.00825787, + -5 + -0.594088, + 5 + -0.720534, + -3 + -0.726017, + 3 + -0.247803, + -5 + -0.0351876, + -3 + -0.485217, + 7 + -0.711281, + 1 + -0.143779, + 5 + 0.830104, + -1 + -0.680937, + -5 + -0.406956, + -7 + -0.572693, + 1 + -0.916711, + -7 + -0.361021, + 5 + -0.669143, + -7 + 0.0977001, + -1 + -0.351618, + -3 + -0.292778, + -3 + 0.94385, + -5 + 0.64688, + -5 + 0.462901, + -7 + 0.139473, + 5 + -0.923586, + -7 + 0.100025, + 7 + 0.762592, + 5 + -0.669251, + -5 + 0.552417, + 3 + 0.578362, + -3 + 0.286511, + -5 + -0.819517, + 5 + -0.174663, + 1 + 0.898405, + -3 + 0.276757, + -5 + -0.860502, + -3 + -0.508774, + -7 + -0.619703, + -1 + -0.576515, + 7 + 0.442863, + 1 + -0.792524, + 1 + -0.967062, + -7 + 0.495375, + -7 + -0.497338, + -5 + -0.649645, + -1 + -0.692724, + -7 + -0.681675, + 5 + 0.80008, + -1 + -0.476369, + -3 + 0.102149, + -3 + -0.595665, + -5 + -0.961165, + 7 + -0.990363, + -5 + 0.716457, + -7 + -0.404208, + -1 + -0.483432, + 1 + 0.236347, + -1 + 0.376305, + 1 + -0.0533286, + -7 + -0.610223, + 3 + 0.843043, + -1 + -0.609047, + 1 + 0.725496, + -1 + -0.31617, + -5 + -0.0189003, + -3 + -0.425178, + -7 + -0.321938, + 3 + 0.0120751, + -1 + 0.315381, + -3 + -0.324733, + -3 + -0.571329, + 5 + -0.30955, + 3 + -0.997293, + 3 + 0.105692, + 1 + 0.0166829, + -7 + 0.295209, + -5 + 0.0396503, + -7 + -0.698527, + 1 + -0.983116, + 7 + 0.659054, + -1 + 0.33142, + -7 + -0.0377453, + -5 + -0.0574753, + -1 + 0.852526, + -1 + 0.983994, + -5 + 0.938022, + 1 + 0.513438, + 3 + 0.0546758, + -5 + 0.0823434, + -7 + 0.166195, + -3 + -0.852176, + 1 + 0.366113, + 1 + -0.397224, + -7 + 0.665549, + 1 + -0.0446258, + 3 + 0.702024, + 5 + -0.733169, + -1 + -0.0454769, + -7 + -0.668073, + 1 + 0.27592, + 7 + -0.323333, + 5 + -0.674522, + 7 + 0.0814798, + 7 + -0.782666, + 3 + -0.0710991, + 5 + 0.773968, + -1 + 0.803732, + -1 + 0.142462, + -3 + -0.243322, + -3 + -0.958958, + 5 + 0.308394, + 7 + -0.500096, + -7 + 0.914925, + 7 + 0.150591, + -5 + 0.58597, + 7 + 0.251341, + -3 + -0.636188, + 7 + 0.909046, + 3 + -0.577617, + -7 + -0.903661, + 7 + -0.275888, + 1 + -0.21705, + -5 + 0.736324, + -1 + -0.820161, + -1 + -0.545268, + 3 + -0.0618935, + 7 + -0.126791, + 1 + -0.792842, + -7 + -0.398747, + 3 + -0.583208, + -5 + -0.325178, + 7 + -0.0370357, + -5 + -0.083306, + 5 + 0.819585, + -7 + 0.0991425, + -3 + -0.130402, + -5 + -0.157376, + 7 + 0.691842, + 5 + -0.748137, + -1 + 0.758925, + 1 + -0.312916, + 3 + -0.820843, + 7 + -0.261816, + 7 + -0.172358, + 7 + 0.536986, + 7 + 0.759576, + 7 + -0.754446, + -7 + 0.567095, + -1 + -0.524981, + -3 + -0.802519, + -3 + 0.3109, + 3 + -0.248219, + 5 + 0.0748601, + 7 + 0.960564, + 1 + 0.667926, + -7 + -0.706296, + -3 + 0.635725, + 7 + 0.978146, + -1 + -0.574543, + 5 + -0.430696, + 1 + 0.0996064, + 1 + -0.00163434, + 3 + 0.14937, + 3 + -0.0844981, + 3 + -0.136261, + 5 + 0.973049, + 3 + 0.282247, + 7 + 0.579739, + 5 + -0.0823847, + 5 + -0.0467881, + 5 + 0.596636, + -1 + -0.297972, + -5 + 0.706257, + -7 + 0.604586, + -3 + 0.0669439, + -1 + -0.453354, + 5 + -0.477196, + 5 + 0.311931, + 5 + 0.166079, + 3 + 0.412152, + 7 + 0.474994, + 5 + -0.771076, + 5 + 0.536177, + -5 + -0.0305953, + -3 + 0.580228, + -3 + 0.284461, + -7 + -0.726361, + -3 + -0.726564, + 1 + -0.345421, + 3 + 0.80056, + 1 + 0.878273, + -5 + 0.654627, + -1 + 0.295187, + 7 + 0.591756, + 3 + 0.260911, + 3 + 0.481528, + -3 + -0.77778, + 3 + -0.683316, + -7 + -0.658198, + -3 + -0.74585, + 1 + 0.938157, + 1 + 0.192402, + 5 + 0.361699, + 3 + -0.163265, + -3 + 0.783476, + -5 + 0.737259, + 1 + -0.569672, + 7 + 0.10586, + -1 + -0.173976, + 1 + 0.935026, + -7 + 0.356488, + -1 + 0.0017309, + 5 + -0.675919, + -1 + 0.0665381, + -1 + -0.307875, + 7 + 0.0983045, + 5 + 0.963101, + 3 + -0.519587, + -5 + 0.899631, + 1 + 0.31666, + 7 + -0.756871, + 7 + 0.333545, + -3 + -0.168074, + 7 + 0.87813, + -1 + 0.779471, + -5 + 0.754198, + 7 + -0.868269, + 1 + 0.333521, + 7 + -0.731973, + -1 + 0.33527, + -3 + -0.467703, + -1 + 0.234056, + -3 + -0.237028, + 3 + 0.74204, + 7 + -0.257894, + -7 + 0.690854, + -1 + 0.652636, + 3 + 0.0301753, + -7 + 0.814373, + -1 + -0.951698, + -5 + 0.976247, + -3 + 0.431324, + -3 + 0.192437, + 3 + 0.31289, + -3 + 0.422132, + 3 + -0.00384281, + 3 + 0.72445, + -5 + 0.920278, + -3 + -0.324996, + 3 + 0.181187, + 7 + 0.658717, + -5 + -0.977313, + -1 + 0.378038, + 1 + 0.615551, + -1 + 0.475454, + 3 + 0.735309, + 7 + -0.398705, + 7 + 0.0674037, + -1 + 0.273941, + 5 + -0.376697, + 1 + -0.934663, + 3 + 0.764279, + -5 + -0.67983, + -5 + -0.951744, + -7 + 0.559239, + -7 + 0.123601, + -1 + 0.279154, + 7 + -0.349745, + -1 + 0.881504, + 5 + 0.743417, + -7 + -0.126299, + -3 + 0.129631, + -7 + -0.248369, + 3 + -0.582388, + 7 + 0.606937, + -1 + -0.766819, + -1 + -0.887898, + -3 + 0.628891, + -3 + 0.797051, + 1 + 0.258235, + 1 + -0.289372, + -7 + -0.689227, + -5 + -0.223412, + -5 + -0.0717334, + 5 + 0.444987, + 3 + -0.47443, + 5 + -0.622907, + 1 + 0.231064, + 7 + 0.0643792, + -5 + -0.545879, + -3 + 0.881704, + 7 + 0.421487, + 7 + -0.163227, + 1 + -0.19334, + 5 + 0.754454, + -7 + -0.173896, + -1 + -0.148776, + -5 + 0.342022, + -3 + 0.00779013, + 7 + -0.959293, + 5 + 0.888742, + 1 + -0.0373372, + 3 + 0.154647, + 7 + 0.522902, + -1 + -0.91692, + 1 + -0.762814, + 1 + -0.308587, + -5 + 0.252501, + 3 + 0.186752, + 7 + -0.897854, + 3 + -0.314141, + 7 + -0.123752, + 5 + -0.986531, + 7 + 0.89791, + 1 + -0.133572, + -7 + -0.828677, + -7 + -0.362269, + 1 + -0.231981, + 1 + 0.6903, + 5 + 0.212784, + -1 + 0.790468, + -7 + -0.822496, + 1 + -0.215268, + 5 + -0.232525, + -1 + -0.479589, + 3 + -0.79679, + -5 + -0.604188, + 7 + -0.201313, + -1 + -0.525663, + -7 + -0.155085, + 1 + -0.820419, + -3 + -0.37499, + -3 + -0.983146, + -5 + -0.793733, + -1 + -0.0931721, + 5 + -0.601751, + 3 + 0.0783009, + -1 + 0.768638, + 1 + 0.492399, + -5 + -0.0098969, + -1 + 0.19191, + -7 + -0.979377, + -7 + -0.0178371, + -5 + -0.329518, + 1 + 0.373382, + -7 + -0.845312, + 3 + -0.922893, + 3 + 0.315986, + 3 + 0.486665, + 1 + -0.263414, + -5 + 0.375741, + 3 + 0.909047, + 1 + -0.905982, + 1 + -0.887325, + 1 + -0.20989, + 5 + -0.476245, + 1 + -0.937806, + 3 + -0.749343, + 3 + -0.786876, + -3 + -0.67605, + -1 + 0.0446474, + -5 + 0.652167, + 1 + 0.543258, + -5 + 0.15279, + -5 + 0.148326, + 5 + 0.254656, + -3 + 0.856795, + -7 + 0.751831, + -3 + 0.630068, + 5 + 0.0417778, + -5 + -0.789099, + -7 + 0.741281, + -3 + 0.391712, + -3 + -0.134653, + -1 + 0.326939, + 7 + -0.0234458, + -3 + -0.23408, + -5 + -0.239154, + -5 + -0.832932, + 5 + -0.305414, + 7 + 0.447744, + -3 + -0.729455, + 7 + 0.48413, + 5 + 0.236162, + 5 + -0.534741, + 5 + 0.00340226, + -5 + -0.92795, + 5 + -0.802271, + 5 + -0.486955, + -3 + -0.958796, + 5 + -0.576444, + -1 + 0.107654, + -5 + -0.759059, + -5 + 0.292163, + 1 + -0.785662, + 3 + -0.374019, + 7 + -0.0159586, + -1 + 0.70116, + -5 + 0.0846993, + 1 + 0.401001, + 7 + 0.0279956, + -7 + -0.394888, + 5 + 0.505212, + 7 + 0.786975, + 3 + 0.532436, + -7 + 0.204459, + 3 + -0.615921, + -3 + 0.0758607, + -5 + 0.130031, + -5 + -0.772899, + 3 + -0.274121, + 5 + 0.056024, + -1 + -0.218418, + -7 + -0.183809, + -5 + 0.109609, + 5 + -0.821093, + 7 + -0.353014, + 3 + 0.228901, + 1 + -0.594237, + -3 + 0.39832, + -5 + 0.575415, + -1 + 0.398899, + -5 + -0.239754, + 3 + -0.535948, + 5 + -0.487767, + 5 + 0.282845, + 1 + -0.720766, + -7 + 0.678491, + -3 + 0.389419, + 5 + -0.862186, + 7 + -0.942864, + 7 + -0.341864, + 7 + -0.332763, + -7 + 0.290539, + -5 + -0.076314, + -3 + 0.14099, + 1 + -0.0547188, + 3 + 0.735025, + 3 + -0.197414, + 5 + 0.690544, + 5 + 0.630046, + -3 + -0.117688, + 7 + 0.656909, + 7 + 0.417193, + -3 + -0.489404, + -1 + 0.66448, + 3 + 0.109689, + 1 + -0.601325, + 5 + 0.930691, + 1 + 0.122041, + -3 + 0.991223, + -5 + -0.700354, + -1 + 0.0347951, + 7 + 0.122125, + 1 + 0.218395, + -7 + -0.177617, + 5 + 0.209456, + -5 + -0.976741, + -5 + -0.41843, + -3 + -0.580374, + -1 + -0.424389, + -5 + -0.183439, + 1 + 0.159905, + 1 + -0.825052, + -1 + -0.783269, + 3 + 0.150836, + -5 + 0.385557, + -1 + -0.657701, + -5 + 0.739214, + 7 + -0.990613, + -5 + 0.787245, + -5 + 0.604144, + -5 + -0.871588, + 5 + 0.721765, + 5 + 0.118939, + -5 + -0.859039, + -3 + 0.111408, + -1 + -0.479201, + 1 + -0.470303, + -1 + -0.136117, + 5 + 0.956995, + 1 + -0.39388, + -1 + 0.614385, + 1 + 0.556813, + 7 + 0.844387, + 1 + -0.436025, + -5 + -0.108634, + 5 + -0.100592, + -7 + -0.723946, + 1 + 0.0688398, + 7 + 0.180889, + -3 + 0.628736, + 1 + 0.112598, + 3 + 0.318029, + -3 + 0.634139, + 7 + -0.691032, + 1 + 0.356673, + 5 + 0.0566803, + 1 + -0.351812, + 5 + 0.531286, + -7 + -0.157417, + 7 + -0.99541, + 7 + -0.681986, + 5 + -0.997084, + -7 + 0.741155, + 1 + -0.622678, + 1 + 0.705248, + -5 + 0.711669, + 7 + 0.377357, + -5 + -0.62871, + -5 + 0.0214289, + -1 + -0.997903, + 5 + 0.0933239, + 3 + -0.526274, + -7 + -0.951203, + -1 + -0.755676, + 5 + 0.339232, + -1 + 0.773219, + -3 + 0.426269, + 3 + -0.396471, + 7 + 0.567064, + 5 + 0.633394, + -7 + 0.791714, + 3 + 0.787449, + 3 + -0.472383, + -5 + -0.155762, + -5 + -0.0783671, + -5 + -0.338965, + 3 + -0.793645, + -5 + 0.876857, + -5 + -0.02886, + -1 + 0.566931, + 5 + 0.623439, + 5 + 0.50836, + 7 + -0.3025, + 7 + -0.714796, + -7 + 0.179475, + 7 + -0.662018, + 1 + -0.348355, + 3 + -0.794334, + -3 + -0.157082, + 7 + 0.149085, + 1 + 0.640906, + -3 + 0.349559, + -3 + 0.857413, + -1 + -0.0283983, + -1 + 0.693171, + -3 + -0.214092, + -5 + -0.98936, + 1 + 0.639767, + 3 + -0.194655, + -5 + 0.940209, + -3 + 0.20604, + -3 + -0.564045, + 3 + -0.590761, + 5 + 0.685986, + 3 + -0.764822, + -1 + 0.42185, + -3 + -0.295677, + 1 + 0.216797, + 1 + -0.814246, + -1 + 0.206404, + -3 + 0.328757, + 7 + -0.566083, + 3 + 0.597134, + -3 + 0.642763, + -7 + -0.395769, + 7 + -0.935252, + -7 + 0.626113, + -3 + -0.849858, + 5 + 0.917923, + 5 + -0.376758, + 3 + 0.849631, + -5 + -0.327594, + -7 + -0.0529906, + -3 + -0.923709, + 1 + 0.0692206, + -5 + 0.056296, + 3 + 0.467438, + -1 + -0.814233, + -5 + -0.302013, + -3 + 0.695497, + 7 + 0.651437, + 3 + 0.168943, + 5 + 0.605341, + -1 + -0.372329, + 1 + 0.765342, + 1 + 0.947534, + -5 + 0.116956, + -3 + 0.577997, + 5 + 0.810715, + 1 + -0.779946, + -7 + -0.370998, + 3 + 0.558406, + -1 + -0.233575, + 1 + 0.77588, + -7 + -0.311882, + 5 + -0.910265, + 5 + -0.992932, + 5 + -0.760745, + 1 + 0.318678, + 5 + -0.210387, + 1 + 0.872963, + 3 + 0.220112, + -5 + -0.811578, + 5 + -0.711665, + 5 + -0.150111, + -1 + 0.641725, + 1 + 0.898414, + -3 + -0.650104, + 7 + -0.14629, + 7 + 0.865109, + -1 + -0.347701, + -1 + 0.921759, + 1 + 0.697452, + 1 + 0.0354798, + 5 + -0.176528, + -7 + 0.664795, + -3 + 0.896781, + 3 + -0.958731, + 5 + -0.141991, + 7 + 0.120368, + -5 + 0.485083, + 7 + -0.376901, + -5 + -0.43829, + -5 + -0.586847, + 1 + -0.959211, + 7 + 0.0708796, + -3 + 0.0492324, + -3 + -0.993246, + -1 + 0.650188, + -1 + -0.865149, + -5 + 0.37034, + 7 + -0.338674, + 3 + 0.623087, + -7 + -0.321175, + 7 + -0.764244, + -1 + 0.378604, + 1 + -0.812146, + 3 + 0.444655, + -5 + 0.253273, + 7 + 0.481744, + 3 + 0.455208, + 5 + 0.908443, + 1 + 0.0686094, + -7 + 0.844868, + -5 + -0.976591, + 7 + -0.72575, + 5 + 0.675135, + -7 + 0.274097, + -3 + 0.409609, + 3 + -0.175133, + -3 + 0.796693, + 3 + -0.247288, + -1 + -0.549564, + -7 + 0.967288, + -1 + -0.839667, + 3 + -0.681989, + -1 + -0.523145, + -5 + 0.396439, + 5 + -0.120618, + 3 + 0.693885, + -1 + -0.816144, + -5 + -0.968818, + -3 + -0.390704, + 3 + -0.448062, + 1 + 0.569756, + 5 + -0.336729, + -1 + 0.136729, + 5 + 0.941006, + 5 + -0.465103, + 7 + 0.468966, + -1 + 0.355103, + -7 + 0.615847, + -1 + -0.692941, + -1 + -0.173114, + 3 + 0.594599, + 7 + 0.557483, + 3 + 0.997697, + -5 + 0.24401, + 1 + -0.00963287, + 5 + 0.0275448, + 5 + 0.659747, + -7 + -0.567272, + -5 + -0.405348, + -1 + -0.614457, + 1 + 0.19472, + -7 + 0.553533, + -3 + -0.612328, + 1 + -0.348393, + -3 + 0.771169, + -3 + 0.354427, + -5 + 0.785281, + 3 + -0.318974, + -5 + -0.170041, + -1 + -0.667593, + -1 + -0.514524, + -5 + -0.76729, + 3 + 0.924267, + 7 + -0.893804, + -7 + -0.250356, + 7 + -0.732358, + -7 + 0.490774, + 1 + -0.437992, + -3 + 0.469562, + 1 + 0.436426, + -3 + -0.400156, + 7 + -0.860264, + 1 + 0.0900252, + -1 + -0.754367, + 1 + -0.838147, + -5 + 0.404529, + -7 + -0.437069, + -5 + -0.496662, + 5 + 0.952867, + -3 + 0.894237, + -3 + -0.555447, + -1 + -0.354976, + 1 + -0.60926, + -7 + 0.759444, + 3 + 0.662752, + -7 + -0.815089, + -5 + 0.98253, + 3 + -0.817391, + 5 + -0.61243, + -5 + -0.456923, + -1 + -0.824931, + 7 + 0.514605, + -1 + 0.828664, + -5 + -0.195044, + -3 + -0.333318, + 3 + 0.164695, + -7 + 0.0349422, + 7 + 0.118845, + 5 + -0.174882, + 7 + -0.872202, + 7 + 0.710986, + 3 + 0.699916, + -5 + 0.066256, + 3 + -0.148756, + 7 + 0.508584, + 5 + 0.825367, + -5 + -0.729841, + -5 + -0.887612, + 5 + -0.758424, + -5 + 0.998181, + -7 + 0.65577, + 5 + -0.474471, + 7 + -0.269234, + 3 + 0.104569, + -5 + -0.102212, + -5 + 0.738547, + 5 + -0.94242, + -1 + 0.15571, + 7 + -0.421775, + -7 + 0.804305, + 3 + 0.770802, + 7 + 0.642568, + -7 + 0.971034, + 1 + -0.144741, + -7 + 0.902049, + 7 + 0.157032, + 7 + -0.710021, + 7 + 0.719006, + 1 + -0.119823, + -7 + 0.156298, + 3 + 0.970851, + -1 + -0.163907, + -7 + -0.353286, + -7 + 0.497258, + -7 + 0.283671, + 1 + 0.0405689, + -5 + -0.962454, + -3 + -0.219818, + 1 + -0.436599, + -3 + -0.651331, + 5 + 0.192501, + -5 + 0.627465, + 3 + -0.0387857, + -5 + 0.235464, + 3 + -0.0781319, + -1 + 0.372664, + -7 + 0.144817, + -3 + -0.981248, + -7 + -0.438408, + 5 + 0.851478, + -1 + -0.473764, + 1 + 0.00188464, + 3 + 0.433134, + -7 + -0.132385, + 7 + -0.0645663, + -1 + -0.202906, + -7 + -0.19273, + -5 + 0.490564, + 5 + -0.986688, + 3 + -0.259055, + -5 + -0.0975989, + -1 + -0.599443, + -1 + 0.313751, + -3 + 0.839625, + -3 + 0.0875769, + 7 + 0.531778, + 5 + 0.78374, + -7 + -0.568377, + -5 + -0.772801, + -5 + -0.0559519, + -5 + 0.945151, + -7 + 0.260123, + -7 + -0.909106, + -5 + 0.0617756, + -3 + -0.0675705, + 3 + 0.425518, + -3 + 0.0981296, + -1 + -0.137702, + 5 + 0.353555, + 7 + 0.895279, + -7 + 0.247132, + -1 + 0.346749, + -3 + 0.748198, + -5 + 0.584672, + 3 + -0.731422, + 3 + 0.0579248, + 5 + 0.212579, + 5 + 0.1419, + -1 + -0.51401, + 1 + -0.844899, + -1 + -0.478985, + -5 + 0.918879, + 3 + -0.0802303, + 5 + 0.995209, + 1 + 0.228169, + -3 + 0.580333, + -3 + -0.866062, + 7 + -0.978268, + -5 + 0.501526, + -7 + 0.334392, + -1 + 0.442487, + -5 + 0.0704108, + -5 + -0.711541, + -5 + 0.982968, + -7 + 0.722414, + 5 + -0.799889, + 1 + -0.853645, + -7 + 0.997917, + 5 + -0.513696, + 5 + 0.0364606, + 5 + -0.248071, + -7 + -0.387232, + 1 + -0.811699, + 1 + 0.732048, + 3 + -0.679307, + -1 + -0.978209, + -1 + -0.964028, + -5 + -0.611812, + -7 + -0.902063, + -3 + 0.398009, + 3 + 0.00542146, + 5 + 0.601782, + 5 + -0.104203, + 1 + 0.506752, + -5 + 0.436524, + 7 + 0.982469, + -1 + -0.0633421, + -7 + 0.446072, + -1 + 0.927761, + 1 + 0.658156, + -7 + 0.785148, + -1 + -0.591183, + -3 + 0.0137029, + -1 + -0.388246, + 7 + -0.675978, + 1 + 0.0143937, + -7 + 0.690042, + -5 + -0.693171, + -7 + -0.352858, + 3 + -0.970363, + -7 + -0.723423, + 3 + 0.724452, + -3 + 0.158585, + 7 + -0.175004, + 1 + -0.19285, + -1 + 0.992788, + 3 + -0.851952, + 5 + 0.81, + 3 + -0.0435364, + -1 + -0.0813053, + -1 + -0.765415, + -7 + -0.0372974, + -1 + 0.694064, + 1 + -0.136753, + 3 + 0.826244, + -7 + 0.140024, + 5 + -0.0882701, + 1 + 0.295136, + 7 + -0.5227, + -5 + -0.237363, + -3 + 0.709084, + -3 + 0.629578, + -5 + 0.643857, + 7 + -0.668263, + -5 + 0.249376, + -1 + -0.760648, + 1 + -0.927984, + 7 + -0.659877, + 7 + -0.567002, + -1 + 0.0565217, + -3 + 0.805679, + -3 + -0.528236, + -7 + -0.13752, + -3 + 0.887507, + 7 + 0.63262, + 3 + -0.119278, + 3 + 0.890306, + -1 + -0.274285, + -1 + 0.369489, + 7 + 0.0317755, + 3 + -0.856605, + 7 + 0.912634, + -7 + 0.0492215, + 1 + -0.276292, + -7 + -0.177337, + 3 + -0.787517, + -3 + -0.53, + -1 + -0.186417, + 3 + -0.949098, + -7 + -0.517213, + -1 + -0.986841, + 5 + 0.600896, + 7 + 0.48168, + -3 + -0.458465, + 5 + 0.321443, + -3 + -0.234238, + 1 + -0.954936, + 5 + -0.0275234, + -7 + 0.924262, + 1 + 0.977532, + -5 + -0.669258, + 3 + 0.364021, + 1 + 0.135028, + -3 + -0.473695, + -7 + -0.185051, + -7 + -0.232574, + 3 + -0.944187, + 3 + -0.0543526, + 5 + 0.673031, + 5 + 0.195805, + 1 + -0.45507, + 7 + 0.404971, + 3 + -0.610784, + 5 + 0.0659073, + -1 + -0.207704, + 7 + 0.644995, + -1 + 0.121214, + -3 + -0.483027, + -7 + 0.711033, + 5 + -0.673219, + -1 + -0.895776, + 3 + 0.951024, + -3 + 0.56215, + 3 + -0.329154, + -5 + -0.577541, + -7 + -0.309147, + -1 + -0.511309, + 7 + 0.499812, + -5 + -0.681876, + -1 + -0.801156, + 7 + 0.151605, + -3 + 0.241685, + 7 + 0.992835, + -3 + 0.982038, + -5 + 0.0631867, + -5 + 0.950436, + 7 + 0.31088, + 5 + -0.708879, + -7 + 0.460315, + 1 + 0.397522, + 3 + -0.830289, + -1 + -0.146992, + 3 + 0.667571, + -5 + 0.870575, + 5 + -0.692335, + 1 + -0.399896, + -7 + -0.421033, + 7 + -0.740574, + -3 + 0.0441913, + -5 + 0.000759854, + -1 + -0.526559, + 7 + -0.50311, + 3 + -0.00944866, + -7 + 0.250031, + -5 + 0.579793, + -3 + 0.554107, + 5 + 0.737397, + 1 + 0.434328, + -5 + -0.698991, + -7 + 0.0322755, + 5 + -0.995791, + -7 + 0.233862, + 3 + -0.201264, + 7 + -0.297969, + -5 + 0.377501, + 3 + -0.571389, + -1 + 0.530284, + 5 + -0.179379, + 7 + -0.356844, + -7 + 0.941165, + 1 + 0.339271, + 3 + -0.66842, + -5 + -0.423012, + 3 + 0.316588, + -1 + -0.984114, + 1 + -0.5428, + -1 + 0.766658, + 1 + -0.960606, + 5 + -0.620487, + 7 + 0.266202, + 7 + 0.901102, + 1 + -0.268669, + -5 + -0.607472, + -7 + -0.52709, + -3 + 0.0705389, + 1 + -0.608374, + -3 + -0.288577, + -5 + 0.843351, + -3 + 0.612135, + -5 + 0.230486, + 5 + -0.244291, + -1 + 0.576229, + -3 + 0.446377, + -3 + -0.106511, + -3 + 0.889909, + -5 + -0.918941, + 1 + 0.848997, + -5 + 0.10993, + -3 + 0.256356, + 1 + 0.504098, + 5 + -0.170462, + 1 + 0.835316, + 7 + 0.644516, + -7 + 0.90372, + -7 + 0.463742, + -5 + 0.349377, + -7 + -0.553437, + 1 + 0.330349, + 5 + 0.710921, + -3 + 0.654504, + -5 + -0.447801, + -5 + 0.0517276, + -1 + 0.975718, + 3 + 0.874352, + -1 + 0.678769, + -1 + -0.264881, + -3 + -0.0680661, + 1 + -0.824504, + -7 + -0.0992408, + -5 + -0.862084, + 3 + -0.805812, + 5 + 0.237566, + -3 + 0.888929, + 1 + -0.476846, + -1 + 0.621217, + 1 + 0.65046, + 1 + -0.177248, + -1 + 0.0533044, + 3 + -0.176522, + -1 + 0.676266, + 5 + 0.0818662, + 5 + -0.0801649, + 5 + -0.430938, + 3 + -0.763183, + -7 + -0.453813, + 3 + 0.555379, + -3 + 0.858594, + 3 + 0.227172, + -1 + -0.632746, + -7 + 0.627382, + 1 + -0.0489046, + 7 + -0.828429, + 3 + 0.555978, + -7 + -0.130752, + 1 + 0.978551, + 1 + 0.985192, + -3 + -0.601231, + -3 + 0.3876, + 1 + 0.907771, + -3 + -0.183183, + -5 + -0.297217, + -5 + 0.579173, + -5 + 0.751301, + 5 + 0.675477, + -7 + -0.700691, + 1 + 0.947316, + -7 + -0.635739, + -1 + -0.1091, + -5 + -0.655627, + -7 + -0.74121, + 1 + 0.334598, + 5 + -0.133385, + -5 + 0.364959, + 5 + -0.692856, + -7 + -0.432334, + -3 + 0.0911902, + -5 + 0.670209, + -7 + -0.0777559, + -3 + 0.769741, + 7 + 0.0235715, + 1 + 0.181115, + -7 + -0.688748, + -7 + -0.641734, + -1 + 0.972104, + 7 + -0.474228, + -7 + -0.984007, + 3 + 0.25339, + 3 + 0.87889, + 5 + 0.624509, + 5 + -0.896409, + 7 + -0.146804, + 5 + 0.79753, + -1 + 0.0419583, + -3 + -0.978575, + 5 + -0.799147, + 7 + -0.100029, + 5 + 0.34877, + 5 + 0.726533, + -3 + 0.902539, + -7 + -0.0300989, + 5 + 0.843366, + 7 + 0.98872, + 7 + -0.428589, + 1 + 0.644193, + -5 + 0.0228081, + 7 + -0.754224, + 7 + 0.805301, + 5 + 0.695254, + -7 + -0.188701, + 3 + -0.581044, + 5 + 0.799149, + 7 + 0.353339, + -1 + -0.9622, + -1 + -0.230887, + 5 + -0.787056, + -7 + -0.706222, + 3 + 0.0197935, + -1 + 0.805143, + 7 + 0.951379, + 5 + -0.333186, + -3 + -0.0693998, + -3 + 0.993613, + -5 + -0.548791, + -5 + -0.964111, + 3 + -0.584394, + 1 + 0.867385, + -7 + -0.480054, + 1 + -0.994699, + 7 + 0.090273, + -3 + 0.901709, + 1 + 0.715806, + 3 + 0.304813, + 7 + 0.403796, + 1 + -0.473723, + 5 + 0.475125, + -1 + 0.0271961, + 7 + -0.487227, + 7 + 0.229468, + -3 + -0.189796, + -3 + -0.625003, + 1 + -0.401116, + -7 + 0.67123, + -5 + -0.927091, + -7 + 0.270972, + 7 + -0.617139, + 1 + -0.91671, + -7 + -0.712691, + -3 + -0.840406, + 5 + -0.406998, + -1 + -0.849947, + 3 + -0.158653, + -1 + 0.0696663, + -1 + 0.758415, + 1 + 0.0694559, + 1 + 0.462296, + -5 + 0.217909, + 1 + 0.473663, + -3 + 0.473242, + -3 + -0.890317, + -3 + -0.397198, + -7 + -0.508332, + 5 + 0.990104, + 5 + -0.32464, + -1 + -0.869012, + 7 + 0.567209, + 1 + -0.495974, + 3 + -0.101183, + -7 + -0.74694, + -5 + -0.675854, + -1 + 0.110992, + -5 + 0.247456, + 7 + 0.840274, + -3 + 0.395728, + 5 + -0.362192, + -3 + -0.680363, + 5 + -0.602484, + -3 + 0.738772, + 1 + -0.644167, + -3 + 0.634913, + 3 + -0.384876, + 5 + -0.916855, + -5 + -0.227988, + -3 + -0.625356, + -5 + -0.740278, + -1 + -0.41118, + 3 + 0.443345, + 3 + 0.736942, + 1 + -0.354426, + -7 + -0.870946, + -3 + -0.546137, + -7 + 0.272889, + 1 + 0.0801028, + 5 + -0.274639, + -5 + -0.154875, + -3 + -0.580005, + -5 + -0.398665, + 3 + -0.385197, + 5 + -0.285359, + 1 + 0.362706, + -7 + -0.855772, + -7 + 0.0454971, + -5 + -0.424857, + -7 + -0.504577, + -5 + -0.00591926, + -5 + 0.149346, + 3 + -0.328489, + 7 + 0.015029, + 7 + 0.747577, + -5 + -0.714686, + 1 + -0.101717, + 3 + 0.656319, + 1 + 0.5271, + -7 + -0.64961, + -7 + -0.359428, + -3 + -0.298523, + -3 + -0.0788614, + 1 + 0.621573, + -1 + 0.0175043, + 3 + -0.579268, + 5 + 0.710546, + 7 + -0.511833, + 5 + 0.162637, + -7 + -0.226472, + 1 + 0.0095225, + 5 + 0.21144, + -5 + -0.582375, + 7 + 0.231257, + 1 + 0.248058, + -1 + 0.922646, + 5 + 0.00967738, + 7 + -0.00782117, + 1 + 0.930862, + 1 + 0.920455, + 7 + -0.994076, + -5 + -0.462763, + 1 + 0.627409, + 3 + 0.936991, + -7 + 0.800793, + -1 + 0.193107, + -7 + 0.703299, + -1 + 0.132479, + 1 + -0.152733, + 5 + -0.953622, + -7 + -0.997253, + 7 + 0.556477, + 3 + 0.272056, + -3 + -0.51489, + 5 + 0.398802, + 5 + 0.602265, + -5 + 0.274229, + -7 + -0.700344, + -7 + 0.0901991, + 5 + 0.0552389, + -7 + -0.536972, + -7 + -0.0797897, + 5 + 0.291342, + 3 + -0.846983, + 3 + 0.700542, + -7 + 0.192372, + 7 + -0.362972, + 5 + 0.180049, + -3 + 0.792655, + 7 + -0.662956, + 5 + -0.142891, + -3 + 0.244501, + -3 + -0.510171, + -3 + 0.321085, + -1 + 0.664982, + 7 + -0.905902, + -5 + 0.966882, + -7 + 0.735439, + 3 + 0.261407, + 3 + 0.963571, + -7 + -0.475502, + 7 + 0.78978, + 7 + 0.365208, + 3 + 0.820723, + 3 + -0.594815, + -1 + -0.942558, + -1 + -0.304459, + -3 + 0.391556, + -1 + -0.795303, + -7 + 0.136453, + -5 + -0.955505, + 1 + -0.534127, + 5 + -0.981382, + -3 + 0.557188, + -5 + -0.118641, + -3 + -0.621408, + -7 + -0.74375, + 7 + 0.0227463, + 5 + 0.112073, + -3 + 0.950711, + 5 + 0.643199, + 5 + -0.351889, + -1 + -0.221595, + -1 + 0.00700172, + 7 + 0.928086, + 5 + 0.0356548, + 3 + -0.370036, + -7 + -0.830755, + -5 + -0.222917, + 1 + -0.782772, + 1 + 0.237148, + -1 + 0.86974, + 5 + -0.537617, + -1 + -0.434889, + -7 + -0.0111739, + 7 + -0.715952, + 3 + -0.40804, + 3 + -0.360795, + 3 + 0.653046, + -3 + 0.706949, + 5 + -0.554727, + -1 + 0.183029, + -7 + -0.239732, + -5 + -0.658072, + 7 + -0.752212, + -5 + 0.293207, + 7 + -0.34722, + -7 + -0.326367, + -5 + -0.0589863, + 5 + -0.927616, + -1 + -0.866135, + 3 + 0.00235856, + -3 + -0.0437649, + -5 + -0.585851, + 1 + -0.481841, + -5 + 0.632601, + 3 + -0.874934, + -1 + -0.230124, + -5 + 0.403241, + -5 + -0.986698, + -1 + 0.968435, + -3 + -0.530127, + 1 + 0.919559, + -7 + 0.425743, + 7 + 0.123378, + 7 + -0.142707, + -7 + -0.494815, + 7 + 0.440976, + -5 + 0.890096, + -3 + -0.708126, + 7 + 0.943091, + -7 + -0.0667361, + 1 + 0.417654, + 7 + 0.25984, + -1 + 0.846645, + 3 + -0.416033, + -1 + -0.149707, + 1 + 0.889424, + 5 + 0.866725, + -3 + 0.625568, + -1 + -0.376365, + -7 + 0.362419, + -7 + 0.212156, + -1 + 0.898672, + 3 + -0.684527, + 3 + 0.350536, + -5 + -0.10858, + -7 + 0.363887, + 1 + 0.431342, + 7 + -0.426099, + -1 + -0.0357183, + 5 + 0.969688, + -7 + 0.436647, + 1 + 0.144824, + 7 + -0.689202, + -5 + -0.369132, + -7 + 0.447801, + 3 + 0.991838, + -5 + -0.95315, + -5 + -0.486236, + 7 + 0.635678, + 7 + -0.672488, + -5 + -0.134572, + -5 + -0.698523, + 3 + 0.0914014, + 5 + 0.826151, + 7 + 0.179363, + 3 + 0.905552, + 3 + 0.460779, + 3 + -0.195297, + -5 + 0.965511, + 1 + -0.98716, + 7 + 0.142015, + -7 + -0.156042, + 7 + 0.338355, + -3 + 0.630815, + -7 + -0.716086, + -5 + 0.30445, + -3 + -0.0663283, + -1 + 0.954605, + -7 + -0.516684, + -1 + 0.739518, + -5 + 0.0926331, + -1 + -0.964479, + -3 + 0.738004, + -1 + -0.0623072, + -3 + 0.994729, + -7 + -0.483703, + -5 + -0.116232, + -3 + 0.608111, + 5 + -0.169533, + 1 + 0.700974, + 7 + 0.344404, + 1 + -0.234486, + -5 + 0.753821, + 3 + 0.264031, + 1 + 0.365123, + -1 + 0.735946, + -3 + 0.075701, + 5 + 0.0457206, + -3 + 0.594172, + 1 + 0.144428, + 3 + -0.945545, + 7 + -0.49231, + -1 + 0.196516, + 7 + 0.397096, + -1 + 0.68979, + 3 + -0.283773, + -7 + -0.891651, + -7 + 0.0992016, + 3 + 0.364927, + 3 + 0.692215, + 1 + 0.902593, + -7 + 0.511356, + 1 + -0.329667, + 3 + 0.151807, + -3 + -0.469367, + -1 + 0.839886, + -3 + 0.990307, + 3 + 0.318869, + 5 + -0.74034, + -5 + -0.339204, + 1 + -0.452787, + 1 + -0.736788, + 1 + -0.248248, + 5 + 0.785201, + 7 + -0.243082, + 7 + -0.107551, + 1 + -0.729608, + -3 + -0.358678, + 1 + -0.786071, + -1 + 0.370913, + 3 + -0.398804, + 1 + 0.0692376, + -1 + -0.103113, + -1 + 0.153375, + 5 + 0.548651, + -1 + -0.306503, + 3 + -0.96292, + 5 + -0.221047, + 5 + 0.567843, + 5 + 0.41284, + 5 + 0.88284, + 1 + -0.629206, + -3 + -0.494796, + 3 + 0.424972, + 7 + 0.365256, + -5 + -0.739219, + 3 + 0.640667, + -5 + 0.633005, + -1 + 0.759701, + 5 + -0.0691017, + -5 + -0.0647394, + -5 + -0.348828, + -5 + 0.665346, + -1 + -0.135857, + 5 + 0.437672, + 5 + 0.381016, + -3 + -0.842788, + -1 + -0.85829, + -7 + 0.19863, + -5 + -0.877027, + 5 + -0.776832, + 3 + -0.591161, + 1 + 0.272311, + 1 + 0.729332, + -7 + -0.085479, + -1 + 0.867551, + -1 + 0.850484, + -7 + 0.688455, + -7 + 0.657501, + 1 + -0.781022, + 7 + -0.853813, + -5 + 0.963325, + 5 + -0.61377, + 1 + -0.946282, + -1 + -0.398061, + 7 + -0.618336, + -5 + 0.210241, + -7 + 0.245468, + 3 + -0.503244, + -7 + -0.991443, + -7 + -0.832428, + 3 + 0.633537, + 3 + -0.0513143, + -5 + -0.740331, + -5 + -0.571087, + -5 + 0.932409, + -1 + 0.310949, + 7 + 0.803959, + 1 + -0.37293, + 3 + 0.625741, + 3 + 0.335055, + -3 + -0.0665732, + -7 + -0.546747, + -3 + -0.824097, + 3 + 0.185571, + -5 + -0.963157, + 1 + -0.575186, + 5 + -0.380057, + -3 + -0.0146486, + -7 + 0.548562, + 7 + -0.294831, + 1 + 0.190966, + 3 + -0.200531, + 3 + 0.769514, + 1 + -0.758442, + 5 + -0.563297, + 3 + -0.268245, + 7 + 0.115331, + 7 + 0.635215, + 1 + -0.393521, + 1 + -0.618453, + -5 + 0.766947, + -5 + -0.89702, + 3 + -0.290726, + -1 + -0.146228, + -7 + -0.671038, + 1 + -0.598244, + 3 + -0.56863, + 7 + -0.501319, + -7 + 0.627518, + 3 + -0.389303, + -3 + 0.0746856, + 5 + -0.0666037, + 5 + -0.275337, + -5 + 0.132165, + 5 + -0.379456, + -3 + -0.232648, + -1 + -0.722393, + -3 + -0.848371, + -3 + -0.894514, + -3 + -0.52825, + -1 + 0.868408, + 5 + 0.305525, + -5 + -0.274425, + -5 + 0.22874, + 5 + 0.71816, + -1 + -0.744417, + -3 + 0.874223, + 1 + -0.0454682, + 3 + 0.998097, + -5 + 0.393407, + 5 + 0.187479, + 1 + 0.85875, + 3 + -0.930842, + 7 + -0.683711, + 3 + -0.625096, + 7 + -0.363623, + -3 + -0.478099, + 5 + 0.0397175, + -1 + 0.772844, + 1 + 0.0351828, + -5 + -0.450596, + 5 + -0.747949, + -1 + -0.901913, + 1 + -0.396489, + 7 + 0.266602, + -3 + -0.144345, + -7 + 0.357022, + -1 + 0.17734, + 3 + -0.490206, + 5 + -0.0589478, + -1 + 0.0215372, + -7 + 0.626992, + 3 + 0.805443, + 5 + -0.774861, + 7 + 0.548483, + -7 + -0.659366, + 5 + -0.399126, + 5 + 0.280639, + -1 + 0.382537, + 5 + 0.253533, + -3 + 0.484453, + -1 + -0.182041, + -7 + 0.403929, + 5 + 0.799799, + -1 + 0.872509, + -1 + 0.446505, + 1 + 0.072863, + 1 + 0.511757, + 5 + -0.0447141, + 7 + 0.418114, + 3 + -0.412815, + -7 + 0.270519, + 1 + -0.691355, + 3 + -0.197421, + 3 + -0.86134, + -5 + -0.0102158, + 1 + 0.35777, + 3 + 0.447566, + -1 + 0.0185418, + -7 + 0.78905, + 7 + 0.691196, + -5 + -0.980607, + 3 + 0.307422, + 1 + 0.612522, + 5 + -0.199466, + -1 + -0.459671, + 1 + 0.170203, + 5 + 0.345741, + -1 + 0.442178, + -5 + 0.431563, + 3 + -0.534043, + 5 + -0.76423, + 3 + 0.121284, + 3 + 0.645713, + 7 + 0.96808, + -7 + 0.488072, + 3 + -0.00669708, + 1 + -0.971889, + -1 + -0.315525, + 5 + 0.541525, + 3 + -0.787017, + -1 + 0.544075, + 3 + -0.0730717, + -5 + 0.522401, + -5 + -0.323174, + 7 + 0.526918, + 5 + -0.385761, + 5 + -0.895487, + -3 + 0.0897052, + -5 + -0.670281, + -5 + -0.182219, + -5 + 0.303178, + -5 + -0.947146, + -3 + -0.721791, + -5 + -0.626817, + 1 + -0.583032, + 3 + 0.641241, + -7 + -0.520007, + 1 + -0.425207, + -5 + 0.0712658, + 1 + 0.812682, + 1 + -0.143148, + 3 + 0.0762144, + 1 + 0.0785892, + 7 + -0.568785, + 1 + -0.59096, + 3 + 0.756584, + -1 + 0.128497, + 3 + -0.975302, + -1 + -0.757146, + 5 + 0.448678, + -7 + 0.00292395, + -3 + -0.0190117, + 7 + -0.211027, + -1 + -0.668733, + -5 + -0.447823, + 1 + -0.502645, + -7 + 0.47152, + -5 + -0.364533, + 7 + 0.745433, + -5 + 0.753726, + -1 + -0.307681, + -1 + 0.791775, + -5 + -0.151863, + -5 + 0.815651, + 7 + -0.0787568, + 1 + 0.901984, + 1 + 0.446558, + -5 + 0.035328, + 5 + -0.461488, + -5 + 0.702664, + 1 + 0.477797, + -1 + -0.0921929, + -3 + -0.231008, + 7 + 0.369765, + -7 + 0.0220315, + 5 + -0.0497525, + -7 + -0.0740606, + -1 + 0.885344, + 3 + 0.332343, + -3 + 0.220104, + -1 + 0.384649, + -5 + -0.196536, + -1 + 0.442901, + 5 + 0.226845, + -7 + 0.378706, + -7 + 0.165296, + 3 + 0.201761, + 1 + -0.666372, + -1 + -0.0523257, + 3 + 0.636851, + 5 + -0.717434, + 1 + -0.354993, + 3 + -0.720888, + -5 + -0.133448, + -5 + -0.12999, + 5 + -0.64646, + 1 + 0.66513, + 7 + 0.38796, + -3 + 0.983196, + 1 + 0.156689, + -1 + -0.598867, + 7 + 0.0891009, + -3 + 0.564803, + 5 + 0.647083, + 3 + 0.28552, + -5 + -0.550295, + 7 + -0.535946, + 3 + -0.323109, + 1 + 0.968116, + -5 + 0.670887, + 5 + 0.723851, + -7 + 0.14941, + 1 + 0.751713, + -3 + 0.379236, + -5 + 0.339108, + -5 + -0.301987, + 3 + -0.683341, + -5 + -0.359829, + 5 + -0.84713, + -3 + 0.304565, + -3 + 0.861481, + 7 + -0.877059, + -5 + 0.289428, + -7 + -0.434084, + -1 + -0.481805, + -3 + 0.932735, + -3 + -0.309733, + -3 + -0.656653, + -1 + 0.858222, + -5 + -0.945002, + -3 + -0.379574, + 1 + -0.329053, + -5 + -0.965912, + -7 + -0.0862743, + -3 + 0.564742, + 1 + 0.430712, + 7 + -0.134825, + 3 + -0.0142276, + -3 + 0.461407, + -3 + 0.237931, + 5 + 0.189721, + -5 + -0.164975, + 3 + 0.158177, + 5 + 0.761349, + 5 + -0.603701, + -1 + 0.343416, + -7 + 0.479708, + 5 + -0.54804, + 5 + 0.0522417, + -7 + -0.975275, + 3 + 0.908053, + 7 + -0.324028, + 1 + 0.20481, + -1 + 0.501097, + -3 + -0.562607, + -5 + 0.555231, + 1 + -0.158267, + 3 + -0.0687857, + 1 + 0.511831, + -5 + -0.607408, + 1 + 0.360143, + -1 + 0.437194, + -3 + -0.092719, + 7 + 0.66663, + -7 + 0.610324, + 1 + 0.477642, + -3 + -0.690053, + 5 + -0.239834, + 5 + 0.430824, + -1 + -0.74709, + -7 + 0.666542, + -3 + 0.787307, + 5 + 0.12119, + -5 + 0.468506, + -7 + -0.655536, + -3 + -0.362963, + -7 + -0.444575, + -5 + -0.813438, + 3 + -0.658917, + -7 + -0.846612, + -5 + 0.47478, + 1 + -0.486082, + -7 + 0.325601, + -3 + 0.10135, + 3 + 0.616988, + -5 + 0.030061, + 1 + 0.546106, + -3 + -0.107568, + 1 + -0.526698, + 1 + -0.402568, + 1 + 0.476488, + 5 + -0.876816, + -7 + -0.814004, + -5 + -0.742022, + 1 + 0.396799, + 3 + 0.302924, + 5 + -0.330856, + 3 + -0.20346, + 1 + -0.0134361, + 3 + 0.603609, + 5 + -0.531407, + 7 + 0.711484, + -1 + 0.520469, + -1 + 0.148813, + 3 + 0.0432309, + 1 + 0.669779, + 1 + -0.428549, + -3 + 0.260938, + -3 + 0.941317, + -5 + -0.780941, + -3 + -0.747831, + 1 + -0.998692, + -5 + 0.892504, + -1 + 0.62686, + 7 + 0.940684, + -1 + -0.157277, + -3 + -0.215904, + 3 + -0.149222, + -3 + -0.876603, + -7 + -0.20916, + 3 + -0.984649, + 7 + -0.60173, + -1 + -0.806134, + -1 + 0.209397, + 1 + 0.310198, + 5 + -0.348507, + -3 + 0.966827, + 1 + -0.781644, + -3 + -0.417686, + 1 + -0.618801, + 7 + 0.862017, + -3 + -0.405402, + -7 + 0.125069, + -7 + 0.815787, + -5 + 0.135567, + -5 + 0.652664, + -5 + 0.509215, + -3 + -0.247757, + -3 + -0.697007, + 7 + -0.760593, + 3 + -0.772638, + -5 + 0.870941, + -1 + 0.864873, + -1 + -0.695855, + 3 + -0.952328, + 7 + -0.984213, + -5 + -0.825547, + 7 + -0.937066, + 1 + -0.030252, + 7 + -0.370309, + -1 + 0.976445, + -1 + 0.105839, + -7 + -0.151788, + 5 + 0.329837, + 5 + 0.484323, + 3 + -0.185114, + 1 + -0.450171, + 7 + -0.174316, + 7 + -0.840168, + -3 + -0.188744, + 7 + 0.4487, + -5 + 0.0857224, + 7 + 0.836002, + -3 + -0.180574, + 7 + 0.933189, + -3 + 0.850465, + -3 + 0.217683, + 7 + -0.504985, + 3 + -0.244207, + -3 + 0.827852, + -3 + 0.231895, + -3 + -0.210397, + -5 + 0.225256, + -5 + -0.424323, + -3 + 0.584223, + 5 + -0.21417, + 7 + 0.0492111, + -5 + 0.717212, + 3 + 0.127463, + 5 + -0.412335, + -3 + -0.235105, + 1 + -0.142685, + 5 + -0.499895, + 3 + -0.081105, + -5 + -0.145618, + 7 + -0.823428, + 5 + -0.860577, + 3 + -0.433851, + 1 + -0.917788, + 1 + 0.0316082, + -7 + 0.825787, + -7 + -0.453454, + -7 + 0.00504467, + -3 + 0.495271, + 3 + 0.0318126, + 5 + -0.344928, + -1 + -0.550629, + -7 + -0.352606, + -1 + -0.122732, + -3 + 0.159171, + 3 + 0.261004, + 3 + -0.691171, + 3 + -0.746879, + 1 + 0.626657, + -3 + 0.0388675, + -1 + 0.51117, + 5 + -0.673213, + -3 + 0.864677, + -7 + -0.726019, + 7 + -0.729394, + -5 + 0.330155, + -7 + -0.0177368, + -7 + -0.300845, + 1 + 0.615713, + 5 + 0.00178831, + 1 + 0.0232089, + 7 + 0.0501066, + -5 + -0.620755, + 1 + -0.446627, + -1 + -0.417687, + 7 + 0.871591, + 7 + -0.750383, + 7 + 0.402812, + 1 + -0.147176, + -5 + 0.443187, + 3 + 0.286959, + 5 + 0.608735, + -3 + 0.380043, + 3 + -0.175819, + 7 + -0.829562, + -7 + -0.79598, + -1 + -0.192267, + -5 + -0.110678, + 1 + 0.6394, + 1 + -0.0846046, + 1 + 0.714054, + 5 + 0.811509, + 1 + -0.398193, + 7 + 0.760568, + -1 + -0.452345, + -5 + 0.687367, + 5 + -0.318674, + -3 + 0.324117, + -7 + 0.236211, + -5 + 0.649759, + 7 + -0.548562, + 3 + 0.0579074, + -3 + 0.967526, + 5 + 0.205966, + 3 + -0.575908, + -5 + -0.137605, + 7 + 0.927195, + -5 + 0.454236, + 5 + -0.445633, + 3 + 0.770301, + 7 + -0.281772, + -1 + -0.810031, + -5 + 0.104421, + -3 + 0.920684, + -1 + 0.868938, + 3 + -0.0053164, + -3 + -0.718631, + -5 + 0.455326, + 5 + -0.820026, + -5 + -0.768273, + 3 + 0.0752762, + 5 + 0.714693, + 7 + -0.17771, + -3 + 0.42292, + -1 + -0.0175617, + 5 + 0.528179, + 3 + 0.568353, + 5 + -0.587159, + 1 + 0.801071, + 7 + 0.0826319, + -3 + 0.0275306, + -5 + 0.676104, + -7 + 0.583124, + -3 + 0.218791, + -7 + 0.227567, + -3 + -0.430536, + 5 + 0.654163, + 3 + -0.467692, + 7 + -0.155845, + -7 + 0.089255, + -3 + 0.938383, + -3 + 0.906627, + 7 + 0.950595, + -5 + -0.489709, + 7 + 0.671718, + 7 + 0.164742, + 3 + -0.852821, + 7 + 0.582895, + -3 + -0.742699, + 1 + -0.0381558, + 1 + 0.752823, + 1 + 0.749102, + -1 + 0.403834, + -3 + -0.442988, + 3 + 0.769955, + -1 + 0.729227, + 3 + -0.464394, + -1 + 0.982971, + 5 + 0.32225, + 3 + 0.707018, + 7 + 0.284523, + -5 + -0.390641, + 7 + 0.838552, + 1 + -0.261646, + 7 + 0.763129, + -1 + 0.26582, + 7 + 0.47961, + 5 + 0.195016, + -1 + 0.442942, + 1 + -0.566928, + 1 + -0.885894, + 3 + 0.809517, + 7 + -0.794782, + 1 + 0.396051, + -1 + -0.717371, + -7 + -0.372855, + -3 + -0.435502, + -5 + 0.486243, + -7 + 0.226385, + -3 + -0.674962, + 5 + -0.818546, + -1 + 0.662066, + -3 + 0.371445, + 7 + -0.181262, + -7 + -0.96998, + 7 + -0.243668, + 1 + -0.622788, + -3 + -0.934349, + -7 + -0.531977, + 7 + 0.913129, + -5 + 0.0873188, + -5 + -0.802866, + 5 + 0.176445, + 7 + 0.931233, + -1 + -0.345816, + -7 + -0.698489, + 3 + -0.0641756, + -1 + 0.20042, + 3 + -0.225253, + 7 + 0.611709, + -3 + -0.526143, + 5 + -0.494852, + -7 + -0.543889, + 5 + -0.865676, + 7 + -0.361067, + -7 + 0.157247, + -1 + -0.148807, + -1 + 0.754306, + -3 + -0.232635, + 1 + 0.285416, + 5 + 0.977439, + 3 + -0.545843, + -5 + -0.684446, + 5 + 0.00538877, + -1 + -0.416723, + 1 + 0.455052, + -1 + -0.694408, + -5 + 0.5697, + -3 + 0.239728, + 7 + -0.157425, + -3 + 0.307093, + 3 + 0.598074, + -3 + -0.192316, + -5 + 0.683009, + 1 + -0.276813, + 7 + -0.0605859, + 7 + -0.160651, + 1 + 0.745574, + 5 + -0.595225, + -3 + 0.679057, + -7 + 0.681067, + -3 + 0.254237, + 3 + -0.309311, + -7 + 0.537294, + 7 + -0.527087, + -1 + -0.914636, + -5 + 0.3696, + -5 + 0.758544, + -3 + 0.615554, + -3 + -0.800559, + 5 + 0.857245, + -7 + 0.911095, + -7 + -0.476043, + 1 + 0.286482, + -7 + -0.106087, + -5 + 0.396264, + -5 + -0.897017, + 1 + -0.963821, + -7 + -0.566173, + -5 + 0.578676, + 1 + 0.813064, + 7 + 0.491473, + 7 + -0.270985, + 5 + 0.132949, + 5 + 0.0161494, + 1 + 0.474008, + -5 + 0.796655, + -3 + -0.63918, + 3 + -0.967985, + 7 + 0.879643, + -1 + 0.214509, + -5 + 0.00227151, + 5 + 0.0762274, + 3 + 0.59941, + 3 + 0.340686, + -5 + -0.518312, + -5 + -0.6534, + -3 + -0.133582, + 1 + 0.772737, + -3 + -0.796512, + -1 + -0.232784, + 7 + -0.567475, + -5 + -0.612535, + -5 + -0.743451, + -5 + 0.922795, + 7 + -0.360325, + -5 + 0.664416, + -7 + 0.537588, + -7 + 0.090611, + -1 + -0.411909, + 3 + -0.926915, + 7 + 0.395344, + -7 + -0.661518, + -3 + -0.170838, + 7 + -0.357837, + -5 + 0.471491, + -3 + -0.382249, + -3 + -0.52305, + -1 + -0.97666, + 3 + 0.0582765, + -1 + -0.0656394, + 7 + -0.406727, + 1 + 0.00918714, + -5 + -0.137935, + 7 + -0.614004, + 1 + -0.979364, + -7 + 0.416733, + -1 + -0.759126, + -7 + -0.370293, + -7 + -0.100497, + 1 + 0.869131, + -3 + 0.164885, + -1 + -0.0975662, + -7 + 0.186475, + 3 + -0.918565, + 3 + -0.0801415, + 7 + -0.100654, + -7 + -0.0564053, + -5 + -0.266266, + 1 + -0.250558, + -7 + 0.00064827, + 1 + 0.0900851, + -5 + -0.598895, + -3 + -0.300177, + -3 + -0.733429, + -1 + 0.644141, + -7 + 0.473614, + -1 + -0.641922, + 5 + -0.771156, + 1 + -0.408759, + 5 + 0.12316, + -5 + 0.293248, + 1 + -0.878825, + -7 + -0.414203, + 1 + -0.158712, + 7 + 0.739709, + -7 + -0.86936, + 3 + 0.642115, + 3 + -0.385535, + -7 + 0.143439, + -3 + 0.698413, + 5 + -0.678345, + 5 + 0.565038, + 5 + 0.815733, + 5 + -0.707831, + -7 + -0.849665, + 3 + -0.293231, + 3 + 0.511878, + -7 + 0.0476101, + -5 + -0.612903, + 5 + 0.912856, + -1 + -0.229084, + -1 + -0.228542, + -1 + 0.543728, + 7 + -0.254476, + 5 + -0.538093, + 7 + 0.873386, + -7 + -0.797387, + 1 + 0.472407, + -5 + 0.952256, + -7 + 0.795923, + -1 + -0.0898826, + -3 + 0.851045, + 3 + 0.649821, + -5 + -0.623912, + -1 + -0.232825, + -5 + -0.293336, + 3 + -0.175406, + 7 + -0.126623, + -3 + -0.458458, + -1 + -0.716308, + 3 + -0.442831, + 5 + -0.240306, + -3 + 0.62798, + 7 + -0.901771, + -1 + 0.980463, + 3 + -0.502372, + -7 + -0.861722, + -1 + 0.827093, + 1 + 0.12554, + -3 + 0.270311, + -5 + 0.348095, + -1 + 0.913085, + 7 + 0.957399, + 7 + 0.340458, + 5 + 0.0422461, + -1 + -0.369125, + -3 + 0.43044, + 7 + -0.632377, + -1 + -0.90659, + 1 + -0.89239, + 7 + 0.828316, + 5 + 0.824523, + -7 + -0.0536567, + 1 + -0.0399239, + 1 + 0.197041, + -1 + -0.554157, + -5 + 0.0431199, + -3 + -0.304071, + -3 + -0.331796, + 5 + 0.822257, + 3 + -0.638709, + 3 + 0.639501, + -1 + -0.549931, + -5 + 0.893208, + 3 + 0.791099, + 7 + 0.153618, + 3 + -0.838246, + -7 + 0.475597, + 1 + -0.354901, + -7 + -0.761264, + -1 + 0.106035, + -3 + -0.481434, + -1 + 0.234136, + 5 + 0.375285, + -7 + -0.539323, + -3 + -0.671027, + -3 + 0.212608, + -5 + 0.992672, + -3 + -0.655146, + -1 + -0.675066, + -1 + 0.944776, + 5 + 0.653261, + 7 + 0.703227, + -1 + -0.329846, + -3 + -0.29662, + 5 + 0.0306179, + 3 + 0.308382, + 5 + -0.37852, + 1 + 0.569875, + -1 + 0.262195, + -7 + 0.65172, + -1 + -0.324076, + -1 + -0.592955, + 3 + 0.330534, + -7 + 0.236835, + 7 + -0.16363, + 5 + -0.350766, + 7 + 0.33076, + -3 + 0.713702, + 7 + 0.986953, + 1 + -0.484957, + 1 + 0.232317, + 1 + -0.241183, + 1 + -0.652168, + -7 + -0.969083, + -3 + -0.00466762, + 7 + -0.643621, + 5 + -0.512406, + 3 + 0.559345, + -1 + 0.876841, + 1 + 0.0247327, + -5 + 0.579806, + -7 + -0.45585, + -1 + -0.978404, + -3 + -0.211921, + 3 + 0.0595151, + -5 + -0.772737, + 1 + 0.701463, + 7 + -0.055659, + 1 + -0.434081, + -7 + -0.748698, + 5 + -0.742137, + 5 + -0.0588123, + -5 + 0.446934, + -7 + -0.9576, + -1 + -0.910423, + -1 + -0.798973, + -7 + 0.643822, + -3 + -0.240149, + 1 + -0.366265, + 1 + -0.168219, + -7 + -0.030838, + 7 + -0.591915, + -3 + -0.92018, + 7 + 0.57597, + -1 + 0.351344, + -7 + 0.647625, + 5 + -0.537432, + -5 + -0.69753, + 3 + 0.489766, + -3 + -0.263308, + 1 + 0.40383, + -1 + 0.0716793, + -3 + 0.0739884, + 7 + -0.543397, + -5 + 0.313842, + -1 + -0.290457, + -3 + -0.84267, + -3 + -0.568324, + -3 + -0.18694, + 7 + 0.544842, + 5 + 0.340199, + -5 + -0.465435, + 5 + 0.386054, + 3 + -0.248471, + -1 + -0.536871, + -3 + -0.00456425, + 5 + 0.30784, + -7 + 0.567282, + -3 + -0.689596, + 7 + -0.973479, + -5 + -0.292588, + 1 + -0.0853992, + 1 + 0.54008, + 1 + 0.933126, + 7 + 0.308498, + -5 + 0.933511, + -1 + -0.616556, + 1 + 0.5256, + -3 + 0.11786, + -1 + 0.742156, + -1 + 0.169955, + -1 + -0.96657, + -3 + 0.556796, + -1 + -0.865691, + -3 + -0.238262, + -5 + 0.647911, + 3 + 0.359834, + 7 + 0.613736, + 1 + 0.507745, + -7 + -0.892512, + 3 + 0.444704, + 7 + -0.939748, + -1 + 0.672554, + -7 + 0.136662, + -7 + 0.565658, + 3 + 0.942443, + -1 + 0.0449975, + 1 + 0.92684, + 3 + -0.297685, + 5 + 0.568496, + 3 + -0.144333, + 1 + -0.166059, + 5 + 0.245617, + -7 + 0.0561295, + 5 + -0.053852, + 5 + 0.796947, + -5 + 0.352517, + -5 + 0.967329, + 5 + -0.892274, + 7 + -0.335576, + -1 + -0.545664, + 5 + 0.768217, + -7 + -0.188918, + -7 + 0.285642, + -3 + -0.467917, + -1 + 0.356141, + -7 + -0.382192, + -5 + 0.0410403, + -3 + 0.593099, + -1 + -0.407076, + 7 + 0.399012, + 3 + -0.215368, + 5 + 0.00567285, + 3 + 0.833758, + 7 + -0.469107, + -3 + 0.84339, + -1 + -0.648244, + -1 + 0.45709, + 5 + 0.221697, + -3 + 0.2979, + -1 + -0.801441, + 5 + 0.358525, + 5 + 0.0155232, + 7 + -0.613239, + -3 + 0.770038, + -3 + 0.386763, + -1 + -0.977012, + -5 + 0.0247041, + 3 + -0.774763, + 1 + -0.269862, + 3 + 0.598317, + -7 + -0.604919, + -5 + -0.295425, + -3 + -0.501016, + 5 + 0.893051, + -7 + 0.592268, + -1 + -0.135156, + 5 + -0.766252, + -3 + 0.445672, + 5 + 0.612924, + -5 + 0.107889, + -1 + 0.306333, + -3 + -0.720024, + 1 + -0.256542, + -5 + -0.644907, + -1 + -0.198375, + -1 + 0.530318, + 7 + 0.865427, + -5 + -0.186188, + 3 + 0.15118, + 5 + 0.652307, + 1 + 0.908472, + 3 + 0.747761, + -1 + -0.654492, + 1 + -0.454527, + 5 + 0.682724, + -5 + 0.372245, + 7 + 0.871819, + 3 + -0.80367, + -1 + 0.448117, + -1 + 0.948526, + -7 + -0.348271, + 7 + -0.927127, + 1 + 0.449701, + -1 + -0.680563, + 1 + 0.892784, + 1 + -0.0924386, + -1 + -0.959661, + 7 + -0.081394, + 5 + -0.963336, + -5 + 0.805157, + -7 + -0.285785, + -7 + -0.592211, + -5 + 0.413432, + -1 + -0.723101, + -3 + -0.0432179, + -3 + 0.357774, + 3 + -0.969629, + -7 + 0.840992, + 7 + -0.0670359, + 1 + -0.230027, + -7 + 0.00539775, + -1 + 0.992222, + -5 + 0.508197, + -1 + -0.0701932, + -7 + -0.916136, + 1 + 0.121754, + 3 + 0.979212, + 5 + 0.710977, + -3 + -0.444553, + 1 + 0.775755, + 1 + -0.731095, + -5 + -0.962054, + -7 + -0.137716, + 1 + 0.0744596, + -3 + -0.298853, + 3 + -0.287877, + 7 + -0.537653, + 7 + -0.370057, + 5 + 0.558642, + -1 + -0.306097, + 5 + 0.298301, + 5 + 0.890951, + 7 + 0.461226, + 5 + -0.273165, + -3 + 0.767864, + -1 + -0.427128, + -7 + 0.0742497, + 3 + -0.628171, + -1 + -0.383706, + -5 + 0.926895, + -3 + -0.111893, + -1 + -0.568481, + 3 + 0.982367, + 3 + -0.746265, + 7 + 0.602531, + 5 + 0.639663, + -5 + 0.640932, + 3 + -0.339199, + -7 + -0.872224, + 7 + 0.493771, + 5 + -0.0426846, + 7 + -0.222289, + 7 + -0.802753, + 5 + -0.998975, + 5 + 0.739618, + 5 + -0.949418, + -7 + -0.348646, + 7 + -0.122117, + -3 + -0.786274, + -1 + -0.910026, + 5 + -0.521515, + 5 + 0.786492, + -3 + -0.956601, + -7 + -0.935189, + -1 + 0.816024, + 5 + 0.675236, + 5 + 0.0495799, + -7 + 0.738648, + 7 + 0.424409, + 3 + -0.438266, + -7 + -0.491474, + 1 + 0.22495, + -5 + -0.0235629, + -3 + 0.479672, + -1 + 0.84058, + -5 + -0.166951, + 5 + -0.0577841, + -1 + -0.642721, + -1 + 0.723607, + 1 + -0.873909, + 3 + -0.888751, + -1 + -0.370589, + -3 + -0.0403842, + 3 + 0.564038, + 1 + -0.590923, + -1 + -0.301823, + 3 + -0.525907, + -7 + -0.700129, + -7 + -0.286343, + -1 + -0.746766, + -1 + 0.510312, + -7 + 0.68781, + -1 + -0.071507, + 5 + 0.20512, + 7 + 0.193939, + -3 + 0.0940258, + -1 + -0.815724, + 7 + 0.914182, + 3 + 0.582396, + -5 + 0.182791, + 5 + -0.169328, + 5 + -0.539398, + 1 + -0.544711, + -7 + -0.29523, + -7 + -0.220718, + -7 + -0.424836, + -1 + -0.583509, + 5 + -0.998364, + 7 + -0.624936, + -3 + 0.682019, + 7 + -0.0926723, + -3 + -0.596477, + -1 + -0.380871, + -3 + -0.215605, + 7 + -0.0981703, + -7 + -0.181927, + -1 + 0.668344, + 1 + 0.550972, + 1 + -0.362117, + -1 + 0.434212, + -7 + 0.529025, + 5 + -0.166071, + -3 + 0.473601, + 5 + 0.555215, + 7 + 0.878004, + 3 + 0.90408, + -5 + 0.504969, + -3 + -0.667642, + -5 + -0.538538, + 5 + 0.188161, + -1 + 0.914107, + 3 + 0.472097, + 7 + 0.510842, + -5 + 0.985461, + -7 + -0.394255, + -5 + 0.890095, + 5 + 0.634067, + -7 + -0.944812, + -1 + -0.199624, + -1 + -0.447444, + 3 + -0.228946, + 7 + 0.22322, + -5 + 0.654362, + -5 + -0.200935, + 3 + -0.833657, + -7 + 0.802499, + 1 + -0.704644, + 5 + -0.415231, + 5 + -0.488818, + -5 + -0.405574, + -3 + -0.551587, + 3 + -0.143344, + -5 + 0.992058, + 7 + 0.973004, + -1 + 0.899068, + -1 + -0.201666, + -5 + -0.327868, + 3 + -0.727053, + -7 + 0.268601, + -7 + 0.109424, + 7 + -0.950672, + 1 + 0.76586, + -3 + 0.875399, + 7 + 0.0168127, + -5 + -0.751942, + 1 + 0.455423, + 5 + -0.133098, + 5 + 0.576325, + -5 + -0.760309, + -7 + -0.273288, + -7 + -0.766843, + 1 + -0.862775, + 7 + -0.885211, + 7 + 0.696724, + -1 + 0.0780369, + 1 + 0.275855, + -5 + 0.21323, + -1 + 0.30191, + 5 + -0.129398, + -3 + -0.659394, + 7 + -0.537345, + -5 + 0.726379, + 1 + -0.351187, + 1 + 0.413273, + -7 + -0.460414, + -1 + 0.780082, + 7 + -0.750839, + 7 + 0.140123, + -1 + 0.431409, + -1 + 0.467309, + 7 + -0.189717, + -5 + -0.619566, + 1 + -0.664491, + 5 + -0.259023, + -3 + 0.956683, + -3 + -0.749516, + -5 + 0.131912, + -7 + 0.20736, + -7 + -0.370862, + 3 + -0.38448, + -7 + -0.0683076, + 5 + -0.0808511, + 3 + -0.716107, + -7 + 0.282494, + -5 + 0.690208, + 5 + -0.0140297, + 3 + -0.0253589, + -1 + -0.286539, + 1 + 0.632755, + 3 + 0.678366, + 7 + -0.298717, + 7 + 0.931446, + 3 + -0.000155271, + 5 + 0.593412, + -1 + -0.237465, + 3 + 0.495449, + 1 + 0.854041, + 7 + 0.417438, + 5 + 0.130533, + 3 + 0.11828, + 7 + -0.492641, + -3 + 0.31251, + -1 + -0.746348, + -3 + 0.00667295, + -7 + -0.849606, + -1 + -0.621633, + 5 + -0.780689, + -7 + 0.325068, + -1 + 0.14253, + -5 + -0.467373, + -7 + -0.215694, + -5 + 0.473324, + -5 + -0.0749665, + 1 + 0.0177372, + 1 + 0.874646, + -3 + -0.548775, + -5 + -0.644173, + 7 + 0.890543, + 1 + -0.258939, + -1 + -0.381203, + 7 + -0.989668, + 7 + -0.370075, + -7 + 0.0443089, + 7 + -0.655745, + -1 + 0.576317, + 1 + -0.867409, + -1 + -0.242211, + 3 + -0.414673, + -3 + -0.668824, + -7 + -0.880169, + -7 + -0.337623, + 3 + 0.421604, + 5 + 0.213655, + 5 + -0.797275, + 5 + 0.0784746, + -7 + 0.29279, + 5 + -0.266808, + 5 + -0.847968, + 3 + 0.627592, + 5 + 0.100925, + -7 + -0.836569, + -5 + -0.484448, + -7 + -0.260665, + 7 + 0.98659, + 5 + 0.811925, + 5 + -0.263092, + 3 + -0.423208, + 3 + -0.219005, + -7 + -0.0725037, + -1 + -0.814871, + 3 + 0.181891, + -3 + 0.309198, + 1 + 0.951535, + -7 + 0.694465, + -3 + 0.851734, + -3 + 0.240617, + 7 + -0.545582, + 7 + -0.582447, + -3 + -0.895393, + 1 + -0.607017, + 5 + 0.575812, + 7 + 0.0485804, + -5 + -0.609581, + 3 + -0.991071, + 1 + -0.69817, + -1 + 0.612983, + 7 + 0.124632, + 1 + -0.934992, + -5 + 0.629333, + -1 + -0.479678, + -7 + -0.690851, + 3 + 0.0123024, + 3 + 0.579883, + -7 + -0.797862, + 3 + 0.930494, + 5 + 0.0959856, + 5 + 0.799511, + 3 + -0.702544, + 3 + 0.863534, + -7 + 0.723902, + 3 + -0.925485, + -3 + 0.0838314, + 5 + -0.539124, + -7 + 0.795782, + -7 + -0.508871, + 3 + -0.666186, + -5 + -0.437818, + 1 + 0.430824, + -1 + 0.890288, + 3 + 0.0323077, + -5 + -0.451717, + 1 + -0.994217, + -5 + -0.889329, + 1 + -0.154296, + 3 + -0.139546, + 3 + 0.783946, + -1 + 0.843542, + -7 + 0.742655, + 3 + 0.0644047, + -3 + 0.707173, + 7 + -0.292937, + -1 + 0.978045, + 3 + -0.495493, + 1 + 0.576421, + -5 + 0.830068, + -7 + -0.7389, + -3 + 0.545496, + 5 + 0.525718, + -5 + 0.491613, + -5 + 0.0724149, + -5 + -0.581892, + -5 + 0.148299, + -3 + -0.0143521, + -7 + 0.224096, + -1 + -0.58379, + -7 + -0.746189, + 3 + 0.678161, + 5 + -0.60352, + 1 + -0.0123151, + -3 + 0.935789, + 7 + 0.146463, + 5 + 0.0833464, + -5 + 0.0973773, + 1 + -0.634221, + 5 + -0.199689, + -5 + -0.977316, + 1 + -0.468532, + -3 + 0.912407, + -1 + 0.618525, + -5 + 0.641828, + -3 + 0.161639, + 3 + -0.521444, + 1 + 0.217545, + -3 + 0.776886, + -5 + -0.0861521, + 7 + -0.684462, + 3 + 0.025459, + 5 + -0.588791, + 3 + -0.968869, + -5 + 0.936218, + 5 + -0.962381, + 1 + 0.102731, + 7 + 0.487412, + 5 + -0.586347, + -5 + 0.483033, + 3 + 0.147303, + 7 + 0.545176, + -1 + -0.346122, + -3 + -0.550012, + -3 + 0.175068, + 5 + -0.32015, + 1 + 0.524341, + -7 + 0.645118, + -5 + -0.940018, + -1 + -0.97908, + -7 + -0.515108, + -3 + 0.367395, + 1 + 0.545659, + 1 + -0.286328, + 5 + -0.58779, + 1 + 0.337098, + 7 + -0.330973, + -3 + 0.374149, + 7 + -0.0352384, + -3 + 0.100802, + -3 + -0.496571, + 5 + -0.780307, + 1 + -0.478443, + 5 + 0.67526, + 7 + -0.425565, + 7 + 0.754558, + -7 + -0.775828, + 5 + 0.655701, + 7 + -0.438407, + 3 + -0.775985, + 7 + -0.666725, + -1 + 0.797674, + 1 + -0.749333, + -7 + 0.194764, + -7 + 0.625181, + -5 + -0.060977, + -5 + 0.643178, + 3 + -0.933005, + -3 + -0.998434, + 3 + 0.713815, + -3 + -0.574046, + -3 + -0.0416154, + -7 + 0.296629, + 7 + 0.191779, + -7 + 0.833033, + -3 + 0.487987, + -3 + -0.575328, + 5 + 0.496461, + 3 + 0.589905, + 7 + -0.924183, + -1 + 0.696718, + 5 + -0.875373, + -3 + 0.0319824, + 5 + -0.207871, + 3 + 0.177233, + -3 + -0.761711, + 1 + 0.401589, + 7 + 0.538526, + 7 + -0.320289, + -3 + -0.281917, + -5 + -0.547839, + -7 + -0.322797, + -5 + -0.605992, + 5 + 0.785395, + -1 + 0.0550308, + -5 + 0.511285, + -7 + 0.402531, + -7 + -0.464181, + 5 + -0.160938, + -5 + -0.735561, + -5 + 0.0996571, + 7 + 0.593118, + 7 + -0.0328994, + -5 + -0.98964, + 3 + 0.205471, + -1 + 0.200857, + 7 + -0.771514, + 1 + -0.587245, + 3 + 0.26805, + -3 + 0.784424, + -5 + -0.963779, + 7 + -0.505932, + -1 + -0.171588, + -1 + 0.670593, + -7 + 0.301767, + 5 + 0.0138393, + -1 + -0.984387, + -1 + 0.0391519, + -3 + -0.222087, + 7 + 0.0864488, + 5 + -0.4927, + 7 + 0.257574, + -3 + 0.232144, + -7 + 0.327466, + 1 + -0.464061, + -3 + -0.275329, + -1 + -0.0648923, + -7 + 0.674159, + -7 + -0.413218, + -7 + -0.692417, + 1 + -0.762459, + -5 + -0.913253, + -7 + 0.36255, + -5 + 0.917413, + -7 + 0.556944, + 7 + 0.869794, + -5 + 0.599393, + -7 + -0.957509, + 3 + -0.0653876, + -3 + 0.542317, + 7 + -0.919778, + -1 + 0.389195, + 1 + -0.694826, + -1 + -0.684451, + 5 + -0.232338, + 7 + 0.107159, + 1 + -0.408376, + 3 + -0.669585, + 5 + 0.257082, + 5 + 0.831891, + -1 + 0.211606, + -5 + -0.384855, + 7 + 0.020007, + -5 + -0.428625, + -3 + -0.0360878, + 5 + -0.848203, + 3 + 0.0254734, + -3 + 0.749542, + -7 + -0.804563, + -1 + -0.0972806, + 1 + -0.248763, + -5 + -0.480906, + -7 + 0.494774, + -7 + 0.809284, + 1 + 0.892301, + 3 + -0.866702, + 7 + 0.549121, + -7 + -0.807113, + 5 + 0.817796, + -3 + -0.258985, + -3 + -0.652257, + 1 + 0.857754, + 1 + 0.602559, + -3 + 0.459551, + -5 + 0.12109, + 7 + 0.228169, + 3 + 0.268535, + -5 + -0.511365, + 3 + 0.473797, + -3 + 0.789188, + 5 + -0.233201, + -1 + 0.337202, + 3 + 0.0872898, + -5 + -0.577231, + -3 + -0.794605, + -3 + 0.948282, + 1 + 0.86739, + 7 + -0.853303, + 1 + 0.585277, + -5 + -0.0480538, + 3 + 0.131517, + -5 + 0.256086, + 3 + -0.220017, + -1 + 0.968746, + 1 + -0.866085, + 1 + -0.75045, + 3 + 0.103057, + 3 + -0.280213, + 7 + -0.915525, + 1 + 0.910469, + -1 + 0.122471, + 7 + 0.756213, + -1 + -0.979998, + -3 + -0.526045, + -3 + -0.515105, + -3 + 0.191857, + -5 + 0.861293, + -5 + 0.557644, + -7 + 0.955665, + -7 + -0.218954, + -5 + 0.843849, + 3 + 0.700339, + -5 + 0.308848, + 5 + -0.671504, + -7 + -0.977673, + -3 + -0.243973, + -7 + -0.21181, + 5 + -0.722984, + 1 + -0.679969, + 1 + -0.943541, + -5 + 0.705531, + -5 + -0.327772, + 3 + -0.462895, + -3 + 0.0536484, + -5 + -0.181505, + 1 + -0.89014, + 3 + -0.24572, + 3 + -0.890222, + -3 + 0.668824, + -1 + -0.785433, + -5 + -0.835302, + 7 + -0.464588, + -3 + -0.970526, + -7 + -0.881556, + 3 + -0.690873, + -7 + 0.627452, + 7 + 0.162041, + 1 + 0.574909, + -3 + -0.436167, + -7 + -0.415736, + -1 + -0.330565, + 3 + -0.0637465, + 1 + -0.952135, + 7 + 0.820211, + 1 + 0.670167, + 3 + -0.227245, + 3 + 0.784935, + -7 + -0.114356, + -7 + -0.79073, + -7 + -0.0845568, + -3 + 0.0352457, + -1 + 0.23913, + 3 + -0.319363, + -1 + -0.784674, + 7 + 0.182406, + -3 + -0.208943, + 1 + -0.0539068, + 5 + -0.793545, + 7 + -0.926668, + -3 + -0.327488, + -5 + 0.286006, + 5 + 0.755716, + -1 + 0.396711, + -5 + 0.50953, + -5 + 0.0396668, + -7 + 0.294158, + 7 + 0.191498, + 1 + -0.157408, + 1 + -0.341843, + 1 + 0.34502, + 1 + 0.892611, + 7 + 0.205394, + -3 + 0.558871, + -5 + 0.209696, + -1 + 0.119176, + 3 + -0.0071817, + -5 + -0.177535, + 3 + 0.909066, + -3 + -0.741923, + 1 + -0.539941, + -3 + -0.037078, + 1 + 0.791042, + -5 + 0.482362, + -5 + -0.0119576, + -3 + 0.52501, + -7 + 0.76094, + -7 + 0.813217, + 7 + 0.985842, + 3 + -0.529906, + 1 + -0.423377, + -3 + 0.0981717, + -3 + -0.223135, + -5 + -0.61793, + 5 + -0.559953, + 5 + -0.469591, + -1 + 0.342377, + 3 + -0.0782716, + 7 + -0.684588, + 7 + 0.389739, + 5 + 0.10658, + -5 + 0.922608, + 7 + 0.602939, + -1 + 0.464956, + 3 + -0.789037, + 5 + 0.429394, + 3 + -0.550469, + 1 + -0.900731, + -3 + -0.623247, + -7 + -0.650424, + -1 + 0.131661, + -1 + -0.806985, + 1 + 0.960326, + -1 + -0.193632, + 7 + 0.582939, + -1 + -0.468436, + 5 + 0.0584084, + -3 + 0.989501, + -7 + -0.836051, + -7 + 0.494241, + -3 + 0.338635, + -1 + -0.648491, + -3 + 0.319444, + 5 + -0.976509, + -7 + -0.560152, + 1 + 0.968145, + -3 + 0.506876, + 1 + -0.446687, + -3 + -0.557403, + -5 + 0.386343, + 7 + -0.26601, + 5 + 0.768097, + -1 + -0.862516, + 3 + 0.092811, + 1 + 0.688699, + -7 + 0.437148, + -7 + 0.819611, + -5 + 0.433439, + -3 + 0.0525214, + 7 + -0.875873, + -1 + -0.318693, + -7 + 0.941041, + 3 + -0.938497, + -5 + -0.700787, + -5 + -0.208713, + -1 + -0.926069, + 5 + 0.763435, + -3 + -0.753673, + -3 + -0.436892, + 5 + 0.25309, + 3 + 0.376517, + 7 + 0.234089, + -1 + 0.602584, + 7 + -0.729457, + -5 + 0.528713, + 5 + -0.0616122, + -5 + 0.485624, + -3 + 0.341517, + 3 + -0.364478, + 7 + 0.124957, + -1 + -0.27282, + 5 + 0.606241, + -7 + 0.409408, + -7 + 0.326685, + 1 + -0.778263, + -5 + -0.479604, + -5 + 0.454517, + 5 + -0.236371, + -5 + -0.208087, + -7 + -0.336902, + -3 + 0.704184, + -1 + -0.607403, + -1 + 0.790341, + -1 + -0.458402, + 3 + 0.29028, + -5 + 0.608615, + -5 + 0.064577, + 7 + -0.440438, + 7 + 0.518133, + 3 + -0.400959, + -5 + 0.957821, + -3 + 0.832433, + -7 + -0.941491, + -3 + -0.158894, + -3 + 0.735858, + -5 + -0.942659, + -7 + 0.362461, + -3 + 0.175003, + -3 + 0.756938, + 5 + -0.586989, + -3 + -0.867437, + -7 + 0.204605, + 7 + -0.447344, + 7 + 0.37656, + -7 + 0.548076, + 5 + -0.720016, + -7 + -0.533887, + -1 + 0.0948688, + -1 + 0.921622, + 5 + -0.363181, + 1 + 0.875163, + 1 + -0.975703, + -7 + -0.991177, + 3 + 0.142339, + -7 + -0.670125, + 7 + 0.835181, + -7 + -0.176508, + 7 + -0.391808, + -3 + 0.659639, + -7 + 0.311382, + -5 + 0.965804, + 3 + 0.127325, + 1 + -0.000208556, + -7 + -0.777168, + -3 + 0.467445, + -7 + -0.274472, + 7 + -0.125423, + -7 + -0.341567, + -7 + -0.152778, + 3 + 0.328462, + 3 + 0.96799, + 3 + -0.863599, diff --git a/gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_output.dat b/gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_output.dat new file mode 100644 index 00000000..462b664b --- /dev/null +++ b/gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_output.dat @@ -0,0 +1,2484 @@ +69, +35, +24, +72, +92, +92, +20, +88, +31, +124, +88, +87, +65, +30, +169, +225, +0, +98, +8, +39, +35, +233, +205, +67, +15, +37, +249, +114, +194, +215, +196, +7, +251, +93, +80, +215, +186, +228, +48, +217, +97, +137, +177, +163, +168, +90, +132, +168, +189, +140, +208, +224, +118, +158, +36, +134, +196, +29, +248, +134, +245, +189, +141, +240, +26, +221, +200, +212, +194, +248, +173, +35, +130, +95, +198, +42, +185, +74, +211, +119, +215, +164, +88, +78, +66, +124, +212, +6, +154, +204, +141, +143, +137, +27, +127, +164, +249, +72, +120, +187, +64, +38, +222, +195, +133, +165, +237, +63, +240, +193, +183, +199, +101, +15, +21, +168, +140, +233, +175, +38, +182, +60, +182, +64, +87, +53, +228, +80, +126, +93, +11, +191, +132, +234, +130, +10, +143, +112, +74, +127, +49, +2, +71, +150, +18, +93, +63, +158, +71, +238, +197, +253, +43, +123, +62, +130, +177, +35, +211, +47, +129, +223, +238, +6, +202, +112, +17, +89, +224, +91, +217, +17, +94, +33, +168, +112, +126, +231, +14, +197, +214, +212, +195, +1, +79, +1, +132, +1, +36, +87, +48, +165, +55, +30, +172, +1, +143, +189, +90, +112, +24, +52, +130, +119, +85, +42, +231, +211, +18, +246, +153, +232, +202, +92, +234, +26, +93, +110, +27, +130, +197, +75, +40, +253, +106, +212, +254, +250, +145, +89, +106, +170, +141, +236, +33, +227, +23, +9, +183, +41, +255, +80, +18, +201, +172, +252, +227, +10, +107, +255, +141, +49, +74, +181, +46, +181, +138, +44, +175, +27, +133, +26, +198, +19, +6, +232, +246, +29, +241, +174, +71, +240, +254, +90, +185, +171, +87, +157, +182, +194, +157, +67, +243, +232, +248, +34, +157, +130, +78, +77, +158, +212, +103, +100, +231, +110, +76, +222, +140, +61, +140, +211, +46, +138, +46, +232, +54, +133, +133, +236, +72, +35, +47, +59, +11, +40, +94, +168, +171, +172, +246, +74, +128, +93, +174, +104, +204, +251, +70, +88, +57, +210, +44, +103, +93, +90, +79, +148, +223, +213, +129, +39, +248, +177, +99, +4, +217, +193, +172, +133, +110, +162, +207, +239, +0, +126, +87, +205, +121, +158, +37, +179, +113, +81, +27, +207, +171, +107, +99, +139, +65, +228, +178, +58, +149, +22, +62, +111, +216, +234, +244, +70, +141, +195, +54, +142, +66, +141, +91, +187, +44, +129, +111, +157, +210, +138, +108, +126, +245, +208, +9, +55, +180, +188, +113, +74, +211, +175, +185, +171, +154, +174, +242, +40, +114, +40, +183, +180, +182, +19, +112, +226, +148, +223, +128, +103, +106, +237, +229, +96, +189, +239, +151, +114, +172, +8, +189, +127, +184, +118, +43, +83, +37, +29, +123, +151, +70, +50, +76, +252, +69, +188, +223, +218, +156, +96, +65, +6, +77, +39, +102, +11, +23, +254, +125, +195, +7, +59, +67, +191, +178, +111, +18, +215, +141, +142, +111, +211, +192, +187, +208, +6, +119, +176, +225, +19, +16, +34, +26, +94, +74, +128, +105, +97, +127, +231, +37, +134, +35, +104, +69, +213, +215, +88, +172, +101, +230, +27, +56, +167, +214, +9, +174, +78, +185, +143, +98, +202, +178, +124, +40, +253, +253, +146, +94, +124, +122, +131, +2, +157, +236, +72, +114, +196, +161, +31, +41, +136, +58, +98, +47, +17, +107, +222, +96, +37, +110, +194, +239, +32, +63, +24, +29, +60, +170, +124, +185, +37, +0, +188, +195, +237, +4, +53, +178, +165, +84, +219, +45, +143, +62, +93, +161, +169, +60, +1, +206, +170, +196, +190, +203, +4, +214, +232, +65, +129, +101, +250, +166, +102, +182, +105, +83, +186, +159, +5, +96, +244, +225, +142, +132, +31, +236, +37, +201, +40, +39, +152, +210, +236, +86, +157, +240, +44, +134, +49, +173, +235, +44, +83, +81, +226, +189, +165, +157, +93, +170, +254, +81, +140, +141, +213, +171, +121, +251, +117, +161, +35, +13, +116, +16, +99, +17, +0, +144, +152, +50, +61, +132, +95, +145, +214, +66, +79, +123, +223, +172, +38, +222, +254, +178, +107, +211, +94, +229, +207, +212, +134, +242, +225, +251, +2, +69, +12, +3, +214, +164, +54, +20, +40, +149, +165, +254, +215, +245, +122, +183, +162, +160, +150, +160, +83, +1, +116, +177, +230, +67, +133, +109, +54, +103, +104, +56, +173, +117, +60, +131, +26, +115, +151, +67, +9, +61, +65, +224, +50, +188, +152, +212, +92, +46, +116, +175, +48, +232, +97, +23, +44, +231, +132, +98, +78, +237, +155, +251, +98, +215, +126, +124, +74, +22, +191, +83, +83, +1, +52, +133, +189, +205, +90, +26, +252, +207, +202, +45, +183, +43, +68, +228, +19, +201, +70, +98, +182, +225, +93, +25, +185, +220, +150, +4, +243, +86, +88, +70, +88, +141, +203, +21, +90, +38, +48, +87, +245, +250, +132, +173, +38, +200, +145, +57, +145, +215, +156, +72, +185, +250, +98, +114, +215, +248, +119, +202, +78, +207, +16, +166, +92, +220, +188, +183, +2, +237, +14, +247, +231, +146, +164, +14, +91, +53, +72, +237, +13, +228, +53, +199, +222, +151, +57, +181, +144, +177, +127, +222, +128, +143, +133, +220, +107, +66, +147, +109, +47, +162, +101, +23, +52, +9, +37, +143, +63, +110, +125, +77, +82, +179, +20, +49, +75, +78, +230, +219, +255, +102, +186, +127, +246, +64, +92, +98, +130, +240, +208, +177, +146, +53, +200, +198, +63, +238, +86, +127, +92, +212, +204, +175, +135, +224, +224, +210, +47, +199, +173, +46, +45, +104, +174, +36, +168, +10, +134, +42, +250, +86, +220, +141, +139, +165, +83, +203, +148, +170, +74, +241, +126, +22, +160, +6, +247, +128, +216, +38, +72, +134, +85, +117, +238, +3, +153, +151, +13, +32, +194, +8, +118, +158, +149, +2, +68, +233, +205, +217, +148, +23, +202, +19, +46, +106, +25, +38, +235, +241, +76, +51, +120, +162, +169, +103, +165, +66, +254, +179, +98, +192, +188, +217, +95, +82, +219, +164, +59, +169, +125, +208, +193, +71, +227, +239, +177, +252, +22, +157, +238, +98, +208, +102, +5, +121, +206, +170, +188, +204, +94, +31, +141, +26, +248, +237, +108, +212, +146, +168, +125, +15, +120, +62, +87, +91, +46, +9, +88, +68, +166, +70, +167, +118, +173, +172, +240, +124, +87, +172, +72, +181, +203, +214, +207, +196, +196, +59, +152, +86, +228, +21, +102, +92, +84, +190, +183, +131, +199, +16, +199, +110, +86, +110, +229, +4, +27, +213, +128, +114, +129, +201, +39, +77, +160, +247, +17, +100, +51, +169, +187, +23, +191, +33, +115, +20, +223, +43, +151, +167, +59, +94, +21, +146, +205, +251, +150, +233, +208, +23, +91, +82, +224, +131, +159, +129, +122, +177, +229, +173, +91, +160, +196, +27, +194, +56, +47, +162, +99, +198, +74, +159, +37, +95, +49, +243, +91, +200, +220, +43, +223, +55, +126, +192, +187, +29, +65, +53, +207, +39, +226, +42, +200, +167, +69, +138, +223, +116, +45, +67, +59, +119, +226, +97, +215, +20, +84, +50, +221, +48, +94, +188, +104, +220, +125, +35, +249, +191, +89, +200, +230, +60, +243, +175, +227, +56, +57, +195, +173, +103, +7, +233, +222, +234, +74, +181, +254, +158, +232, +219, +207, +70, +152, +56, +34, +22, +92, +28, +213, +181, +229, +188, +241, +216, +107, +213, +17, +165, +153, +190, +12, +160, +167, +235, +139, +242, +161, +138, +144, +137, +101, +96, +208, +254, +152, +242, +20, +244, +14, +234, +170, +243, +167, +155, +204, +19, +113, +221, +184, +11, +156, +197, +171, +68, +177, +55, +54, +82, +193, +199, +220, +39, +39, +172, +37, +192, +158, +58, +180, +173, +37, +94, +161, +204, +250, +109, +224, +108, +75, +153, +119, +232, +94, +35, +45, +15, +90, +99, +98, +27, +43, +62, +66, +83, +234, +104, +20, +137, +162, +201, +54, +200, +39, +215, +149, +34, +69, +117, +142, +144, +14, +6, +121, +109, +41, +166, +125, +131, +10, +223, +159, +53, +29, +225, +137, +8, +74, +157, +145, +237, +102, +200, +181, +142, +159, +74, +177, +229, +192, +64, +118, +207, +70, +239, +60, +111, +149, +185, +243, +160, +153, +146, +214, +182, +116, +95, +191, +190, +253, +80, +171, +99, +25, +97, +242, +185, +172, +163, +158, +108, +228, +20, +59, +42, +4, +120, +154, +154, +49, +141, +58, +202, +32, +16, +129, +149, +112, +65, +83, +109, +146, +255, +209, +171, +96, +196, +100, +13, +103, +2, +121, +76, +23, +181, +118, +28, +45, +17, +183, +95, +158, +241, +42, +191, +2, +172, +84, +115, +237, +168, +224, +127, +168, +178, +42, +8, +118, +142, +22, +222, +145, +143, +42, +169, +69, +160, +197, +114, +177, +124, +210, +80, +110, +252, +16, +113, +168, +101, +228, +149, +13, +197, +20, +181, +119, +63, +190, +237, +206, +212, +203, +95, +100, +245, +9, +169, +150, +207, +28, +72, +76, +238, +153, +186, +234, +169, +44, +146, +14, +17, +40, +28, +214, +61, +209, +77, +125, +144, +59, +75, +100, +6, +171, +200, +252, +180, +114, +147, +131, +142, +219, +207, +124, +117, +138, +102, +31, +183, +249, +45, +200, +34, +74, +158, +96, +27, +236, +221, +172, +39, +40, +16, +46, +212, +217, +43, +136, +75, +190, +11, +217, +154, +219, +85, +15, +102, +188, +46, +29, +182, +92, +229, +217, +166, +131, +57, +194, +112, +22, +110, +151, +63, +127, +197, +19, +88, +241, +156, +163, +175, +168, +125, +73, +131, +211, +88, +233, +143, +135, +7, +70, +227, +236, +31, +138, +112, +88, +77, +224, +111, +187, +120, +174, +59, +62, +194, +147, +47, +94, +55, +222, +6, +180, +40, +138, +135, +129, +116, +23, +8, +123, +93, +236, +103, +125, +118, +216, +213, +195, +184, +69, +127, +49, +244, +187, +111, +182, +78, +158, +21, +134, +125, +27, +59, +165, +165, +195, +38, +25, +218, +47, +149, +56, +27, +252, +181, +146, +213, +139, +86, +142, +208, +213, +191, +196, +145, +46, +123, +223, +205, +144, +102, +75, +171, +161, +240, +81, +101, +23, +107, +64, +70, +0, +120, +98, +253, +46, +244, +210, +185, +74, +96, +138, +32, +32, +78, +177, +79, +201, +145, +28, +89, +248, +103, +5, +154, +88, +87, +255, +112, +195, +63, +183, +196, +184, +25, +193, +230, +14, +148, +160, +89, +245, +42, +122, +21, +121, +43, +100, +67, +189, +129, +157, +182, +233, +162, +80, +65, +250, +80, +178, +190, +143, +105, +130, +72, +131, +67, +47, +145, +216, +208, +235, +205, +251, +101, +227, +116, +145, +71, +183, +78, +201, +84, +4, +178, +247, +85, +244, +242, +165, +166, +176, +53, +16, +50, +126, +147, +118, +173, +37, +78, +125, +16, +28, +120, +117, +0, +237, +6, +71, +164, +85, +17, +249, +90, +195, +240, +175, +184, +227, +85, +94, +147, +138, +110, +197, +8, +2, +60, +182, +39, +139, +51, +55, +167, +172, +173, +167, +153, +179, +239, +62, +9, +1, +55, +99, +196, +40, +19, +124, +12, +104, +219, +159, +243, +74, +101, +251, +76, +161, +178, +115, +44, +230, +171, +212, +146, +88, +124, +44, +12, +108, +107, +21, +109, +163, +121, +50, +204, +140, +175, +216, +244, +138, +119, +232, +213, +221, +228, +33, +127, +150, +149, +172, +124, +64, +129, +15, +153, +253, +59, +166, +105, +167, +187, +215, +74, +53, +9, +22, +193, +184, +238, +182, +67, +102, +158, +24, +68, +130, +58, +195, +24, +207, +111, +149, +16, +240, +164, +170, +238, +224, +80, +88, +135, +12, +47, +209, +65, +57, +232, +2, +242, +215, +185, +53, +62, +87, +78, +130, +218, +136, +69, +243, +87, +181, +136, +104, +166, +44, +18, +148, +13, +99, +237, +148, +111, +28, +102, +176, +86, +79, +179, +72, +38, +109, +125, +100, +197, +203, +231, +159, +83, +44, +146, +171, +226, +27, +20, +137, +72, +39, +29, +85, +138, +10, +234, +249, +39, +81, +170, +125, +160, +94, +197, +198, +203, +67, +43, +145, +15, +18, +48, +98, +63, +195, +14, +34, +222, +35, +171, +39, +74, +201, +125, +212, +212, +103, +206, +251, +185, +121, +121, +89, +215, +63, +32, +163, +130, +75, +52, +145, +94, +101, +244, +158, +40, +3, +192, +7, +38, +107, +47, +113, +52, +172, +69, +8, +20, +20, +4, +205, +141, +126, +38, +101, +189, +71, +9, +64, +147, +62, +210, +241, +163, +198, +143, +204, +202, +80, +212, +241, +187, +4, +98, +240, +176, +168, +249, +197, +188, +254, +146, +73, +124, +185, +175, +57, +1, +184, +122, +148, +246, +76, +134, +154, +19, +21, +102, +222, +102, +59, +207, +33, +63, +49, +18, +240, +218, +11, +181, +150, +9, +72, +224, +134, +2, +143, +192, +3, +71, +58, +151, +62, +135, +29, +216, +154, +51, +63, +120, +153, +123, +72, +187, +187, +122, +206, +171, +84, +218, +97, +234, +228, +169, +203, +106, +172, +90, +42, +175, +162, +101, +71, +224, +236, +101, +185, +135, +153, +248, +0, +51, +116, +72, +238, +47, +194, +189, +218, +22, +151, +60, +1, +123, +230, +204, +230, +146, +38, +17, +66, +200, +118, +137, +169, +99, +239, +98, +234, +136, +91, +234, +187, +208, +51, +170, +255, +245, +103, +218, +11, +255, +22, +12, +123, +252, +217, +97, +142, +255, +115, +208, +200, +234, +90, +114, +77, +73, +212, +56, +209, +48, +35, +141, +0, +86, +55, +0, +75, +159, +218, +87, +159, +240, +100, +26, +237, +61, +124, +124, +61, +239, +77, +6, +218, +167, +120, +39, +241, +77, +96, +195, +125, +132, +80, +126, +218, +136, +126, +38, +40, +88, +126, +199, +73, +226, +225, +55, +32, +94, +179, +94, +78, +1, +100, +40, +168, +220, +80, +154, +41, +177, +93, +167, +53, +173, +37, +16, +54, +164, +55, +94, +253, +181, +37, +70, +152, +7, +126, +184, +102, +50, +22, +180, +51, +123, +221, +220, +87, +46, +118, +129, +223, +211, +41, +20, +129, +78, +37, +183, +243, +92, +21, +240, +17, +59, +55, +169, +67, +181, +98, +170, +231, +121, +94, +27, +244, +60, +247, +76, +106, +109, +206, +73, +64, +247, +94, +193, +70, +131, +121, +57, +223, +143, +41, +241, +203, +97, +155, +14, +23, +253, +184, +255, +119, +23, +26, +108, +83, +17, +184, +190, +127, +135, +7, +191, +126, +102, +129, +196, +233, +251, +254, +200, +138, +40, +186, +85, +137, +85, +100, +160, +83, +29, +159, +202, +53, +185, +54, +137, +203, +239, +71, +74, +119, +79, +10, +245, +181, +140, +186, +158, +135, +184, +103, +18, +224, +33, +103, +106, +118, +204, +10, +201, +234, +170, +147, +31, +99, +202, +168, +47, +186, +239, +121, +50, +62, +131, +39, +243, +15, +225, +146, +151, +154, +249, +169, +123, +26, +17, +229, +145, +221, +239, +90, +199, +153, +238, +230, +253, +185, +142, +44, +116, +126, +166, +166, +189, +41, +206, +176, +57, +176, +67, +208, +74, +60, +121, +197, +87, +138, +170, +232, +104, +154, +67, +48, +52, +50, +22, +49, +236, +165, +94, +96, +36, +4, +7, +225, +46, +213, +146, +104, +133, +213, +57, +207, +18, +178, +149, +105, +61, +63, +82, +166, +218, +150, +214, +14, +200, +237, +64, +180, +147, +159, +21, +183, +164, +28, +152, +210, +241, +42, +59, +118, +0, +116, +70, +18, diff --git a/gr-atsc/src/lib/qa_convolutional_interleaver.cc b/gr-atsc/src/lib/qa_convolutional_interleaver.cc new file mode 100644 index 00000000..2850549b --- /dev/null +++ b/gr-atsc/src/lib/qa_convolutional_interleaver.cc @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +void +qa_convolutional_interleaver::t0 () +{ + static int input[16] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16 + }; + + static int output[16] = { + 1, 0, 0, 0, + 5, 2, 0, 0, + 9, 6, 3, 0, + 13, 10, 7, 4 + }; + + // test interleaver + intl = new convolutional_interleaver(true, 4, 1); + + for (int i = 0; i < 16; i++) + CPPUNIT_ASSERT_EQUAL (output[i], intl->transform (input[i])); +} + +void +qa_convolutional_interleaver::t1 () +{ + static int input[16] = { + 1, 0, 0, 0, + 5, 2, 0, 0, + 9, 6, 3, 0, + 13, 10, 7, 4 + }; + + static int output[16] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 1, 2, 3, 4 + }; + + // test deinterleaver + intl = new convolutional_interleaver(false, 4, 1); + + for (int i = 0; i < 16; i++) + CPPUNIT_ASSERT_EQUAL (output[i], intl->transform (input[i])); +} + +void +qa_convolutional_interleaver::t2 () +{ + intl = new convolutional_interleaver(true, 4, 1); + deintl = new convolutional_interleaver(false, 4, 1); + + int icount = 6000; + int dcount = 6000; + + int end_to_end_delay = intl->end_to_end_delay (); + for (int i = 0; i < end_to_end_delay; i++){ + CPPUNIT_ASSERT_EQUAL (0, deintl->transform (intl->transform (icount++))); + } + + for (int i = 0; i < 3 * end_to_end_delay; i++){ + CPPUNIT_ASSERT_EQUAL (dcount++, deintl->transform (intl->transform (icount++))); + } +} + +void +qa_convolutional_interleaver::t3 () +{ + intl = new convolutional_interleaver(true, 4, 2); + deintl = new convolutional_interleaver(false, 4, 2); + + int icount = 6000; + int dcount = 6000; + + int end_to_end_delay = intl->end_to_end_delay (); + for (int i = 0; i < end_to_end_delay; i++){ + CPPUNIT_ASSERT_EQUAL (0, deintl->transform (intl->transform (icount++))); + } + + for (int i = 0; i < 3 * end_to_end_delay; i++){ + CPPUNIT_ASSERT_EQUAL (dcount++, deintl->transform (intl->transform (icount++))); + } +} + +void +qa_convolutional_interleaver::t4 () +{ + intl = new convolutional_interleaver(true, 52, 4); + deintl = new convolutional_interleaver(false, 52, 4); + + int icount = 6000; + int dcount = 6000; + + int end_to_end_delay = intl->end_to_end_delay (); + CPPUNIT_ASSERT_EQUAL (10608, end_to_end_delay); + + for (int i = 0; i < end_to_end_delay; i++){ + CPPUNIT_ASSERT_EQUAL (0, deintl->transform (intl->transform (icount++))); + } + + for (int i = 0; i < 3 * end_to_end_delay; i++){ + CPPUNIT_ASSERT_EQUAL (dcount++, deintl->transform (intl->transform (icount++))); + } +} diff --git a/gr-atsc/src/lib/qa_convolutional_interleaver.h b/gr-atsc/src/lib/qa_convolutional_interleaver.h new file mode 100644 index 00000000..54f3b1e1 --- /dev/null +++ b/gr-atsc/src/lib/qa_convolutional_interleaver.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_CONVOLUTIONAL_INTERLEAVER_H_ +#define _QA_CONVOLUTIONAL_INTERLEAVER_H_ + +#include +#include + +#include + +class qa_convolutional_interleaver : public CppUnit::TestCase { + private: + convolutional_interleaver *intl; + convolutional_interleaver *deintl; + + CPPUNIT_TEST_SUITE (qa_convolutional_interleaver); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST_SUITE_END (); + + public: + + void setUp (){ + intl = 0; + deintl = 0; + } + + void tearDown (){ + delete intl; + intl = 0; + delete deintl; + deintl = 0; + } + + private: + + void t0 (); + void t1 (); + void t2 (); + void t3 (); + void t4 (); + +}; + + +#endif /* _QA_CONVOLUTIONAL_INTERLEAVER_H_ */ diff --git a/gr-atsc/src/lib/qa_interleaver_fifo.cc b/gr-atsc/src/lib/qa_interleaver_fifo.cc new file mode 100644 index 00000000..920e68bc --- /dev/null +++ b/gr-atsc/src/lib/qa_interleaver_fifo.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +void +qa_interleaver_fifo::t0 () +{ + fifo = new interleaver_fifo(0); + + for (int i = 10; i < 20; i++) + CPPUNIT_ASSERT_EQUAL (i, fifo->stuff (i)); +} + +void +qa_interleaver_fifo::t1 () +{ + fifo = new interleaver_fifo(1); + + CPPUNIT_ASSERT_EQUAL (0, fifo->stuff (2)); + + for (int i = 1; i < 10; i++) + CPPUNIT_ASSERT_EQUAL (i * 2, fifo->stuff ((i + 1) * 2)); +} + +void +qa_interleaver_fifo::t2 () +{ + fifo = new interleaver_fifo(4); + + CPPUNIT_ASSERT_EQUAL (0, fifo->stuff (1)); + CPPUNIT_ASSERT_EQUAL (0, fifo->stuff (2)); + CPPUNIT_ASSERT_EQUAL (0, fifo->stuff (3)); + CPPUNIT_ASSERT_EQUAL (0, fifo->stuff (4)); + + for (int i = 5; i < 20; i++) + CPPUNIT_ASSERT_EQUAL (i - 4, fifo->stuff (i)); +} diff --git a/gr-atsc/src/lib/qa_interleaver_fifo.h b/gr-atsc/src/lib/qa_interleaver_fifo.h new file mode 100644 index 00000000..3002e8cd --- /dev/null +++ b/gr-atsc/src/lib/qa_interleaver_fifo.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_INTERLEAVER_FIFO_H_ +#define _QA_INTERLEAVER_FIFO_H_ + +#include +#include + +#include + +class qa_interleaver_fifo : public CppUnit::TestCase { + private: + interleaver_fifo *fifo; + + public: + + void tearDown (){ + delete fifo; + fifo = 0; + } + + CPPUNIT_TEST_SUITE (qa_interleaver_fifo); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t0 (); + void t1 (); + void t2 (); + +}; + + +#endif /* _QA_INTERLEAVER_FIFO_H_ */ diff --git a/gr-atsc/src/lib/test_atsci.cc b/gr-atsc/src/lib/test_atsci.cc new file mode 100644 index 00000000..655c3aa1 --- /dev/null +++ b/gr-atsc/src/lib/test_atsci.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_atsc::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gr-atsc/src/python/Makefile.am b/gr-atsc/src/python/Makefile.am new file mode 100644 index 00000000..bdca3257 --- /dev/null +++ b/gr-atsc/src/python/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +noinst_PYTHON = \ + atsc_utils.py \ + qa_atsc.py diff --git a/gr-atsc/src/python/atsc_utils.py b/gr-atsc/src/python/atsc_utils.py new file mode 100644 index 00000000..11976640 --- /dev/null +++ b/gr-atsc/src/python/atsc_utils.py @@ -0,0 +1,74 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import random +import sys + +MPEG_SYNC_BYTE = 0x47 + +def make_fake_transport_stream_packet(npkts): + """ + Return a sequence of 8-bit ints that represents an MPEG Transport Stream packet. + + @param npkts: how many 188-byte packets to return + + FYI, each ATSC Data Frame contains two Data Fields, each of which contains + 312 data segments. Each transport stream packet maps to a data segment. + """ + r = [0] * (npkts * 188) + i = 0 + for j in range(npkts): + r[i+0] = MPEG_SYNC_BYTE + r[i+1] = random.randint(0, 127) # top bit (transport error bit) clear + i = i + 2 + for n in range(186): + r[i + n] = random.randint(0, 255) + i = i + 186 + + return r + + +def pad_stream(src, sizeof_total, sizeof_pad): + sizeof_valid = sizeof_total - sizeof_pad + assert sizeof_valid > 0 + assert (len(src) % sizeof_valid) == 0 + npkts = len(src) // sizeof_valid + dst = [0] * (npkts * sizeof_total) + for i in range(npkts): + src_s = i * sizeof_valid + dst_s = i * sizeof_total + dst[dst_s:dst_s + sizeof_valid] = src[src_s:src_s + sizeof_valid] + return dst + + +def depad_stream(src, sizeof_total, sizeof_pad): + sizeof_valid = sizeof_total - sizeof_pad + assert sizeof_valid > 0 + assert (len(src) % sizeof_total) == 0 + npkts = len(src) // sizeof_total + dst = [0] * (npkts * sizeof_valid) + for i in range(npkts): + src_s = i * sizeof_total + dst_s = i * sizeof_valid + dst[dst_s:dst_s + sizeof_valid] = src[src_s:src_s + sizeof_valid] + return dst + + diff --git a/gr-atsc/src/python/qa_atsc.py b/gr-atsc/src/python/qa_atsc.py new file mode 100755 index 00000000..d9c94e19 --- /dev/null +++ b/gr-atsc/src/python/qa_atsc.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import atsc # qa code needs to run without being installed +#from gnuradio import atsc +from atsc_utils import * +import sys + + +class memoize(object): + def __init__(self, thunk): + self.thunk = thunk + self.cached = False + self.value = None + + def __call__(self): + if self.cached: + return self.value + self.value = self.thunk() + self.cached = True + return self.value + + +""" +Make a fake transport stream that's big enough for our purposes. +We generate 8 full fields. This is relatively expensive. It +takes about 2 seconds to execute. +""" +make_transport_stream = \ + memoize(lambda : tuple(make_fake_transport_stream_packet(8 * atsc.ATSC_DSEGS_PER_FIELD))) + + +def pad_transport_stream(src): + """ + An MPEG transport stream packet is 188 bytes long. Internally we use a packet + that is 256 bytes long to help with buffer alignment. This function adds the + appropriate trailing padding to convert each packet from 188 to 256 bytes. + """ + return pad_stream(src, atsc.sizeof_atsc_mpeg_packet, atsc.sizeof_atsc_mpeg_packet_pad) + + +def depad_transport_stream(src): + """ + An MPEG transport stream packet is 188 bytes long. Internally we use a packet + that is 256 bytes long to help with buffer alignment. This function removes the + trailing padding to convert each packet from 256 back to 188 bytes. + """ + return depad_stream(src, atsc.sizeof_atsc_mpeg_packet, atsc.sizeof_atsc_mpeg_packet_pad) + + +class vector_source_ts(gr.hier_block): + """ + MPEG Transport stream source for testing. + """ + def __init__(self, fg, ts): + """ + Pad tranport stream packets to 256 bytes and reformat appropriately. + + @param fg: flow graph + @param ts: MPEG transport stream. + @type ts: sequence of ints in [0,255]; len(ts) % 188 == 0 + """ + src = gr.vector_source_b(pad_transport_stream(ts)) + s2v = gr.stream_to_vector(gr.sizeof_char, atsc.sizeof_atsc_mpeg_packet) + fg.connect(src, s2v) + gr.hier_block.__init__(self, fg, None, s2v) + + +class vector_sink_ts(gr.hier_block): + """ + MPEG Transport stream sink for testing. + """ + def __init__(self, fg): + """ + @param fg: flow graph + """ + v2s = gr.vector_to_stream(gr.sizeof_char, atsc.sizeof_atsc_mpeg_packet) + self.sink = gr.vector_sink_b() + fg.connect(v2s, self.sink) + gr.hier_block.__init__(self, fg, v2s, None) + + def data(self): + """ + Extracts tranport stream from sink and returns it to python. + + Depads tranport stream packets from 256 back to 188 bytes. + @rtype: tuple of ints in [0,255]; len(result) % 188 == 0 + """ + return tuple(depad_transport_stream(self.sink.data())) + + + +class qa_atsc(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + + # The tests are run in alphabetical order + + def test_loopback_000(self): + """ + Loopback randomizer to derandomizer + """ + src_data = make_transport_stream() + expected_result = src_data + + src = vector_source_ts(self.fg, src_data) + rand = atsc.randomizer() + derand = atsc.derandomizer() + dst = vector_sink_ts(self.fg) + self.fg.connect(src, rand, derand, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + def test_loopback_001(self): + """ + Loopback randomizer/rs_encoder to rs_decoder/derandomizer + """ + src_data = make_transport_stream() + expected_result = src_data + + src = vector_source_ts(self.fg, src_data) + rand = atsc.randomizer() + rs_enc = atsc.rs_encoder() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + dst = vector_sink_ts(self.fg) + self.fg.connect(src, rand, rs_enc, rs_dec, derand, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + def test_loopback_002(self): + """ + Loopback randomizer/rs_encoder/interleaver to + deinterleaver/rs_decoder/derandomizer + """ + src_data = make_transport_stream() + interleaver_delay = 52 + expected_result = src_data[0:len(src_data)-(interleaver_delay*atsc.ATSC_MPEG_PKT_LENGTH)] + + src = vector_source_ts(self.fg, src_data) + rand = atsc.randomizer() + rs_enc = atsc.rs_encoder() + inter = atsc.interleaver() + deinter = atsc.deinterleaver() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + dst = vector_sink_ts(self.fg) + self.fg.connect(src, rand, rs_enc, inter, deinter, rs_dec, derand, dst) + self.fg.run () + result_data = dst.data () + result_data = result_data[(interleaver_delay*atsc.ATSC_MPEG_PKT_LENGTH):len(result_data)] + self.assertEqual (expected_result, result_data) + + + def test_loopback_003(self): + """ + Loopback randomizer/rs_encoder/interleaver/trellis_encoder + via ds_to_softds to + viterbi_decoder/deinterleaver/rs_decoder/derandomizer + """ + src_data = make_transport_stream() + interleaver_delay = 52 + viterbi_delay = 12 + expected_result = src_data[0:len(src_data)-((interleaver_delay+viterbi_delay)*atsc.ATSC_MPEG_PKT_LENGTH)] + + src = vector_source_ts(self.fg, src_data) + rand = atsc.randomizer() + rs_enc = atsc.rs_encoder() + inter = atsc.interleaver() + trellis = atsc.trellis_encoder() + softds = atsc.ds_to_softds() + viterbi = atsc.viterbi_decoder() + deinter = atsc.deinterleaver() + rs_dec = atsc.rs_decoder() + derand = atsc.derandomizer() + dst = vector_sink_ts(self.fg) + self.fg.connect(src, rand, rs_enc, inter, trellis, softds, viterbi, deinter, rs_dec, derand, dst) + self.fg.run () + result_data = dst.data ()[((interleaver_delay+viterbi_delay)*atsc.ATSC_MPEG_PKT_LENGTH):len(dst.data())] + self.assertEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main() + + + + + + diff --git a/gr-atsc/src/python/run_tests.in b/gr-atsc/src/python/run_tests.in new file mode 100644 index 00000000..b83d85bf --- /dev/null +++ b/gr-atsc/src/python/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-atsc/src/lib +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-atsc/src/lib +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-atsc/src/python + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-audio-alsa/AUTHORS b/gr-audio-alsa/AUTHORS new file mode 100644 index 00000000..65ca9014 --- /dev/null +++ b/gr-audio-alsa/AUTHORS @@ -0,0 +1,2 @@ +Eric Blossom +Ramakrishnan Muthukrishnan diff --git a/gr-audio-alsa/ChangeLog b/gr-audio-alsa/ChangeLog new file mode 100644 index 00000000..95e0c041 --- /dev/null +++ b/gr-audio-alsa/ChangeLog @@ -0,0 +1,88 @@ +2006-03-30 Eric Blossom + + * gr-audio-alsa.conf: new config file + * src/audio_alsa_source.{h,cc,i}, src/audio_alsa_sink.{h,cc,i}: + added ok_to_block ctor arg. Now use prefs for default devices, etc. + +2006-02-27 Eric Blossom + + * src/Makefile.am (audio_alsa.cc audio_alsa.py): added missing + dependency. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + +2005-06-18 Eric Blossom + + * src/audio_alsa_sink.cc (check_topology): set start threshold to + help avoid audio underruns. + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-01-29 Eric Blossom + + * src/Makefile.am: cleanup for SWIG 1.3.24 + +2005-01-17 Eric Blossom + + * src/audio_alsa_source.{h,cc}: emulate mono source even on + stereo-only hardware. + +2005-01-12 Eric Blossom + + * src/audio_alsa_source.cc,src/audio_alsa_sink.cc: overruns are + now indicated with aO, underruns with aU to distinguish them from + usrp under/overruns. + +2004-11-11 Eric Blossom + + * src/audio_alsa_source.cc (audio_alsa_source): working! + +2004-11-10 Eric Blossom + + * src/audio_alsa_sink.cc (audio_alsa_sink): working! + +2004-11-08 Eric Blossom + + * src/audio_alsa.i (audio_alsa_make_source): added throw + declarations so that swig generates the proper catch. + +2004-10-25 Ramakrishnan Muthukrishnan + + * playout works. But segfaults on exit. + * capture is untested. + +2004-10-23 Ramakrishnan Muthukrishnan + + * src/audio_oss_source.{h,cc}: first cut from oss sources. + * src/audio_oss_sink.{h,cc}: first cut from oss sources. + + +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-alsa/Makefile.am b/gr-audio-alsa/Makefile.am new file mode 100644 index 00000000..18a5dc46 --- /dev/null +++ b/gr-audio-alsa/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = gr-audio-alsa.conf + +SUBDIRS = src + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gr-audio-alsa.conf diff --git a/gr-audio-alsa/README b/gr-audio-alsa/README new file mode 100644 index 00000000..325759b2 --- /dev/null +++ b/gr-audio-alsa/README @@ -0,0 +1,4 @@ +N.B. This is currently a work-in-progress and is not ready for use. + +Stay tuned. It should be ready in a couple of days... + diff --git a/gr-audio-alsa/build-stamp b/gr-audio-alsa/build-stamp new file mode 100644 index 00000000..e69de29b diff --git a/gr-audio-alsa/gr-audio-alsa.conf b/gr-audio-alsa/gr-audio-alsa.conf new file mode 100644 index 00000000..5cec63e7 --- /dev/null +++ b/gr-audio-alsa/gr-audio-alsa.conf @@ -0,0 +1,11 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[audio_alsa] + +default_input_device = hw:0,0 +default_output_device = hw:0,0 +period_time = 0.010 # in seconds +nperiods = 4 # total buffering = period_time * nperiods +verbose = false diff --git a/gr-audio-alsa/src/Makefile.am b/gr-audio-alsa/src/Makefile.am new file mode 100644 index 00000000..e06fef9a --- /dev/null +++ b/gr-audio-alsa/src/Makefile.am @@ -0,0 +1,91 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.audio_alsa module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +LIBS += $(GNURADIO_CORE_LIBS) + +EXTRA_DIST = run_tests.in + +TESTS = run_tests + +LOCAL_IFILES = \ + audio_alsa.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_alsa.cc \ + audio_alsa.py + +ourpython_PYTHON = \ + audio_alsa.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) + +ourlib_LTLIBRARIES = _audio_alsa.la + +_audio_alsa_la_SOURCES = \ + audio_alsa.cc \ + audio_alsa_sink.cc \ + audio_alsa_source.cc \ + gri_alsa.cc + +grinclude_HEADERS = \ + audio_alsa_sink.h \ + audio_alsa_source.h + +noinst_HEADERS = \ + gri_alsa.h + + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_alsa_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +_audio_alsa_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +audio_alsa.cc audio_alsa.py: audio_alsa.i $(NON_LOCAL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module audio_alsa -o audio_alsa.cc $< + + +noinst_PYTHON = \ + qa_alsa.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc diff --git a/gr-audio-alsa/src/audio_alsa.i b/gr-audio-alsa/src/audio_alsa.i new file mode 100644 index 00000000..1cb13b83 --- /dev/null +++ b/gr-audio-alsa/src/audio_alsa.i @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_alsa_sink.h" +#include "audio_alsa_source.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_alsa,source) + +audio_alsa_source_sptr +audio_alsa_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_alsa_source : public gr_sync_block { + + protected: + audio_alsa_source (int sampling_rate, + const std::string device_name, + bool ok_to_block = true + ) throw (std::runtime_error); + + public: + ~audio_alsa_source (); + + bool start(); + bool stop(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_alsa,sink) + +audio_alsa_sink_sptr +audio_alsa_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_alsa_sink : public gr_sync_block { + + protected: + audio_alsa_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block + ) throw (std::runtime_error); + + public: + ~audio_alsa_sink (); +}; diff --git a/gr-audio-alsa/src/audio_alsa_sink.cc b/gr-audio-alsa/src/audio_alsa_sink.cc new file mode 100644 index 00000000..bdf9dbbe --- /dev/null +++ b/gr-audio-alsa/src/audio_alsa_sink.cc @@ -0,0 +1,538 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + + +static bool CHATTY_DEBUG = false; + + +static snd_pcm_format_t acceptable_formats[] = { + // these are in our preferred order... + SND_PCM_FORMAT_S32, + SND_PCM_FORMAT_S16 +}; + +#define NELEMS(x) (sizeof(x)/sizeof(x[0])) + + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_alsa", "default_output_device", "hw:0,0"); +} + +static double +default_period_time () +{ + return std::max(0.001, gr_prefs::singleton()->get_double("audio_alsa", "period_time", 0.010)); +} + +static int +default_nperiods () +{ + return std::max(2L, gr_prefs::singleton()->get_long("audio_alsa", "nperiods", 4)); +} + +// ---------------------------------------------------------------- + +audio_alsa_sink_sptr +audio_alsa_make_sink (int sampling_rate, + const std::string dev, + bool ok_to_block) +{ + return audio_alsa_sink_sptr (new audio_alsa_sink (sampling_rate, dev, + ok_to_block)); +} + +audio_alsa_sink::audio_alsa_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_alsa_sink", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_pcm_handle (0), + d_hw_params ((snd_pcm_hw_params_t *)(new char[snd_pcm_hw_params_sizeof()])), + d_sw_params ((snd_pcm_sw_params_t *)(new char[snd_pcm_sw_params_sizeof()])), + d_nperiods (default_nperiods()), + d_period_time_us ((unsigned int) (default_period_time() * 1e6)), + d_period_size (0), + d_buffer_size_bytes (0), d_buffer (0), + d_worker (0), d_special_case_mono_to_stereo (false), + d_nunderuns (0), d_nsuspends (0) +{ + CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false); + + int error; + int dir; + + // open the device for playback + error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str (), + SND_PCM_STREAM_PLAYBACK, 0); + if (error < 0){ + fprintf (stderr, "audio_alsa_sink[%s]: %s\n", + d_device_name.c_str(), snd_strerror(error)); + throw std::runtime_error ("audio_alsa_sink"); + } + + // Fill params with a full configuration space for a PCM. + error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params); + if (error < 0) + bail ("broken configuration for playback", error); + + + if (CHATTY_DEBUG) + gri_alsa_dump_hw_params (d_pcm_handle, d_hw_params, stdout); + + + // now that we know how many channels the h/w can handle, set input signature + unsigned int umin_chan, umax_chan; + snd_pcm_hw_params_get_channels_min (d_hw_params, &umin_chan); + snd_pcm_hw_params_get_channels_max (d_hw_params, &umax_chan); + int min_chan = std::min (umin_chan, 1000U); + int max_chan = std::min (umax_chan, 1000U); + + // As a special case, if the hw's min_chan is two, we'll accept + // a single input and handle the duplication ourselves. + + if (min_chan == 2){ + min_chan = 1; + d_special_case_mono_to_stereo = true; + } + set_input_signature (gr_make_io_signature (min_chan, max_chan, + sizeof (float))); + + // fill in portions of the d_hw_params that we know now... + + // Specify the access methods we implement + // For now, we only handle RW_INTERLEAVED... + snd_pcm_access_mask_t *access_mask; + snd_pcm_access_mask_alloca (&access_mask); + snd_pcm_access_mask_none (access_mask); + snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED); + // snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED); + + if ((error = snd_pcm_hw_params_set_access_mask (d_pcm_handle, + d_hw_params, access_mask)) < 0) + bail ("failed to set access mask", error); + + + // set sample format + if (!gri_alsa_pick_acceptable_format (d_pcm_handle, d_hw_params, + acceptable_formats, + NELEMS (acceptable_formats), + &d_format, + "audio_alsa_sink", + CHATTY_DEBUG)) + throw std::runtime_error ("audio_alsa_sink"); + + + // sampling rate + unsigned int orig_sampling_rate = d_sampling_rate; + if ((error = snd_pcm_hw_params_set_rate_near (d_pcm_handle, d_hw_params, + &d_sampling_rate, 0)) < 0) + bail ("failed to set rate near", error); + + if (orig_sampling_rate != d_sampling_rate){ + fprintf (stderr, "audio_alsa_sink[%s]: unable to support sampling rate %d\n", + snd_pcm_name (d_pcm_handle), orig_sampling_rate); + fprintf (stderr, " card requested %d instead.\n", d_sampling_rate); + } + + /* + * ALSA transfers data in units of "periods". + * We indirectly determine the underlying buffersize by specifying + * the number of periods we want (typically 4) and the length of each + * period in units of time (typically 1ms). + */ + unsigned int min_nperiods, max_nperiods; + snd_pcm_hw_params_get_periods_min (d_hw_params, &min_nperiods, &dir); + snd_pcm_hw_params_get_periods_max (d_hw_params, &max_nperiods, &dir); + //fprintf (stderr, "alsa_sink: min_nperiods = %d, max_nperiods = %d\n", + // min_nperiods, max_nperiods); + + unsigned int orig_nperiods = d_nperiods; + d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods); + + // adjust period time so that total buffering remains more-or-less constant + d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods; + + error = snd_pcm_hw_params_set_periods (d_pcm_handle, d_hw_params, + d_nperiods, 0); + if (error < 0) + bail ("set_periods failed", error); + + dir = 0; + error = snd_pcm_hw_params_set_period_time_near (d_pcm_handle, d_hw_params, + &d_period_time_us, &dir); + if (error < 0) + bail ("set_period_time_near failed", error); + + dir = 0; + error = snd_pcm_hw_params_get_period_size (d_hw_params, + &d_period_size, &dir); + if (error < 0) + bail ("get_period_size failed", error); + + set_output_multiple (d_period_size); +} + + +bool +audio_alsa_sink::check_topology (int ninputs, int noutputs) +{ + // ninputs is how many channels the user has connected. + // Now we can finish up setting up the hw params... + + int nchan = ninputs; + int err; + + // FIXME check_topology may be called more than once. + // Ensure that the pcm is in a state where we can still mess with the hw_params + + bool special_case = nchan == 1 && d_special_case_mono_to_stereo; + if (special_case) + nchan = 2; + + err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, nchan); + + if (err < 0){ + output_error_msg ("set_channels failed", err); + return false; + } + + // set the parameters into the driver... + err = snd_pcm_hw_params(d_pcm_handle, d_hw_params); + if (err < 0){ + output_error_msg ("snd_pcm_hw_params failed", err); + return false; + } + + // get current s/w params + err = snd_pcm_sw_params_current (d_pcm_handle, d_sw_params); + if (err < 0) + bail ("snd_pcm_sw_params_current", err); + + // Tell the PCM device to wait to start until we've filled + // it's buffers half way full. This helps avoid audio underruns. + + err = snd_pcm_sw_params_set_start_threshold(d_pcm_handle, + d_sw_params, + d_nperiods * d_period_size / 2); + if (err < 0) + bail ("snd_pcm_sw_params_set_start_threshold", err); + + // store the s/w params + err = snd_pcm_sw_params (d_pcm_handle, d_sw_params); + if (err < 0) + bail ("snd_pcm_sw_params", err); + + d_buffer_size_bytes = + d_period_size * nchan * snd_pcm_format_size (d_format, 1); + + d_buffer = new char [d_buffer_size_bytes]; + + if (CHATTY_DEBUG) + fprintf (stdout, "audio_alsa_sink[%s]: sample resolution = %d bits\n", + snd_pcm_name (d_pcm_handle), + snd_pcm_hw_params_get_sbits (d_hw_params)); + + switch (d_format){ + case SND_PCM_FORMAT_S16: + if (special_case) + d_worker = &audio_alsa_sink::work_s16_1x2; + else + d_worker = &audio_alsa_sink::work_s16; + break; + + case SND_PCM_FORMAT_S32: + if (special_case) + d_worker = &audio_alsa_sink::work_s32_1x2; + else + d_worker = &audio_alsa_sink::work_s32; + break; + + default: + assert (0); + } + + return true; +} + +audio_alsa_sink::~audio_alsa_sink () +{ + if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING) + snd_pcm_drop (d_pcm_handle); + + snd_pcm_close(d_pcm_handle); + delete [] ((char *) d_hw_params); + delete [] ((char *) d_sw_params); + delete [] d_buffer; +} + +int +audio_alsa_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert ((noutput_items % d_period_size) == 0); + + // this is a call through a pointer to a method... + return (this->*d_worker)(noutput_items, input_items, output_items); +} + +/* + * Work function that deals with float to S16 conversion + */ +int +audio_alsa_sink::work_s16 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int16 sample_t; // the type of samples we're creating + static const int NBITS = 16; // # of bits in a sample + + unsigned int nchan = input_items.size (); + const float **in = (const float **) &input_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + int n; + + unsigned int sizeof_frame = nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + for (n = 0; n < noutput_items; n += d_period_size){ + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + for (unsigned int chan = 0; chan < nchan; chan++){ + buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1)); + } + } + + // update src pointers + for (unsigned int chan = 0; chan < nchan; chan++) + in[chan] += d_period_size; + + if (!write_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + } + + return n; +} + + +/* + * Work function that deals with float to S32 conversion + */ +int +audio_alsa_sink::work_s32 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int32 sample_t; // the type of samples we're creating + static const int NBITS = 32; // # of bits in a sample + + unsigned int nchan = input_items.size (); + const float **in = (const float **) &input_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + int n; + + unsigned int sizeof_frame = nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + for (n = 0; n < noutput_items; n += d_period_size){ + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + for (unsigned int chan = 0; chan < nchan; chan++){ + buf[bi++] = (sample_t) (in[chan][i] * (float) ((1L << (NBITS-1)) - 1)); + } + } + + // update src pointers + for (unsigned int chan = 0; chan < nchan; chan++) + in[chan] += d_period_size; + + if (!write_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + } + + return n; +} + +/* + * Work function that deals with float to S16 conversion and + * mono to stereo kludge. + */ +int +audio_alsa_sink::work_s16_1x2 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int16 sample_t; // the type of samples we're creating + static const int NBITS = 16; // # of bits in a sample + + assert (input_items.size () == 1); + static const unsigned int nchan = 2; + const float **in = (const float **) &input_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + int n; + + unsigned int sizeof_frame = nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + for (n = 0; n < noutput_items; n += d_period_size){ + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1)); + buf[bi++] = t; + buf[bi++] = t; + } + + // update src pointers + in[0] += d_period_size; + + if (!write_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + } + + return n; +} + +/* + * Work function that deals with float to S32 conversion and + * mono to stereo kludge. + */ +int +audio_alsa_sink::work_s32_1x2 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int32 sample_t; // the type of samples we're creating + static const int NBITS = 32; // # of bits in a sample + + assert (input_items.size () == 1); + static unsigned int nchan = 2; + const float **in = (const float **) &input_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + int n; + + unsigned int sizeof_frame = nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + for (n = 0; n < noutput_items; n += d_period_size){ + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + sample_t t = (sample_t) (in[0][i] * (float) ((1L << (NBITS-1)) - 1)); + buf[bi++] = t; + buf[bi++] = t; + } + + // update src pointers + in[0] += d_period_size; + + if (!write_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + } + + return n; +} + +bool +audio_alsa_sink::write_buffer (const void *vbuffer, + unsigned nframes, unsigned sizeof_frame) +{ + const unsigned char *buffer = (const unsigned char *) vbuffer; + + while (nframes > 0){ + int r = snd_pcm_writei (d_pcm_handle, buffer, nframes); + if (r == -EAGAIN) + continue; // try again + + else if (r == -EPIPE){ // underrun + d_nunderuns++; + fputs ("aU", stderr); + if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){ + output_error_msg ("snd_pcm_prepare failed. Can't recover from underrun", r); + return false; + } + continue; // try again + } + + else if (r == -ESTRPIPE){ // h/w is suspended (whatever that means) + // This is apparently related to power management + d_nsuspends++; + if ((r = snd_pcm_resume (d_pcm_handle)) < 0){ + output_error_msg ("failed to resume from suspend", r); + return false; + } + continue; // try again + } + + else if (r < 0){ + output_error_msg ("snd_pcm_writei failed", r); + return false; + } + + nframes -= r; + buffer += r * sizeof_frame; + } + + return true; +} + + +void +audio_alsa_sink::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "audio_alsa_sink[%s]: %s: %s\n", + snd_pcm_name (d_pcm_handle), msg, snd_strerror (err)); +} + +void +audio_alsa_sink::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("audio_alsa_sink"); +} diff --git a/gr-audio-alsa/src/audio_alsa_sink.h b/gr-audio-alsa/src/audio_alsa_sink.h new file mode 100644 index 00000000..bb61e49a --- /dev/null +++ b/gr-audio-alsa/src/audio_alsa_sink.h @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_ALSA_SINK_H +#define INCLUDED_AUDIO_ALSA_SINK_H + +// use new ALSA API +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API + +#include +#include +#include +#include + + +class audio_alsa_sink; +typedef boost::shared_ptr audio_alsa_sink_sptr; + +/*! + * \brief make an alsa audio sink. + * + * \param sampling_rate sampling rate in Hz + * \param dev ALSA pcm device name, e.g., "hw:0,0" + * \param ok_to_block (currently ignored) + */ +audio_alsa_sink_sptr +audio_alsa_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +/*! + * \brief audio sink using ALSA + * + * The sink has N input streams of floats, where N depends + * on the hardware characteristics of the selected device. + * + * Input samples must be in the range [-1,1]. + */ +class audio_alsa_sink : public gr_sync_block { + friend audio_alsa_sink_sptr + audio_alsa_make_sink (int sampling_rate, const std::string device_name, + bool ok_to_block); + + // typedef for pointer to class work method + typedef int (audio_alsa_sink::*work_t)(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int d_sampling_rate; + std::string d_device_name; + snd_pcm_t *d_pcm_handle; + snd_pcm_hw_params_t *d_hw_params; + snd_pcm_sw_params_t *d_sw_params; + snd_pcm_format_t d_format; + unsigned int d_nperiods; + unsigned int d_period_time_us; // microseconds + snd_pcm_uframes_t d_period_size; // in frames + unsigned int d_buffer_size_bytes; // sizeof of d_buffer + char *d_buffer; + work_t d_worker; // the work method to use + bool d_special_case_mono_to_stereo; + + // random stats + int d_nunderuns; // count of underruns + int d_nsuspends; // count of suspends + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + + protected: + audio_alsa_sink (int sampling_rate, const std::string device_name, + bool ok_to_block); + + public: + ~audio_alsa_sink (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + +protected: + bool write_buffer (const void *buffer, unsigned nframes, unsigned sizeof_frame); + + int work_s16 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work_s16_1x2 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work_s32 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work_s32_1x2 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_ALSA_SINK_H */ diff --git a/gr-audio-alsa/src/audio_alsa_source.cc b/gr-audio-alsa/src/audio_alsa_source.cc new file mode 100644 index 00000000..4e7ee94b --- /dev/null +++ b/gr-audio-alsa/src/audio_alsa_source.cc @@ -0,0 +1,506 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + + +static bool CHATTY_DEBUG = false; + +static snd_pcm_format_t acceptable_formats[] = { + // these are in our preferred order... + SND_PCM_FORMAT_S32, + SND_PCM_FORMAT_S16 +}; + +#define NELEMS(x) (sizeof(x)/sizeof(x[0])) + + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_alsa", "default_input_device", "hw:0,0"); +} + +static double +default_period_time () +{ + return std::max(0.001, gr_prefs::singleton()->get_double("audio_alsa", "period_time", 0.010)); +} + +static int +default_nperiods () +{ + return std::max(2L, gr_prefs::singleton()->get_long("audio_alsa", "nperiods", 4)); +} + +// ---------------------------------------------------------------- + +audio_alsa_source_sptr +audio_alsa_make_source (int sampling_rate, const std::string dev, + bool ok_to_block) +{ + return audio_alsa_source_sptr (new audio_alsa_source (sampling_rate, dev, + ok_to_block)); +} + +audio_alsa_source::audio_alsa_source (int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_alsa_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_pcm_handle (0), + d_hw_params ((snd_pcm_hw_params_t *)(new char[snd_pcm_hw_params_sizeof()])), + d_sw_params ((snd_pcm_sw_params_t *)(new char[snd_pcm_sw_params_sizeof()])), + d_nperiods (default_nperiods()), + d_period_time_us ((unsigned int) (default_period_time() * 1e6)), + d_period_size (0), + d_buffer_size_bytes (0), d_buffer (0), + d_worker (0), d_hw_nchan (0), + d_special_case_stereo_to_mono (false), + d_noverruns (0), d_nsuspends (0) +{ + + CHATTY_DEBUG = gr_prefs::singleton()->get_bool("audio_alsa", "verbose", false); + + int error; + int dir; + + // open the device for capture + error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str (), + SND_PCM_STREAM_CAPTURE, 0); + if (error < 0){ + fprintf (stderr, "audio_alsa_source[%s]: %s\n", + d_device_name.c_str(), snd_strerror(error)); + throw std::runtime_error ("audio_alsa_source"); + } + + // Fill params with a full configuration space for a PCM. + error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params); + if (error < 0) + bail ("broken configuration for playback", error); + + if (CHATTY_DEBUG) + gri_alsa_dump_hw_params (d_pcm_handle, d_hw_params, stdout); + + // now that we know how many channels the h/w can handle, set output signature + unsigned int umax_chan; + unsigned int umin_chan; + snd_pcm_hw_params_get_channels_min (d_hw_params, &umin_chan); + snd_pcm_hw_params_get_channels_max (d_hw_params, &umax_chan); + int min_chan = std::min (umin_chan, 1000U); + int max_chan = std::min (umax_chan, 1000U); + + // As a special case, if the hw's min_chan is two, we'll accept + // a single output and handle the demux ourselves. + + if (min_chan == 2){ + min_chan = 1; + d_special_case_stereo_to_mono = true; + } + + set_output_signature (gr_make_io_signature (min_chan, max_chan, + sizeof (float))); + + // fill in portions of the d_hw_params that we know now... + + // Specify the access methods we implement + // For now, we only handle RW_INTERLEAVED... + snd_pcm_access_mask_t *access_mask; + snd_pcm_access_mask_alloca (&access_mask); + snd_pcm_access_mask_none (access_mask); + snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_INTERLEAVED); + // snd_pcm_access_mask_set (access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED); + + if ((error = snd_pcm_hw_params_set_access_mask (d_pcm_handle, + d_hw_params, access_mask)) < 0) + bail ("failed to set access mask", error); + + + // set sample format + if (!gri_alsa_pick_acceptable_format (d_pcm_handle, d_hw_params, + acceptable_formats, + NELEMS (acceptable_formats), + &d_format, + "audio_alsa_source", + CHATTY_DEBUG)) + throw std::runtime_error ("audio_alsa_source"); + + + // sampling rate + unsigned int orig_sampling_rate = d_sampling_rate; + if ((error = snd_pcm_hw_params_set_rate_near (d_pcm_handle, d_hw_params, + &d_sampling_rate, 0)) < 0) + bail ("failed to set rate near", error); + + if (orig_sampling_rate != d_sampling_rate){ + fprintf (stderr, "audio_alsa_source[%s]: unable to support sampling rate %d\n", + snd_pcm_name (d_pcm_handle), orig_sampling_rate); + fprintf (stderr, " card requested %d instead.\n", d_sampling_rate); + } + + /* + * ALSA transfers data in units of "periods". + * We indirectly determine the underlying buffersize by specifying + * the number of periods we want (typically 4) and the length of each + * period in units of time (typically 1ms). + */ + unsigned int min_nperiods, max_nperiods; + snd_pcm_hw_params_get_periods_min (d_hw_params, &min_nperiods, &dir); + snd_pcm_hw_params_get_periods_max (d_hw_params, &max_nperiods, &dir); + //fprintf (stderr, "alsa_source: min_nperiods = %d, max_nperiods = %d\n", + // min_nperiods, max_nperiods); + + + unsigned int orig_nperiods = d_nperiods; + d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods); + + // adjust period time so that total buffering remains more-or-less constant + d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods; + + error = snd_pcm_hw_params_set_periods (d_pcm_handle, d_hw_params, + d_nperiods, 0); + if (error < 0) + bail ("set_periods failed", error); + + dir = 0; + error = snd_pcm_hw_params_set_period_time_near (d_pcm_handle, d_hw_params, + &d_period_time_us, &dir); + if (error < 0) + bail ("set_period_time_near failed", error); + + dir = 0; + error = snd_pcm_hw_params_get_period_size (d_hw_params, + &d_period_size, &dir); + if (error < 0) + bail ("get_period_size failed", error); + + set_output_multiple (d_period_size); +} + +bool +audio_alsa_source::check_topology (int ninputs, int noutputs) +{ + // noutputs is how many channels the user has connected. + // Now we can finish up setting up the hw params... + + unsigned int nchan = noutputs; + int err; + + // FIXME check_topology may be called more than once. + // Ensure that the pcm is in a state where we can still mess with the hw_params + + bool special_case = nchan == 1 && d_special_case_stereo_to_mono; + if (special_case) + nchan = 2; + + d_hw_nchan = nchan; + err = snd_pcm_hw_params_set_channels (d_pcm_handle, d_hw_params, d_hw_nchan); + if (err < 0){ + output_error_msg ("set_channels failed", err); + return false; + } + + // set the parameters into the driver... + err = snd_pcm_hw_params(d_pcm_handle, d_hw_params); + if (err < 0){ + output_error_msg ("snd_pcm_hw_params failed", err); + return false; + } + + d_buffer_size_bytes = + d_period_size * d_hw_nchan * snd_pcm_format_size (d_format, 1); + + d_buffer = new char [d_buffer_size_bytes]; + + if (CHATTY_DEBUG) + fprintf (stdout, "audio_alsa_source[%s]: sample resolution = %d bits\n", + snd_pcm_name (d_pcm_handle), + snd_pcm_hw_params_get_sbits (d_hw_params)); + + switch (d_format){ + case SND_PCM_FORMAT_S16: + if (special_case) + d_worker = &audio_alsa_source::work_s16_2x1; + else + d_worker = &audio_alsa_source::work_s16; + break; + + case SND_PCM_FORMAT_S32: + if (special_case) + d_worker = &audio_alsa_source::work_s32_2x1; + else + d_worker = &audio_alsa_source::work_s32; + break; + + default: + assert (0); + } + + return true; +} + +audio_alsa_source::~audio_alsa_source () +{ + if (snd_pcm_state (d_pcm_handle) == SND_PCM_STATE_RUNNING) + snd_pcm_drop (d_pcm_handle); + + snd_pcm_close(d_pcm_handle); + delete [] ((char *) d_hw_params); + delete [] ((char *) d_sw_params); + delete [] d_buffer; +} + +int +audio_alsa_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert ((noutput_items % d_period_size) == 0); + assert (noutput_items != 0); + + // this is a call through a pointer to a method... + return (this->*d_worker)(noutput_items, input_items, output_items); +} + +/* + * Work function that deals with float to S16 conversion + */ +int +audio_alsa_source::work_s16 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int16 sample_t; // the type of samples we're creating + static const int NBITS = 16; // # of bits in a sample + + unsigned int nchan = output_items.size (); + float **out = (float **) &output_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + + unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + // To minimize latency, return at most a single period's worth of samples. + // [We could also read the first one in a blocking mode and subsequent + // ones in non-blocking mode, but we'll leave that for later (or never).] + + if (!read_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + for (unsigned int chan = 0; chan < nchan; chan++){ + out[chan][i] = (float) buf[bi++] * (1.0 / (float) ((1L << (NBITS-1)) - 1)); + } + } + + return d_period_size; +} + +/* + * Work function that deals with float to S16 conversion + * and stereo to mono kludge... + */ +int +audio_alsa_source::work_s16_2x1 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int16 sample_t; // the type of samples we're creating + static const int NBITS = 16; // # of bits in a sample + + unsigned int nchan = output_items.size (); + float **out = (float **) &output_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + + assert (nchan == 1); + + unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + // To minimize latency, return at most a single period's worth of samples. + // [We could also read the first one in a blocking mode and subsequent + // ones in non-blocking mode, but we'll leave that for later (or never).] + + if (!read_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + int t = (buf[bi] + buf[bi+1]) / 2; + bi += 2; + out[0][i] = (float) t * (1.0 / (float) ((1L << (NBITS-1)) - 1)); + } + + return d_period_size; +} + +/* + * Work function that deals with float to S32 conversion + */ +int +audio_alsa_source::work_s32 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int32 sample_t; // the type of samples we're creating + static const int NBITS = 32; // # of bits in a sample + + unsigned int nchan = output_items.size (); + float **out = (float **) &output_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + + unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + // To minimize latency, return at most a single period's worth of samples. + // [We could also read the first one in a blocking mode and subsequent + // ones in non-blocking mode, but we'll leave that for later (or never).] + + if (!read_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + for (unsigned int chan = 0; chan < nchan; chan++){ + out[chan][i] = (float) buf[bi++] * (1.0 / (float) ((1L << (NBITS-1)) - 1)); + } + } + + return d_period_size; +} + +/* + * Work function that deals with float to S32 conversion + * and stereo to mono kludge... + */ +int +audio_alsa_source::work_s32_2x1 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + typedef gr_int32 sample_t; // the type of samples we're creating + static const int NBITS = 32; // # of bits in a sample + + unsigned int nchan = output_items.size (); + float **out = (float **) &output_items[0]; + sample_t *buf = (sample_t *) d_buffer; + int bi; + + assert (nchan == 1); + + unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t); + assert (d_buffer_size_bytes == d_period_size * sizeof_frame); + + // To minimize latency, return at most a single period's worth of samples. + // [We could also read the first one in a blocking mode and subsequent + // ones in non-blocking mode, but we'll leave that for later (or never).] + + if (!read_buffer (buf, d_period_size, sizeof_frame)) + return -1; // No fixing this problem. Say we're done. + + // process one period of data + bi = 0; + for (unsigned int i = 0; i < d_period_size; i++){ + int t = (buf[bi] + buf[bi+1]) / 2; + bi += 2; + out[0][i] = (float) t * (1.0 / (float) ((1L << (NBITS-1)) - 1)); + } + + return d_period_size; +} + +bool +audio_alsa_source::read_buffer (void *vbuffer, unsigned nframes, unsigned sizeof_frame) +{ + unsigned char *buffer = (unsigned char *) vbuffer; + + while (nframes > 0){ + int r = snd_pcm_readi (d_pcm_handle, buffer, nframes); + if (r == -EAGAIN) + continue; // try again + + else if (r == -EPIPE){ // overrun + d_noverruns++; + fputs ("aO", stderr); + if ((r = snd_pcm_prepare (d_pcm_handle)) < 0){ + output_error_msg ("snd_pcm_prepare failed. Can't recover from overrun", r); + return false; + } + continue; // try again + } + + else if (r == -ESTRPIPE){ // h/w is suspended (whatever that means) + // This is apparently related to power management + d_nsuspends++; + if ((r = snd_pcm_resume (d_pcm_handle)) < 0){ + output_error_msg ("failed to resume from suspend", r); + return false; + } + continue; // try again + } + + else if (r < 0){ + output_error_msg ("snd_pcm_readi failed", r); + return false; + } + + nframes -= r; + buffer += r * sizeof_frame; + } + + return true; +} + + +void +audio_alsa_source::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "audio_alsa_source[%s]: %s: %s\n", + snd_pcm_name (d_pcm_handle), msg, snd_strerror (err)); +} + +void +audio_alsa_source::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("audio_alsa_source"); +} diff --git a/gr-audio-alsa/src/audio_alsa_source.h b/gr-audio-alsa/src/audio_alsa_source.h new file mode 100644 index 00000000..cc1ae116 --- /dev/null +++ b/gr-audio-alsa/src/audio_alsa_source.h @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_ALSA_SOURCE_H +#define INCLUDED_AUDIO_ALSA_SOURCE_H + +// use new ALSA API +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API + +#include +#include +#include +#include + +class audio_alsa_source; +typedef boost::shared_ptr audio_alsa_source_sptr; + +/*! + * \brief Make an ALSA audio source. + * + * \param sampling_rate sampling rate + * \param dev ALSA pcm device name, e.g., "hw:0,0" + * \param ok_to_block (currently ignored) + */ +audio_alsa_source_sptr +audio_alsa_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +/*! + * \brief audio source using ALSA + * + * The source has between 1 and N input streams of floats, where N is + * depends on the hardware characteristics of the selected device. + * + * Output samples will be in the range [-1,1]. + */ +class audio_alsa_source : public gr_sync_block { + friend audio_alsa_source_sptr + audio_alsa_make_source (int sampling_rate, + const std::string device_name, + bool ok_to_block); + + // typedef for pointer to class work method + typedef int (audio_alsa_source::*work_t)(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int d_sampling_rate; + std::string d_device_name; + snd_pcm_t *d_pcm_handle; + snd_pcm_hw_params_t *d_hw_params; + snd_pcm_sw_params_t *d_sw_params; + snd_pcm_format_t d_format; + unsigned int d_nperiods; + unsigned int d_period_time_us; // microseconds + snd_pcm_uframes_t d_period_size; // in frames + unsigned int d_buffer_size_bytes; // sizeof of d_buffer + char *d_buffer; + work_t d_worker; // the work method to use + unsigned int d_hw_nchan; // # of configured h/w channels + bool d_special_case_stereo_to_mono; + + // random stats + int d_noverruns; // count of overruns + int d_nsuspends; // count of suspends + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + + protected: + audio_alsa_source (int sampling_rate, const std::string device_name, + bool ok_to_block); + + public: + ~audio_alsa_source (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +protected: + bool read_buffer (void *buffer, unsigned nframes, unsigned sizeof_frame); + + int work_s16 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work_s16_2x1 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work_s32 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work_s32_2x1 (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_ALSA_SOURCE_H */ diff --git a/gr-audio-alsa/src/gri_alsa.cc b/gr-audio-alsa/src/gri_alsa.cc new file mode 100644 index 00000000..25ff7f65 --- /dev/null +++ b/gr-audio-alsa/src/gri_alsa.cc @@ -0,0 +1,175 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static snd_pcm_access_t access_types[] = { + SND_PCM_ACCESS_MMAP_INTERLEAVED, + SND_PCM_ACCESS_MMAP_NONINTERLEAVED, + SND_PCM_ACCESS_MMAP_COMPLEX, + SND_PCM_ACCESS_RW_INTERLEAVED, + SND_PCM_ACCESS_RW_NONINTERLEAVED +}; + +static snd_pcm_format_t format_types[] = { + // SND_PCM_FORMAT_UNKNOWN, + SND_PCM_FORMAT_S8, + SND_PCM_FORMAT_U8, + SND_PCM_FORMAT_S16_LE, + SND_PCM_FORMAT_S16_BE, + SND_PCM_FORMAT_U16_LE, + SND_PCM_FORMAT_U16_BE, + SND_PCM_FORMAT_S24_LE, + SND_PCM_FORMAT_S24_BE, + SND_PCM_FORMAT_U24_LE, + SND_PCM_FORMAT_U24_BE, + SND_PCM_FORMAT_S32_LE, + SND_PCM_FORMAT_S32_BE, + SND_PCM_FORMAT_U32_LE, + SND_PCM_FORMAT_U32_BE, + SND_PCM_FORMAT_FLOAT_LE, + SND_PCM_FORMAT_FLOAT_BE, + SND_PCM_FORMAT_FLOAT64_LE, + SND_PCM_FORMAT_FLOAT64_BE, + SND_PCM_FORMAT_IEC958_SUBFRAME_LE, + SND_PCM_FORMAT_IEC958_SUBFRAME_BE, + SND_PCM_FORMAT_MU_LAW, + SND_PCM_FORMAT_A_LAW, + SND_PCM_FORMAT_IMA_ADPCM, + SND_PCM_FORMAT_MPEG, + SND_PCM_FORMAT_GSM, + SND_PCM_FORMAT_SPECIAL, + SND_PCM_FORMAT_S24_3LE, + SND_PCM_FORMAT_S24_3BE, + SND_PCM_FORMAT_U24_3LE, + SND_PCM_FORMAT_U24_3BE, + SND_PCM_FORMAT_S20_3LE, + SND_PCM_FORMAT_S20_3BE, + SND_PCM_FORMAT_U20_3LE, + SND_PCM_FORMAT_U20_3BE, + SND_PCM_FORMAT_S18_3LE, + SND_PCM_FORMAT_S18_3BE, + SND_PCM_FORMAT_U18_3LE, + SND_PCM_FORMAT_U18_3BE +}; + +static unsigned int test_rates[] = { + 8000, 16000, 22050, 32000, 44100, 48000, 96000, 192000 +}; + +#define NELEMS(x) (sizeof(x)/sizeof(x[0])) + +void +gri_alsa_dump_hw_params (snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, FILE *fp) +{ + fprintf (fp, "PCM name: %s\n", snd_pcm_name (pcm)); + + fprintf (fp, "Access types:\n"); + for (unsigned i = 0; i < NELEMS (access_types); i++){ + snd_pcm_access_t at = access_types[i]; + fprintf (fp, " %-20s %s\n", + snd_pcm_access_name (at), + snd_pcm_hw_params_test_access (pcm, hwparams, at) == 0 ? "YES" : "NO"); + } + + fprintf (fp, "Formats:\n"); + for (unsigned i = 0; i < NELEMS (format_types); i++){ + snd_pcm_format_t ft = format_types[i]; + if (0) + fprintf (fp, " %-20s %s\n", + snd_pcm_format_name (ft), + snd_pcm_hw_params_test_format (pcm, hwparams, ft) == 0 ? "YES" : "NO"); + else { + if (snd_pcm_hw_params_test_format (pcm, hwparams, ft) == 0) + fprintf (fp, " %-20s YES\n", snd_pcm_format_name (ft)); + } + } + + fprintf (fp, "Number of channels\n"); + unsigned int min_chan, max_chan; + snd_pcm_hw_params_get_channels_min (hwparams, &min_chan); + snd_pcm_hw_params_get_channels_max (hwparams, &max_chan); + fprintf (fp, " min channels: %d\n", min_chan); + fprintf (fp, " max channels: %d\n", max_chan); + unsigned int chan; + max_chan = std::min (max_chan, 16U); // truncate display... + for (chan = min_chan; chan <= max_chan; chan++){ + fprintf (fp, " %d channels\t%s\n", chan, + snd_pcm_hw_params_test_channels (pcm, hwparams, chan) == 0 ? "YES" : "NO"); + } + + fprintf (fp, "Sample Rates:\n"); + unsigned int min_rate, max_rate; + int min_dir, max_dir; + + snd_pcm_hw_params_get_rate_min (hwparams, &min_rate, &min_dir); + snd_pcm_hw_params_get_rate_max (hwparams, &max_rate, &max_dir); + fprintf (fp, " min rate: %7d (dir = %d)\n", min_rate, min_dir); + fprintf (fp, " max rate: %7d (dir = %d)\n", max_rate, max_dir); + for (unsigned i = 0; i < NELEMS (test_rates); i++){ + unsigned int rate = test_rates[i]; + fprintf (fp, " %6u %s\n", rate, + snd_pcm_hw_params_test_rate (pcm, hwparams, rate, 0) == 0 ? "YES" : "NO"); + } + + fflush (fp); +} + +bool +gri_alsa_pick_acceptable_format (snd_pcm_t *pcm, + snd_pcm_hw_params_t *hwparams, + snd_pcm_format_t acceptable_formats[], + unsigned nacceptable_formats, + snd_pcm_format_t *selected_format, + const char *error_msg_tag, + bool verbose) +{ + int err; + + // pick a format that we like... + for (unsigned i = 0; i < nacceptable_formats; i++){ + if (snd_pcm_hw_params_test_format (pcm, hwparams, + acceptable_formats[i]) == 0){ + err = snd_pcm_hw_params_set_format (pcm, hwparams, acceptable_formats[i]); + if (err < 0){ + fprintf (stderr, "%s[%s]: failed to set format: %s\n", + error_msg_tag, snd_pcm_name (pcm), snd_strerror (err)); + return false; + } + if (verbose) + fprintf (stdout, "%s[%s]: using %s\n", + error_msg_tag, snd_pcm_name (pcm), + snd_pcm_format_name (acceptable_formats[i])); + *selected_format = acceptable_formats[i]; + return true; + } + } + + fprintf (stderr, "%s[%s]: failed to find acceptable format", + error_msg_tag, snd_pcm_name (pcm)); + return false; +} diff --git a/gr-audio-alsa/src/gri_alsa.h b/gr-audio-alsa/src/gri_alsa.h new file mode 100644 index 00000000..841c54d4 --- /dev/null +++ b/gr-audio-alsa/src/gri_alsa.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_ALSA_H +#define INCLUDED_GRI_ALSA_H + +#include +#include + +void +gri_alsa_dump_hw_params (snd_pcm_t *pcm, + snd_pcm_hw_params_t *hwparams, + FILE *fp); + +bool +gri_alsa_pick_acceptable_format (snd_pcm_t *pcm, + snd_pcm_hw_params_t *hwparams, + snd_pcm_format_t acceptable_formats[], + unsigned nacceptable_formats, + snd_pcm_format_t *selected_format, + const char *error_msg_tag, + bool verbose); + + +#endif /* INCLUDED_GRI_ALSA_H */ diff --git a/gr-audio-alsa/src/qa_alsa.py b/gr-audio-alsa/src/qa_alsa.py new file mode 100755 index 00000000..2994573d --- /dev/null +++ b/gr-audio-alsa/src/qa_alsa.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_alsa + +class qa_alsa (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have ALSA drivers, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-alsa/src/run_tests.in b/gr-audio-alsa/src/run_tests.in new file mode 100644 index 00000000..4bfb076e --- /dev/null +++ b/gr-audio-alsa/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-alsa/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-alsa/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-alsa/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-audio-jack/AUTHORS b/gr-audio-jack/AUTHORS new file mode 100644 index 00000000..624606f0 --- /dev/null +++ b/gr-audio-jack/AUTHORS @@ -0,0 +1 @@ +Stephane Fillod diff --git a/gr-audio-jack/ChangeLog b/gr-audio-jack/ChangeLog new file mode 100644 index 00000000..3851f66a --- /dev/null +++ b/gr-audio-jack/ChangeLog @@ -0,0 +1,42 @@ +2006-03-30 Eric Blossom + + * gr-audio-jack.conf: new config file. + * src/audio_jack_source.{h,cc}, src/audio_jack_sink.{h,cc}: added + ok_to_block ctor argument (currently ignored). Also query prefs + for default input and output device names. + +2005-10-13 Stephane Fillod + + * src/audio_jack_{source,sink}.cc: don't use jack_get_client_name + since older jack versions don't have it. + +2005-10-09 Stephane Fillod + + * src/audio_jack_{source,sink}.cc: fix, don't retrieve jack buffer + when ringbuffer overflows/underflows. + +2005-09-30 Stephane Fillod + + * src/audio_jack_source.{h,cc}: new. + * src/audio_jack_sink.{h,cc}: new. + +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-jack/Makefile.am b/gr-audio-jack/Makefile.am new file mode 100644 index 00000000..329f5692 --- /dev/null +++ b/gr-audio-jack/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = gr-audio-jack.conf +SUBDIRS = src + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gr-audio-jack.conf diff --git a/gr-audio-jack/gr-audio-jack.conf b/gr-audio-jack/gr-audio-jack.conf new file mode 100644 index 00000000..bdbc1fd1 --- /dev/null +++ b/gr-audio-jack/gr-audio-jack.conf @@ -0,0 +1,8 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[audio_jack] + +default_input_device = gr_source +default_output_device = gr_sink diff --git a/gr-audio-jack/src/Makefile.am b/gr-audio-jack/src/Makefile.am new file mode 100644 index 00000000..a00e574c --- /dev/null +++ b/gr-audio-jack/src/Makefile.am @@ -0,0 +1,98 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +LIBS += $(GNURADIO_CORE_LIBS) + +# Install this stuff so that it ends up as the gnuradio.audio_jack module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in + +TESTS = run_tests + +LOCAL_IFILES = \ + audio_jack.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_jack.cc \ + audio_jack.py + +ourpython_PYTHON = \ + audio_jack.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) + + +ourlib_LTLIBRARIES = _audio_jack.la + + +_audio_jack_la_SOURCES = \ + audio_jack.cc \ + audio_jack_sink.cc \ + audio_jack_source.cc \ + gri_jack.cc + +grinclude_HEADERS = \ + audio_jack_sink.h \ + audio_jack_source.h + +noinst_HEADERS = \ + gri_jack.h + + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_jack_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +_audio_jack_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +audio_jack.cc audio_jack.py: audio_jack.i $(NON_LOCAL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module audio_jack -o audio_jack.cc $< + + +noinst_PYTHON = \ + qa_jack.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done diff --git a/gr-audio-jack/src/audio_jack.i b/gr-audio-jack/src/audio_jack.i new file mode 100644 index 00000000..1a210661 --- /dev/null +++ b/gr-audio-jack/src/audio_jack.i @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_jack_sink.h" +#include "audio_jack_source.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_jack,source) + +audio_jack_source_sptr +audio_jack_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_jack_source : public gr_sync_block { + + protected: + audio_jack_source (int sampling_rate, + const std::string device_name, + bool ok_to_block + ) throw (std::runtime_error); + + public: + ~audio_jack_source (); + + bool start(); + bool stop(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_jack,sink) + +audio_jack_sink_sptr +audio_jack_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_jack_sink : public gr_sync_block { + + protected: + audio_jack_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block + ) throw (std::runtime_error); + + public: + ~audio_jack_sink (); +}; diff --git a/gr-audio-jack/src/audio_jack_sink.cc b/gr-audio-jack/src/audio_jack_sink.cc new file mode 100644 index 00000000..b5a8373e --- /dev/null +++ b/gr-audio-jack/src/audio_jack_sink.cc @@ -0,0 +1,231 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef NO_PTHREAD +#include +#endif + +typedef jack_default_audio_sample_t sample_t; + + +// Number of jack buffers in the ringbuffer +// TODO: make it to match at least the quantity of items passed by work() +static const unsigned int N_BUFFERS = 16; + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_jack", "default_output_device", "gr_sink"); +} + +int +jack_sink_process (jack_nframes_t nframes, void *arg) +{ + audio_jack_sink *self = (audio_jack_sink *)arg; + unsigned int read_size = nframes*sizeof(sample_t); + + if (jack_ringbuffer_read_space (self->d_ringbuffer) < read_size) { + self->d_nunderuns++; + // FIXME: move this fputs out, we shouldn't use blocking calls in process() + fputs ("jU", stderr); + return 0; + } + + char *buffer = (char *) jack_port_get_buffer (self->d_jack_output_port, nframes); + + jack_ringbuffer_read (self->d_ringbuffer, buffer, read_size); + +#ifndef NO_PTHREAD + // Tell the sink thread there is room in the ringbuffer. + // If it is already running, the lock will not be available. + // We can't wait here in the process() thread, but we don't + // need to signal in that case, because the sink thread will + // check for room availability. + + if (pthread_mutex_trylock (&self->d_jack_process_lock) == 0) { + pthread_cond_signal (&self->d_ringbuffer_ready); + pthread_mutex_unlock (&self->d_jack_process_lock); + } +#endif + + return 0; +} + +// ---------------------------------------------------------------- + +audio_jack_sink_sptr +audio_jack_make_sink(int sampling_rate, const std::string dev, bool ok_to_block) +{ + return audio_jack_sink_sptr (new audio_jack_sink (sampling_rate, dev, + ok_to_block)); +} + +audio_jack_sink::audio_jack_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_jack_sink", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_ok_to_block (ok_to_block), + d_jack_client (0), + d_ringbuffer (0), + d_nunderuns (0) +{ +#ifndef NO_PTHREAD + pthread_cond_init(&d_ringbuffer_ready, NULL);; + pthread_mutex_init(&d_jack_process_lock, NULL); +#endif + + // try to become a client of the JACK server + if ((d_jack_client = jack_client_new (d_device_name.c_str ())) == 0) { + fprintf (stderr, "audio_jack_sink[%s]: jack server not running?\n", + d_device_name.c_str()); + throw std::runtime_error ("audio_jack_sink"); + } + + // tell the JACK server to call `jack_sink_process()' whenever + // there is work to be done. + jack_set_process_callback (d_jack_client, &jack_sink_process, (void*)this); + + // tell the JACK server to call `jack_shutdown()' if + // it ever shuts down, either entirely, or if it + // just decides to stop calling us. + + //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this); + + d_jack_output_port = + jack_port_register (d_jack_client, "out", + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + + d_jack_buffer_size = jack_get_buffer_size (d_jack_client); + + set_output_multiple (d_jack_buffer_size); + + d_ringbuffer = + jack_ringbuffer_create (N_BUFFERS*d_jack_buffer_size*sizeof(sample_t)); + if (d_ringbuffer == NULL) + bail ("jack_ringbuffer_create failed", 0); + + assert(sizeof(float)==sizeof(sample_t)); + set_input_signature (gr_make_io_signature (1, 1, sizeof (sample_t))); + + + jack_nframes_t sample_rate = jack_get_sample_rate (d_jack_client); + + if ((jack_nframes_t)sampling_rate != sample_rate){ + fprintf (stderr, "audio_jack_sink[%s]: unable to support sampling rate %d\n", + d_device_name.c_str (), sampling_rate); + fprintf (stderr, " card requested %d instead.\n", sample_rate); + } +} + + +bool +audio_jack_sink::check_topology (int ninputs, int noutputs) +{ + if (ninputs != 1) + return false; + + // tell the JACK server that we are ready to roll + if (jack_activate (d_jack_client)) + throw std::runtime_error ("audio_jack_sink"); + + return true; +} + +audio_jack_sink::~audio_jack_sink () +{ + jack_client_close (d_jack_client); + jack_ringbuffer_free (d_ringbuffer); +} + +int +audio_jack_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // write_size and work_size are in bytes + int work_size = noutput_items*sizeof(sample_t); + unsigned int write_size; + + while (work_size > 0) { + unsigned int write_space; // bytes + +#ifdef NO_PTHREAD + while ((write_space=jack_ringbuffer_write_space (d_ringbuffer)) < + d_jack_buffer_size*sizeof(sample_t)) { + usleep(1000000*((d_jack_buffer_size-write_space/sizeof(sample_t))/d_sampling_rate)); + } +#else + // JACK actually requires POSIX + + pthread_mutex_lock (&d_jack_process_lock); + while ((write_space=jack_ringbuffer_write_space (d_ringbuffer)) < + d_jack_buffer_size*sizeof(sample_t)) { + + // wait until jack_sink_process() signals more room + pthread_cond_wait (&d_ringbuffer_ready, &d_jack_process_lock); + } + pthread_mutex_unlock (&d_jack_process_lock); +#endif + + write_space -= write_space%(d_jack_buffer_size*sizeof(sample_t)); + write_size = std::min(write_space, (unsigned int)work_size); + + if (jack_ringbuffer_write (d_ringbuffer, (char *) input_items[0], + write_size) < write_size) { + bail ("jack_ringbuffer_write failed", 0); + } + work_size -= write_size; + } + + return noutput_items; +} + +void +audio_jack_sink::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "audio_jack_sink[%s]: %s: %d\n", + d_device_name.c_str (), msg, err); +} + +void +audio_jack_sink::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("audio_jack_sink"); +} diff --git a/gr-audio-jack/src/audio_jack_sink.h b/gr-audio-jack/src/audio_jack_sink.h new file mode 100644 index 00000000..00b94990 --- /dev/null +++ b/gr-audio-jack/src/audio_jack_sink.h @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_AUDIO_JACK_SINK_H +#define INCLUDED_AUDIO_JACK_SINK_H + +#include +#include +#include +#include +#include + +class audio_jack_sink; +typedef boost::shared_ptr audio_jack_sink_sptr; + +/*! + * \brief make an JACK audio sink. + * + * \param sampling_rate sampling rate in Hz + * \param dev JACK device name, e.g., "gr_sink" + * \param ok_to_block + */ +audio_jack_sink_sptr +audio_jack_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +int jack_sink_process (jack_nframes_t nframes, void *arg); + +/*! + * \brief audio sink using JACK + * + * The sink has one input stream of floats. + * + * Input samples must be in the range [-1,1]. + */ +class audio_jack_sink : public gr_sync_block { + friend audio_jack_sink_sptr + audio_jack_make_sink (int sampling_rate, const std::string device_name, bool ok_to_block); + + friend int jack_sink_process (jack_nframes_t nframes, void *arg); + + // typedef for pointer to class work method + typedef int (audio_jack_sink::*work_t)(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int d_sampling_rate; + std::string d_device_name; + bool d_ok_to_block; + + jack_client_t *d_jack_client; + jack_port_t *d_jack_output_port; + jack_ringbuffer_t *d_ringbuffer; + jack_nframes_t d_jack_buffer_size; + pthread_cond_t d_ringbuffer_ready; + pthread_mutex_t d_jack_process_lock; + + // random stats + int d_nunderuns; // count of underruns + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + + + protected: + audio_jack_sink (int sampling_rate, const std::string device_name, bool ok_to_block); + + public: + ~audio_jack_sink (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_JACK_SINK_H */ diff --git a/gr-audio-jack/src/audio_jack_source.cc b/gr-audio-jack/src/audio_jack_source.cc new file mode 100644 index 00000000..baa7db19 --- /dev/null +++ b/gr-audio-jack/src/audio_jack_source.cc @@ -0,0 +1,231 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef NO_PTHREAD +#include +#endif + +typedef jack_default_audio_sample_t sample_t; + + +// Number of jack buffers in the ringbuffer +// TODO: make it to match at least the quantity of items passed to work() +static const unsigned int N_BUFFERS = 16; + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_jack", "default_input_device", "gr_source"); +} + + +int +jack_source_process (jack_nframes_t nframes, void *arg) +{ + audio_jack_source *self = (audio_jack_source *)arg; + unsigned int write_size = nframes*sizeof(sample_t); + + if (jack_ringbuffer_write_space (self->d_ringbuffer) < write_size) { + self->d_noverruns++; + // FIXME: move this fputs out, we shouldn't use blocking calls in process() + fputs ("jO", stderr); + return 0; + } + + char *buffer = (char *) jack_port_get_buffer (self->d_jack_input_port, nframes); + + jack_ringbuffer_write (self->d_ringbuffer, buffer, write_size); + +#ifndef NO_PTHREAD + // Tell the source thread there is data in the ringbuffer. + // If it is already running, the lock will not be available. + // We can't wait here in the process() thread, but we don't + // need to signal in that case, because the source thread will + // check for data availability. + + if (pthread_mutex_trylock (&self->d_jack_process_lock) == 0) { + pthread_cond_signal (&self->d_ringbuffer_ready); + pthread_mutex_unlock (&self->d_jack_process_lock); + } +#endif + + return 0; +} + +// ---------------------------------------------------------------- + +audio_jack_source_sptr +audio_jack_make_source (int sampling_rate, const std::string dev, bool ok_to_block) +{ + return audio_jack_source_sptr (new audio_jack_source (sampling_rate, dev, ok_to_block)); +} + +audio_jack_source::audio_jack_source (int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_jack_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_ok_to_block(ok_to_block), + d_jack_client (0), + d_ringbuffer (0), + d_noverruns (0) +{ +#ifndef NO_PTHREAD + pthread_cond_init(&d_ringbuffer_ready, NULL);; + pthread_mutex_init(&d_jack_process_lock, NULL); +#endif + + // try to become a client of the JACK server + if ((d_jack_client = jack_client_new (d_device_name.c_str ())) == 0) { + fprintf (stderr, "audio_jack_source[%s]: jack server not running?\n", + d_device_name.c_str()); + throw std::runtime_error ("audio_jack_source"); + } + + // tell the JACK server to call `jack_source_process()' whenever + // there is work to be done. + jack_set_process_callback (d_jack_client, &jack_source_process, (void*)this); + + // tell the JACK server to call `jack_shutdown()' if + // it ever shuts down, either entirely, or if it + // just decides to stop calling us. + + //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this); + + d_jack_input_port = jack_port_register (d_jack_client, "in", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0); + + + d_jack_buffer_size = jack_get_buffer_size (d_jack_client); + + set_output_multiple (d_jack_buffer_size); + + d_ringbuffer = jack_ringbuffer_create (N_BUFFERS*d_jack_buffer_size*sizeof(sample_t)); + if (d_ringbuffer == NULL) + bail ("jack_ringbuffer_create failed", 0); + + assert(sizeof(float)==sizeof(sample_t)); + set_output_signature (gr_make_io_signature (1, 1, sizeof (sample_t))); + + + jack_nframes_t sample_rate = jack_get_sample_rate (d_jack_client); + + if ((jack_nframes_t)sampling_rate != sample_rate){ + fprintf (stderr, "audio_jack_source[%s]: unable to support sampling rate %d\n", + d_device_name.c_str (), sampling_rate); + fprintf (stderr, " card requested %d instead.\n", sample_rate); + } +} + + +bool +audio_jack_source::check_topology (int ninputs, int noutputs) +{ + // tell the JACK server that we are ready to roll + if (jack_activate (d_jack_client)) + throw std::runtime_error ("audio_jack_source"); + + return true; +} + +audio_jack_source::~audio_jack_source () +{ + jack_client_close (d_jack_client); + jack_ringbuffer_free (d_ringbuffer); +} + +int +audio_jack_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // read_size and work_size are in bytes + unsigned int read_size; + + // Minimize latency + noutput_items = std::min (noutput_items, (int)d_jack_buffer_size); + + int work_size = noutput_items*sizeof(sample_t); + + while (work_size > 0) { + unsigned int read_space; // bytes + +#ifdef NO_PTHREAD + while ((read_space=jack_ringbuffer_read_space (d_ringbuffer)) < + d_jack_buffer_size*sizeof(sample_t)) { + usleep(1000000*((d_jack_buffer_size-read_space/sizeof(sample_t))/d_sampling_rate)); + } +#else + // JACK actually requires POSIX + + pthread_mutex_lock (&d_jack_process_lock); + while ((read_space=jack_ringbuffer_read_space (d_ringbuffer)) < + d_jack_buffer_size*sizeof(sample_t)) { + + // wait until jack_source_process() signals more data + pthread_cond_wait (&d_ringbuffer_ready, &d_jack_process_lock); + } + pthread_mutex_unlock (&d_jack_process_lock); +#endif + + read_space -= read_space%(d_jack_buffer_size*sizeof(sample_t)); + read_size = std::min(read_space, (unsigned int)work_size); + + if (jack_ringbuffer_read (d_ringbuffer, (char *) output_items[0], + read_size) < read_size) { + bail ("jack_ringbuffer_read failed", 0); + } + work_size -= read_size; + } + + return noutput_items; +} + +void +audio_jack_source::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "audio_jack_source[%s]: %s: %d\n", + d_device_name.c_str (), msg, err); +} + +void +audio_jack_source::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("audio_jack_source"); +} diff --git a/gr-audio-jack/src/audio_jack_source.h b/gr-audio-jack/src/audio_jack_source.h new file mode 100644 index 00000000..4d647144 --- /dev/null +++ b/gr-audio-jack/src/audio_jack_source.h @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_AUDIO_JACK_SOURCE_H +#define INCLUDED_AUDIO_JACK_SOURCE_H + +#include +#include +#include +#include +#include + +class audio_jack_source; +typedef boost::shared_ptr audio_jack_source_sptr; + +/*! + * \brief make a JACK audio source. + * + * \param sampling_rate sampling rate in Hz + * \param dev JACK device name, e.g., "gr_source" + * \param ok_to_block + */ +audio_jack_source_sptr +audio_jack_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +int jack_source_process (jack_nframes_t nframes, void *arg); + +/*! + * \brief audio source using JACK + * + * The source has one input stream of floats. + * + * Output samples will be in the range [-1,1]. + */ +class audio_jack_source : public gr_sync_block { + friend audio_jack_source_sptr + audio_jack_make_source (int sampling_rate, const std::string device_name, bool ok_to_block); + + friend int jack_source_process (jack_nframes_t nframes, void *arg); + + // typedef for pointer to class work method + typedef int (audio_jack_source::*work_t)(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int d_sampling_rate; + std::string d_device_name; + bool d_ok_to_block; + + jack_client_t *d_jack_client; + jack_port_t *d_jack_input_port; + jack_ringbuffer_t *d_ringbuffer; + jack_nframes_t d_jack_buffer_size; + pthread_cond_t d_ringbuffer_ready; + pthread_mutex_t d_jack_process_lock; + + // random stats + int d_noverruns; // count of overruns + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + + + protected: + audio_jack_source (int sampling_rate, const std::string device_name, bool ok_to_block); + + public: + ~audio_jack_source (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_JACK_SOURCE_H */ diff --git a/gr-audio-jack/src/gri_jack.cc b/gr-audio-jack/src/gri_jack.cc new file mode 100644 index 00000000..9ae80d00 --- /dev/null +++ b/gr-audio-jack/src/gri_jack.cc @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + + diff --git a/gr-audio-jack/src/gri_jack.h b/gr-audio-jack/src/gri_jack.h new file mode 100644 index 00000000..564672b5 --- /dev/null +++ b/gr-audio-jack/src/gri_jack.h @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_JACK_H +#define INCLUDED_GRI_JACK_H + +#include + +#endif /* INCLUDED_GRI_JACK_H */ diff --git a/gr-audio-jack/src/qa_jack.py b/gr-audio-jack/src/qa_jack.py new file mode 100755 index 00000000..58f860c6 --- /dev/null +++ b/gr-audio-jack/src/qa_jack.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_jack + +class qa_jack (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have JACK library, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-jack/src/run_tests.in b/gr-audio-jack/src/run_tests.in new file mode 100644 index 00000000..3e589894 --- /dev/null +++ b/gr-audio-jack/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-jack/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-jack/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-jack/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-audio-oss/AUTHORS b/gr-audio-oss/AUTHORS new file mode 100644 index 00000000..ee4560a5 --- /dev/null +++ b/gr-audio-oss/AUTHORS @@ -0,0 +1 @@ +Eric Blossom diff --git a/gr-audio-oss/ChangeLog b/gr-audio-oss/ChangeLog new file mode 100644 index 00000000..ab917e58 --- /dev/null +++ b/gr-audio-oss/ChangeLog @@ -0,0 +1,91 @@ +2006-03-30 Eric Blossom + + * gr-audio-oss.conf: new config file. + * src/audio_oss_sink.{h,cc,i}, src/audio_oss_source.{h,cc,i}: + added ok_to_block constructor arg (currrently ignored), and now query + preferences for latency and default input and output devices. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-03-29 Eric Blossom + + * src/audio_oss.i, src/audio_oss_sink.{h,cc}, + src/audio_oss_source.{h,cc}: map zero length device name to default. + +2005-02-06 Eric Blossom + + * configure.ac: upped rev to 0.5 for release + * src/Makefile.am: backed out dependency on libpython + +2005-01-29 Eric Blossom + + * src/Makefile.am: cleanup for SWIG 1.3.24 + +2005-01-28 Stephane Fillod + + * src/Makefile.am: fixes for MinGW. + +2004-11-04 Eric Blossom + + * configure.ac: upped rev to 0.3cvs + + * configure.ac: added AC_HAVE_LIBRARY(ossaudio) check for NetBSD. + upped rev to 0.3. Made release. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 0.2cvs + +2004-10-11 Eric Blossom + + * configure.ac: bumped rev to 0.2, make release + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 0.1cvs + +2004-07-09 Eric Blossom + + * src/audio_oss_source.{h,cc}: new. + * src/audio_oss_sink.{h,cc}: new. + +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-oss/Makefile.am b/gr-audio-oss/Makefile.am new file mode 100644 index 00000000..77595d9e --- /dev/null +++ b/gr-audio-oss/Makefile.am @@ -0,0 +1,30 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + gr-audio-oss.conf + +SUBDIRS = src + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gr-audio-oss.conf diff --git a/gr-audio-oss/gr-audio-oss.conf b/gr-audio-oss/gr-audio-oss.conf new file mode 100644 index 00000000..6ea14d67 --- /dev/null +++ b/gr-audio-oss/gr-audio-oss.conf @@ -0,0 +1,9 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[audio_oss] + +default_input_device = /dev/dsp +default_output_device = /dev/dsp +latency = 0.005 # in seconds diff --git a/gr-audio-oss/src/Makefile.am b/gr-audio-oss/src/Makefile.am new file mode 100644 index 00000000..656d665a --- /dev/null +++ b/gr-audio-oss/src/Makefile.am @@ -0,0 +1,90 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +LIBS += $(GNURADIO_CORE_LIBS) + +# Install this stuff so that it ends up as the gnuradio.audio_oss module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in +TESTS = run_tests + +LOCAL_IFILES = \ + audio_oss.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_oss.cc \ + audio_oss.py + +ourpython_PYTHON = \ + audio_oss.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) + +ourlib_LTLIBRARIES = _audio_oss.la + +_audio_oss_la_SOURCES = \ + audio_oss.cc \ + audio_oss_sink.cc \ + audio_oss_source.cc + + +grinclude_HEADERS = \ + audio_oss_sink.h \ + audio_oss_source.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_oss_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +_audio_oss_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +audio_oss.cc audio_oss.py: audio_oss.i $(NON_LOCAL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module audio_oss -o audio_oss.cc $< + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done + +noinst_PYTHON = qa_oss.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc + diff --git a/gr-audio-oss/src/audio_oss.i b/gr-audio-oss/src/audio_oss.i new file mode 100644 index 00000000..75bb31e4 --- /dev/null +++ b/gr-audio-oss/src/audio_oss.i @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_oss_sink.h" +#include "audio_oss_source.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_oss,sink) + +audio_oss_sink_sptr +audio_oss_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + + +class audio_oss_sink : public gr_sync_block { + protected: + audio_oss_sink (int sampling_rate, const std::string device_name = "", bool ok_to_block = true); + + public: + ~audio_oss_sink (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_oss,source) + +audio_oss_source_sptr +audio_oss_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_oss_source : public gr_sync_block { + protected: + audio_oss_source (int sampling_rate, const std::string device_name = "", bool ok_to_block = true); + + public: + ~audio_oss_source (); +}; diff --git a/gr-audio-oss/src/audio_oss_sink.cc b/gr-audio-oss/src/audio_oss_sink.cc new file mode 100644 index 00000000..eff3de49 --- /dev/null +++ b/gr-audio-oss/src/audio_oss_sink.cc @@ -0,0 +1,161 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_oss", "default_output_device", "/dev/dsp"); +} + +audio_oss_sink_sptr +audio_oss_make_sink (int sampling_rate, const std::string dev, bool ok_to_block) +{ + return audio_oss_sink_sptr (new audio_oss_sink (sampling_rate, dev, ok_to_block)); +} + +audio_oss_sink::audio_oss_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_oss_sink", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_fd (-1), d_buffer (0), d_chunk_size (0) +{ + if ((d_fd = open (d_device_name.c_str (), O_WRONLY)) < 0){ + fprintf (stderr, "audio_oss_sink: "); + perror (d_device_name.c_str ()); + throw std::runtime_error ("audio_oss_sink"); + } + + double CHUNK_TIME = + std::max(0.001, gr_prefs::singleton()->get_double("audio_oss", "latency", 0.005)); + + d_chunk_size = (int) (d_sampling_rate * CHUNK_TIME); + set_output_multiple (d_chunk_size); + + d_buffer = new short [d_chunk_size * 2]; + + int format = AFMT_S16_NE; + int orig_format = format; + if (ioctl (d_fd, SNDCTL_DSP_SETFMT, &format) < 0){ + std::cerr << "audio_oss_sink: " << d_device_name << " ioctl failed\n"; + perror (d_device_name.c_str ()); + throw std::runtime_error ("audio_oss_sink"); + } + + if (format != orig_format){ + fprintf (stderr, "audio_oss_sink: unable to support format %d\n", orig_format); + fprintf (stderr, " card requested %d instead.\n", format); + } + + // set to stereo no matter what. Some hardware only does stereo + int channels = 2; + if (ioctl (d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2){ + perror ("audio_oss_sink: could not set STEREO mode"); + throw std::runtime_error ("audio_oss_sink"); + } + + // set sampling freq + int sf = sampling_rate; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0){ + std::cerr << "audio_oss_sink: " + << d_device_name << ": invalid sampling_rate " + << sampling_rate << "\n"; + sampling_rate = 8000; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0){ + std::cerr << "audio_oss_sink: failed to set sampling_rate to 8000\n"; + throw std::runtime_error ("audio_oss_sink"); + } + } +} + +audio_oss_sink::~audio_oss_sink () +{ + close (d_fd); + delete [] d_buffer; +} + + +int +audio_oss_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *f0, *f1; + + switch (input_items.size ()){ + + case 1: // mono input + + f0 = (const float *) input_items[0]; + + for (int i = 0; i < noutput_items; i += d_chunk_size){ + for (int j = 0; j < d_chunk_size; j++){ + d_buffer[2*j+0] = (short) (f0[j] * 32767); + d_buffer[2*j+1] = (short) (f0[j] * 32767); + } + f0 += d_chunk_size; + if (write (d_fd, d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + perror ("audio_oss_sink: write"); + } + break; + + case 2: // stereo input + + f0 = (const float *) input_items[0]; + f1 = (const float *) input_items[1]; + + for (int i = 0; i < noutput_items; i += d_chunk_size){ + for (int j = 0; j < d_chunk_size; j++){ + d_buffer[2*j+0] = (short) (f0[j] * 32767); + d_buffer[2*j+1] = (short) (f1[j] * 32767); + } + f0 += d_chunk_size; + f1 += d_chunk_size; + if (write (d_fd, d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + perror ("audio_oss_sink: write"); + } + break; + } + + return noutput_items; +} diff --git a/gr-audio-oss/src/audio_oss_sink.h b/gr-audio-oss/src/audio_oss_sink.h new file mode 100644 index 00000000..940ce46f --- /dev/null +++ b/gr-audio-oss/src/audio_oss_sink.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_OSS_SINK_H +#define INCLUDED_AUDIO_OSS_SINK_H + +#include +#include + + +class audio_oss_sink; +typedef boost::shared_ptr audio_oss_sink_sptr; + +audio_oss_sink_sptr +audio_oss_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +/*! + * \brief audio sink using OSS + * + * input signature is one or two streams of floats. + * Input samples must be in the range [-1,1]. + */ + +class audio_oss_sink : public gr_sync_block { + friend audio_oss_sink_sptr + audio_oss_make_sink (int sampling_rate, const std::string device_name, bool ok_to_block); + + int d_sampling_rate; + std::string d_device_name; + int d_fd; + short *d_buffer; + int d_chunk_size; + + protected: + audio_oss_sink (int sampling_rate, const std::string device_name = "", bool ok_to_block = true); + + public: + ~audio_oss_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_OSS_SINK_H */ diff --git a/gr-audio-oss/src/audio_oss_source.cc b/gr-audio-oss/src/audio_oss_source.cc new file mode 100644 index 00000000..6afb0883 --- /dev/null +++ b/gr-audio-oss/src/audio_oss_source.cc @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_oss", "default_input_device", "/dev/dsp"); +} + +audio_oss_source_sptr +audio_oss_make_source (int sampling_rate, const std::string dev, bool ok_to_block) +{ + return audio_oss_source_sptr (new audio_oss_source (sampling_rate, dev, ok_to_block)); +} + + +audio_oss_source::audio_oss_source (int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_oss_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 2, sizeof (float))), + d_sampling_rate (sampling_rate), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_fd (-1), d_buffer (0), d_chunk_size (0) +{ + if ((d_fd = open (d_device_name.c_str (), O_RDONLY)) < 0){ + fprintf (stderr, "audio_oss_source: "); + perror (d_device_name.c_str ()); + throw std::runtime_error ("audio_oss_source"); + } + + double CHUNK_TIME = + std::max(0.001, gr_prefs::singleton()->get_double("audio_oss", "latency", 0.005)); + + d_chunk_size = (int) (d_sampling_rate * CHUNK_TIME); + set_output_multiple (d_chunk_size); + + d_buffer = new short [d_chunk_size * 2]; + + int format = AFMT_S16_NE; + int orig_format = format; + if (ioctl (d_fd, SNDCTL_DSP_SETFMT, &format) < 0){ + std::cerr << "audio_oss_source: " << d_device_name << " ioctl failed\n"; + perror (d_device_name.c_str ()); + throw std::runtime_error ("audio_oss_source"); + } + + if (format != orig_format){ + fprintf (stderr, "audio_oss_source: unable to support format %d\n", orig_format); + fprintf (stderr, " card requested %d instead.\n", format); + } + + // set to stereo no matter what. Some hardware only does stereo + int channels = 2; + if (ioctl (d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2){ + perror ("audio_oss_source: could not set STEREO mode"); + throw std::runtime_error ("audio_oss_source"); + } + + // set sampling freq + int sf = sampling_rate; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0){ + std::cerr << "audio_oss_source: " + << d_device_name << ": invalid sampling_rate " + << sampling_rate << "\n"; + sampling_rate = 8000; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0){ + std::cerr << "audio_oss_source: failed to set sampling_rate to 8000\n"; + throw std::runtime_error ("audio_oss_source"); + } + } +} + +audio_oss_source::~audio_oss_source () +{ + close (d_fd); + delete [] d_buffer; +} + +int +audio_oss_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *f0 = (float *) output_items[0]; + float *f1 = (float *) output_items[1]; // will be invalid if this is mono output + + const int shorts_per_item = 2; // L + R + const int bytes_per_item = shorts_per_item * sizeof (short); + + // To minimize latency, never return more than CHUNK_TIME + // worth of samples per call to work. + + noutput_items = std::min (noutput_items, d_chunk_size); + + int base = 0; + int ntogo = noutput_items; + + while (ntogo > 0){ + int nbytes = std::min (ntogo, d_chunk_size) * bytes_per_item; + int result_nbytes = read (d_fd, d_buffer, nbytes); + + if (result_nbytes < 0){ + perror ("audio_oss_source"); + return -1; // say we're done + } + + if ((result_nbytes & (bytes_per_item - 1)) != 0){ + fprintf (stderr, "audio_oss_source: internal error.\n"); + throw std::runtime_error ("internal error"); + } + + int result_nitems = result_nbytes / bytes_per_item; + + // now unpack samples into output streams + + switch (output_items.size ()){ + case 1: // mono output + for (int i = 0; i < result_nitems; i++){ + f0[base+i] = d_buffer[2*i+0] * (1.0 / 32767); + } + break; + + case 2: // stereo output + for (int i = 0; i < result_nitems; i++){ + f0[base+i] = d_buffer[2*i+0] * (1.0 / 32767); + f1[base+i] = d_buffer[2*i+1] * (1.0 / 32767); + } + break; + + default: + assert (0); + } + + ntogo -= result_nitems; + base += result_nitems; + } + + return noutput_items - ntogo; +} diff --git a/gr-audio-oss/src/audio_oss_source.h b/gr-audio-oss/src/audio_oss_source.h new file mode 100644 index 00000000..4f0facd4 --- /dev/null +++ b/gr-audio-oss/src/audio_oss_source.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_OSS_SOURCE_H +#define INCLUDED_AUDIO_OSS_SOURCE_H + +#include +#include + + +class audio_oss_source; +typedef boost::shared_ptr audio_oss_source_sptr; + +audio_oss_source_sptr +audio_oss_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +/*! + * \brief audio source using OSS + * + * Output signature is one or two streams of floats. + * Output samples will be in the range [-1,1]. + */ + +class audio_oss_source : public gr_sync_block { + friend audio_oss_source_sptr + audio_oss_make_source (int sampling_rate, const std::string device_name, bool ok_to_block); + + int d_sampling_rate; + std::string d_device_name; + int d_fd; + short *d_buffer; + int d_chunk_size; + + protected: + audio_oss_source (int sampling_rate, + const std::string device_name = "", + bool ok_to_block = true); + + public: + ~audio_oss_source (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + + +#endif /* INCLUDED_AUDIO_OSS_SOURCE_H */ diff --git a/gr-audio-oss/src/qa_oss.py b/gr-audio-oss/src/qa_oss.py new file mode 100755 index 00000000..f7476543 --- /dev/null +++ b/gr-audio-oss/src/qa_oss.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_oss + +class qa_oss (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have OSS drivers, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-oss/src/run_tests.in b/gr-audio-oss/src/run_tests.in new file mode 100644 index 00000000..ec252d50 --- /dev/null +++ b/gr-audio-oss/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-oss/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-oss/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-oss/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-audio-osx/AUTHORS b/gr-audio-osx/AUTHORS new file mode 100644 index 00000000..ecc9577a --- /dev/null +++ b/gr-audio-osx/AUTHORS @@ -0,0 +1 @@ +Michael Dickens NCIP Lab, University of Notre Dame diff --git a/gr-audio-osx/ChangeLog b/gr-audio-osx/ChangeLog new file mode 100644 index 00000000..0ae5acf7 --- /dev/null +++ b/gr-audio-osx/ChangeLog @@ -0,0 +1,25 @@ +2006-04-22 Michael Dickens + NCIP Lab, University of Notre Dame + + Everything is new. + +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio. +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-osx/Makefile.am b/gr-audio-osx/Makefile.am new file mode 100644 index 00000000..077d2aa1 --- /dev/null +++ b/gr-audio-osx/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = README_OSX +SUBDIRS = src diff --git a/gr-audio-osx/README_OSX b/gr-audio-osx/README_OSX new file mode 100644 index 00000000..2a98e96b --- /dev/null +++ b/gr-audio-osx/README_OSX @@ -0,0 +1,61 @@ +Michael Dickens +2006-Apr-30 + +0) This module should compile and install in the same manner as the +other GNURadio modules (e.g. gnuradio-core), with the possible +exception that GNU libtool 1.5.20 or newer should be installed and +used (if not first in the path) via "make LIBTOOL=/..." and so forth. +Version 1.5.10 has failed making, and while picking version 1.5.20 is +somewhat arbitrary, the newer version compiles and installs easily +under OSX. + +1) This module should be automatically loaded by the Python command +"from gr import audio". The audio import script will automatically +select gr.audio_osx if it is available (though it will try to import +ALSA first, then OSS, then OSX, and finally WINDOWS audio modules, in +that order). If that import command doesn't work, try reinstalling +gnuradio-core from scratch followed by gr-audio-osx. + +2) Instantiation arguments for either source or sink are: + +* sample_rate : integer : default == 44100 + OSX converts the integer sample rate to a double internally; it + would be nice to have this input as a double natively, but that + doesn't work with other audio devices. + +* device_name : string : default == "2" + For OSX, the device name should be an integer string. This value is + the maximum number of channels to allocate (for input or output). + In the "source" case (input), the actual number of channels will be + whatever is available on that current system input device. In the + "sink" case (output), OSX will convert the provided channels into + whatever format is required by the current system output device. + For example, "3" would try to setup for 3 input or output channels. + NOTE that this is a very different use than that for other audio + modules (though they can interpret the number of channels from this + argument). + +* do_block : boolean : default == true + If the data transfer buffer between OSX internals and GNURadio gets + full, either block (true) or overwrite (false) depending on this + variable. + +The following are currently non-standard arguments: + +* channel_config : integer : default == -1 + An enum (internally) describing the channel configuration. Not + currently used, but rather reserved for future expansion. + +* max_sample_count : integer : default == -1 + The maximum number of samples to buffer between OSX internals and + GNURadio. The value -1 is mapped to 1 second's worth of data. + +3) When the buffer is full and do_block is false and new data comes +in, the oldest data will be overwritten. The source will print out +"iX" each time this happens; the sink will print out "oX". + +4) In the "src" directory is a python script "test_audio_loop" which +connects the default audio input device to the default audio output +device. This script is very useful in testing that audio is correctly +installed and both the source and sink are functional. This script is +not run by "make check". diff --git a/gr-audio-osx/TODO b/gr-audio-osx/TODO new file mode 100644 index 00000000..e36ed2b2 --- /dev/null +++ b/gr-audio-osx/TODO @@ -0,0 +1,51 @@ +List as of 2006-Apr-22, by Michael Dickens, primary author + +* Change buffering to use gr_buffer's and necessary related classes. + Currently uses a circular_buffer I wrote myself (in + ./src/circular_buffer.h ), which hides the "circular" part from the + user but otherwise is very fast as well as thread safe. + +* A current limitation of this implementation is that the user cannot + dynamically switch audio devices (input or output) during playback + and use the new device without stopping the current executing GR and + restarting the process. I would like to figure out how to get a + CoreAudio "listener" for when the default hardware input / output + device changes (e.g. when switched by the user in the "Sound" system + preference pane). The code in ./src/audio-osx-source.cc creates + listeners for the AudioUnit being used as well as the Hardware + device, but these for some reason don't do the trick. It's possible + that the Python framework doesn't allow for one to do this. + +* In both the source and sink, move the code which defines the "Audio + Stream Basic Description" (ASBD) to a routine to do this as needed + as start-up as well as in a callback ("listener") if the default + device changes. + +* Tweak the mutex (d_internal) to only where it is truly needed + (around class-specific variables used across all threads) in order + to improve performance. Currently the mutex is used at the + start and end of any function requiring access to the class variables. + +* Change the instantiation arguments ... once those arguments are + finalized. Right now gr.audio.source () takes the sample rate (int + - should be double), the device name (std::string), a boolean for + blocking or not, and 2 completely non-standard ones for channel + configuration and the maximum sample count to buffer. These are + reasonable for OSX, but might not be for other OSs. Nothing to do + right now but wait and discuss. + +* Once the previous issue has been resolved, then the current method + of determining the number of channels needs to be updated. + Currently the "device_name" for OSX should contain a numeric string + for the maximum number of channels to use (e.g. "3" means 3 + channels, generally mapped to 2 channel stereo by OSX). The + "device_name" is generally input via "-O" in Python scripts, so "-O + 3" would allow for 3 incoming output channels (or fewer). In theory + the "channel_config" argument would make more sense for determining + channel usage. Example config strings might be "2.1" for stereo w/ + subwoofer (3 channels), "5.1" or "6.1" for various surround w/ + subwoofer (6 & 7 channels, respectively). OSX can handle all sorts + of channel configurations, but the names for these will be different + than those use for OSS or ALMA or Windows ... thus the need for a + common naming scheme for all cared-about configurations, possibly + with options for other OS-specific options. diff --git a/gr-audio-osx/src/Makefile.am b/gr-audio-osx/src/Makefile.am new file mode 100644 index 00000000..54cc3272 --- /dev/null +++ b/gr-audio-osx/src/Makefile.am @@ -0,0 +1,88 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio. +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.audio_osx module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in +TESTS = run_tests + +LOCAL_IFILES = \ + audio_osx.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_osx.cc \ + audio_osx.py + +ourpython_PYTHON = \ + audio_osx.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGCPPPYTHONARGS = -python $(PYTHON_CPPFLAGS) $(STD_DEFINES_AND_INCLUDES) + +ourlib_LTLIBRARIES = _audio_osx.la + +_audio_osx_la_SOURCES = \ + audio_osx.cc \ + audio_osx_sink.cc \ + audio_osx_source.cc + +noinst_HEADERS = \ + audio_osx.h \ + circular_buffer.h \ + mld_threads.h + +grinclude_HEADERS = \ + audio_osx_sink.h \ + audio_osx_source.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_osx_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + $(GNURADIO_CORE_LIBS) \ + -lstdc++ + +_audio_osx_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version -framework AudioUnit -framework CoreAudio -framework AudioToolbox + +audio_osx.cc audio_osx.py: audio_osx.i + $(SWIG) $(SWIGCPPPYTHONARGS) -module audio_osx -o audio_osx.cc $< + +noinst_PYTHON = qa_osx.py test_audio_loop.py + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *~ *.pyc run_tests *.loT + +CONFIG_CLEAN_FILES = Makefile.in run_tests *.loT diff --git a/gr-audio-osx/src/audio_osx.h b/gr-audio-osx/src/audio_osx.h new file mode 100644 index 00000000..f92ca3fc --- /dev/null +++ b/gr-audio-osx/src/audio_osx.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_OSX_H +#define INCLUDED_AUDIO_OSX_H + +#define CheckErrorAndThrow(err,what,throw_str) \ +if (err) { \ + OSStatus error = static_cast(err); \ + fprintf (stderr, "%s\n Error# %ld ('%4s')\n %s:%d\n", \ + what, error, (char*)(&err), __FILE__, __LINE__); \ + fflush (stdout); \ + throw std::runtime_error (throw_str); \ +} + +#define CheckError(err,what) \ +if (err) { \ + OSStatus error = static_cast(err); \ + fprintf (stderr, "%s\n Error# %ld ('%4s')\n %s:%d\n", \ + what, error, (char*)(&err), __FILE__, __LINE__); \ + fflush (stdout); \ +} + +#ifdef WORDS_BIGENDIAN +#define GR_PCM_ENDIANNESS kLinearPCMFormatFlagIsBigEndian +#else +#define GR_PCM_ENDIANNESS 0 +#endif + +#endif /* INCLUDED_AUDIO_OSX_H */ diff --git a/gr-audio-osx/src/audio_osx.i b/gr-audio-osx/src/audio_osx.i new file mode 100644 index 00000000..9ced419f --- /dev/null +++ b/gr-audio-osx/src/audio_osx.i @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_osx_sink.h" +#include "audio_osx_source.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_osx,sink) + +audio_osx_sink_sptr +audio_osx_make_sink (int sample_rate = 44100, + const std::string device_name = "2", + bool do_block = TRUE, + int channel_config = -1, + int max_sample_count = -1 + ) throw (std::runtime_error); + +class audio_osx_sink : public gr_sync_block { + protected: + audio_osx_sink (int sample_rate = 44100, + const std::string device_name = "2", + bool do_block = TRUE, + int channel_config = -1, + int max_sample_count = -1); + + public: + ~audio_osx_sink (); + + bool start (); + bool stop (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_osx,source) + +audio_osx_source_sptr +audio_osx_make_source (int sample_rate = 44100, + const std::string device_name = "2", + bool do_block = TRUE, + int channel_config = -1, + int max_sample_count = -1 + ) throw (std::runtime_error); + +class audio_osx_source : public gr_sync_block { + protected: + audio_osx_source (int sample_rate = 44100, + const std::string device_name = "2", + bool do_block = TRUE, + int channel_config = -1, + int max_sample_count = -1); + + public: + ~audio_osx_source (); + + bool start (); + bool stop (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gr-audio-osx/src/audio_osx_sink.cc b/gr-audio-osx/src/audio_osx_sink.cc new file mode 100644 index 00000000..14b4a513 --- /dev/null +++ b/gr-audio-osx/src/audio_osx_sink.cc @@ -0,0 +1,398 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _USE_OMNI_THREADS_ + +#include +#include +#include +#include + +#define _OSX_AU_DEBUG_ 0 + +audio_osx_sink::audio_osx_sink (int sample_rate, + const std::string device_name, + bool do_block, + int channel_config, + int max_sample_count) + : gr_sync_block ("audio_osx_sink", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sample_rate (0.0), d_channel_config (0), d_n_channels (0), + d_queueSampleCount (0), d_max_sample_count (0), + d_do_block (do_block), d_internal (0), d_cond_data (0), + d_OutputAU (0) +{ + if (sample_rate <= 0) { + fprintf (stderr, "Invalid Sample Rate: %d\n", sample_rate); + throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); + } else + d_sample_rate = (Float64) sample_rate; + + if (channel_config <= 0 & channel_config != -1) { + fprintf (stderr, "Invalid Channel Config: %d\n", channel_config); + throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); + } else if (channel_config == -1) { +// no user input; try "device name" instead + int l_n_channels = (int) strtol (device_name.data(), (char **)NULL, 10); + if (l_n_channels == 0 & errno) { + fprintf (stderr, "Error Converting Device Name: %d\n", errno); + throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); + } + if (l_n_channels <= 0) + channel_config = 2; + else + channel_config = l_n_channels; + } + + d_n_channels = d_channel_config = channel_config; + +// set the input signature + + set_input_signature (gr_make_io_signature (1, d_n_channels, sizeof (float))); + +// check that the max # of samples to store is valid + + if (max_sample_count == -1) + max_sample_count = sample_rate; + else if (max_sample_count <= 0) { + fprintf (stderr, "Invalid Max Sample Count: %d\n", max_sample_count); + throw std::invalid_argument ("audio_osx_sink::audio_osx_sink"); + } + + d_max_sample_count = max_sample_count; + +// allocate the output circular buffer(s), one per channel + + d_buffers = (circular_buffer**) new + circular_buffer* [d_n_channels]; + UInt32 n_alloc = (UInt32) ceil ((double) d_max_sample_count); + for (UInt32 n = 0; n < d_n_channels; n++) { + d_buffers[n] = new circular_buffer (n_alloc, false, false); + } + +// create the default AudioUnit for output + OSStatus err = noErr; + +// Open the default output unit + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + Component comp = FindNextComponent (NULL, &desc); + if (comp == NULL) { + fprintf (stderr, "FindNextComponent Error\n"); + throw std::runtime_error ("audio_osx_sink::audio_osx_sink"); + } + + err = OpenAComponent (comp, &d_OutputAU); + CheckErrorAndThrow (err, "OpenAComponent", "audio_osx_sink::audio_osx_sink"); + +// Set up a callback function to generate output to the output unit + + AURenderCallbackStruct input; + input.inputProc = (AURenderCallback)(audio_osx_sink::AUOutputCallback); + input.inputProcRefCon = this; + + err = AudioUnitSetProperty (d_OutputAU, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &input, + sizeof (input)); + CheckErrorAndThrow (err, "AudioUnitSetProperty Render Callback", "audio_osx_sink::audio_osx_sink"); + +// tell the Output Unit what format data will be supplied to it +// so that it handles any format conversions + + AudioStreamBasicDescription streamFormat; + streamFormat.mSampleRate = (Float64)(sample_rate); + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = (kLinearPCMFormatFlagIsFloat | + GR_PCM_ENDIANNESS | + kLinearPCMFormatFlagIsPacked | + kAudioFormatFlagIsNonInterleaved); + streamFormat.mBytesPerPacket = 4; + streamFormat.mFramesPerPacket = 1; + streamFormat.mBytesPerFrame = 4; + streamFormat.mChannelsPerFrame = d_n_channels; + streamFormat.mBitsPerChannel = 32; + + err = AudioUnitSetProperty (d_OutputAU, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &streamFormat, + sizeof (AudioStreamBasicDescription)); + CheckErrorAndThrow (err, "AudioUnitSetProperty StreamFormat", "audio_osx_sink::audio_osx_sink"); + +// create the stuff to regulate I/O + + d_internal = new mld_mutex (); + if (d_internal == NULL) + CheckErrorAndThrow (errno, "new mld_mutex (internal)", + "audio_osx_source::audio_osx_source"); + + d_cond_data = new mld_condition (); + if (d_cond_data == NULL) + CheckErrorAndThrow (errno, "new mld_condition (data)", + "audio_osx_source::audio_osx_source"); + +// initialize the AU for output + + err = AudioUnitInitialize (d_OutputAU); + CheckErrorAndThrow (err, "AudioUnitInitialize", + "audio_osx_sink::audio_osx_sink"); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "audio_osx_sink Parameters:\n"); + fprintf (stderr, " Sample Rate is %g\n", d_sample_rate); + fprintf (stderr, " Number of Channels is %ld\n", d_n_channels); + fprintf (stderr, " Max # samples to store per channel is %ld", + d_max_sample_count); +#endif +} + +bool audio_osx_sink::IsRunning () +{ + UInt32 AURunning = 0, AUSize = sizeof (UInt32); + + OSStatus err = AudioUnitGetProperty (d_OutputAU, + kAudioOutputUnitProperty_IsRunning, + kAudioUnitScope_Global, + 0, + &AURunning, + &AUSize); + CheckErrorAndThrow (err, "AudioUnitGetProperty IsRunning", + "audio_osx_sink::IsRunning"); + + return (AURunning); +} + +bool audio_osx_sink::start () +{ + if (! IsRunning ()) { + OSStatus err = AudioOutputUnitStart (d_OutputAU); + CheckErrorAndThrow (err, "AudioOutputUnitStart", "audio_osx_sink::start"); + } + + return (true); +} + +bool audio_osx_sink::stop () +{ + if (IsRunning ()) { + OSStatus err = AudioOutputUnitStop (d_OutputAU); + CheckErrorAndThrow (err, "AudioOutputUnitStop", "audio_osx_sink::stop"); + + for (UInt32 n = 0; n < d_n_channels; n++) { + d_buffers[n]->abort (); + } + } + + return (true); +} + +audio_osx_sink::~audio_osx_sink () +{ +// stop and close the AudioUnit + stop (); + AudioUnitUninitialize (d_OutputAU); + CloseComponent (d_OutputAU); + +// empty and delete the queues + for (UInt32 n = 0; n < d_n_channels; n++) { + delete d_buffers[n]; + d_buffers[n] = 0; + } + delete [] d_buffers; + d_buffers = 0; + +// close and delete control stuff + delete d_internal; + delete d_cond_data; +} + +audio_osx_sink_sptr +audio_osx_make_sink (int sampling_freq, + const std::string dev, + bool do_block, + int channel_config, + int max_sample_count) +{ + return audio_osx_sink_sptr (new audio_osx_sink (sampling_freq, + dev, + do_block, + channel_config, + max_sample_count)); +} + +int +audio_osx_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + d_internal->wait (); + + /* take the input data, copy it, and push it to the bottom of the queue + mono input are pushed onto queue[0]; + stereo input are pushed onto queue[1]. + Start the AudioUnit if necessary. */ + + UInt32 l_max_count; + int diff_count = d_max_sample_count - noutput_items; + if (diff_count < 0) + l_max_count = 0; + else + l_max_count = (UInt32) diff_count; + +#if 0 + if (l_max_count < d_queueItemLength->back()) { +// allow 2 buffers at a time, regardless of length + l_max_count = d_queueItemLength->back(); + } +#endif + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "work1: qSC = %ld, lMC = %ld, dmSC = %ld, nOI = %d\n", + d_queueSampleCount, l_max_count, d_max_sample_count, noutput_items); +#endif + + if (d_queueSampleCount > l_max_count) { +// data coming in too fast; do_block decides what to do + if (d_do_block == true) { +// block until there is data to return + while (d_queueSampleCount > l_max_count) { +// release control so-as to allow data to be retrieved + d_internal->post (); +// block until there is data to return + d_cond_data->wait (); +// the condition's signal() was called; acquire control +// to keep thread safe + d_internal->wait (); + } + } + } +// not blocking case and overflow is handled by the circular buffer + +// add the input frames to the buffers' queue, checking for overflow + + UInt32 l_counter; + int res = 0; + float* inBuffer = (float*) input_items[0]; + const UInt32 l_size = input_items.size(); + for (l_counter = 0; l_counter < l_size; l_counter++) { + inBuffer = (float*) input_items[l_counter]; + int l_res = d_buffers[l_counter]->enqueue (inBuffer, + noutput_items); + if (l_res == -1) + res = -1; + } + while (l_counter < d_n_channels) { +// for extra channels, copy the last input's data + int l_res = d_buffers[l_counter++]->enqueue (inBuffer, + noutput_items); + if (l_res == -1) + res = -1; + } + + if (res == -1) { +// data coming in too fast +// drop oldest buffer + fputs ("oX", stderr); + fflush (stderr); +// set the local number of samples available to the max + d_queueSampleCount = d_buffers[0]->buffer_length_items (); + } else { +// keep up the local sample count + d_queueSampleCount += noutput_items; + } + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "work2: #OI = %4d, #Cnt = %4ld, mSC = %ld\n", + noutput_items, d_queueSampleCount, d_max_sample_count); +#endif + +// release control to allow for other processing parts to run + d_internal->post (); + + return (noutput_items); +} + +OSStatus audio_osx_sink::AUOutputCallback +(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) +{ + audio_osx_sink* This = (audio_osx_sink*) inRefCon; + OSStatus err = noErr; + + This->d_internal->wait (); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cb_in: SC = %4ld, in#F = %4ld\n", + This->d_queueSampleCount, inNumberFrames); +#endif + + if (This->d_queueSampleCount < inNumberFrames) { +// not enough data to fill request + err = -1; + } else { +// enough data; remove data from our buffers into the AU's buffers + int l_counter = This->d_n_channels; + + while (--l_counter >= 0) { + UInt32 t_n_output_items = inNumberFrames; + float* outBuffer = (float*) ioData->mBuffers[l_counter].mData; + This->d_buffers[l_counter]->dequeue (outBuffer, &t_n_output_items); + if (t_n_output_items != inNumberFrames) { + throw std::runtime_error ("audio_osx_sink::AUOutputCallback(): " + "number of available items changing " + "unexpectedly.\n"); + } + } + + This->d_queueSampleCount -= inNumberFrames; + } + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cb_out: SC = %4ld\n", This->d_queueSampleCount); +#endif + +// signal that data is available + This->d_cond_data->signal (); + +// release control to allow for other processing parts to run + This->d_internal->post (); + + return (err); +} diff --git a/gr-audio-osx/src/audio_osx_sink.h b/gr-audio-osx/src/audio_osx_sink.h new file mode 100644 index 00000000..8cd3be0a --- /dev/null +++ b/gr-audio-osx/src/audio_osx_sink.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_OSX_SINK_H +#define INCLUDED_AUDIO_OSX_SINK_H + +#include +#include +#include +#include +#include + +class audio_osx_sink; +typedef boost::shared_ptr audio_osx_sink_sptr; + +audio_osx_sink_sptr +audio_osx_make_sink (int sample_rate = 44100, + const std::string device_name = "2", + bool do_block = true, + int channel_config = -1, + int max_sample_count = -1); + +/*! + * \brief audio sink using OSX + * + * input signature is one or two streams of floats. + * Input samples must be in the range [-1,1]. + */ + +class audio_osx_sink : public gr_sync_block { + friend audio_osx_sink_sptr + audio_osx_make_sink (int sample_rate, + const std::string device_name, + bool do_block, + int channel_config, + int max_sample_count); + + Float64 d_sample_rate; + int d_channel_config; + UInt32 d_n_channels; + UInt32 d_queueSampleCount, d_max_sample_count; + bool d_do_block; + mld_mutex_ptr d_internal; + mld_condition_ptr d_cond_data; + circular_buffer** d_buffers; + +// AudioUnits and Such + AudioUnit d_OutputAU; + +protected: + audio_osx_sink (int sample_rate = 44100, + const std::string device_name = "2", + bool do_block = true, + int channel_config = -1, + int max_sample_count = -1); + +public: + ~audio_osx_sink (); + + bool IsRunning (); + bool start (); + bool stop (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +private: + static OSStatus AUOutputCallback (void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData); +}; + +#endif /* INCLUDED_AUDIO_OSX_SINK_H */ diff --git a/gr-audio-osx/src/audio_osx_source.cc b/gr-audio-osx/src/audio_osx_source.cc new file mode 100644 index 00000000..2abf1c2a --- /dev/null +++ b/gr-audio-osx/src/audio_osx_source.cc @@ -0,0 +1,978 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _USE_OMNI_THREADS_ + +#include +#include +#include +#include + +#define _OSX_AU_DEBUG_ 0 +#define _OSX_DO_LISTENERS_ 0 + +void PrintStreamDesc (AudioStreamBasicDescription *inDesc) +{ + if (inDesc == NULL) { + fprintf (stderr, "PrintStreamDesc: Can't print a NULL desc!\n"); + return; + } + + fprintf (stderr, " Sample Rate : %g\n", inDesc->mSampleRate); + fprintf (stderr, " Format ID : %4s\n", (char*)&inDesc->mFormatID); + fprintf (stderr, " Format Flags : %lX\n", inDesc->mFormatFlags); + fprintf (stderr, " Bytes per Packet : %ld\n", inDesc->mBytesPerPacket); + fprintf (stderr, " Frames per Packet : %ld\n", inDesc->mFramesPerPacket); + fprintf (stderr, " Bytes per Frame : %ld\n", inDesc->mBytesPerFrame); + fprintf (stderr, " Channels per Frame : %ld\n", inDesc->mChannelsPerFrame); + fprintf (stderr, " Bits per Channel : %ld\n", inDesc->mBitsPerChannel); +} + +// FIXME these should query some kind of user preference + +audio_osx_source::audio_osx_source (int sample_rate, + const std::string device_name, + bool do_block, + int channel_config, + int max_sample_count) + : gr_sync_block ("audio_osx_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_deviceSampleRate (0.0), d_outputSampleRate (0.0), + d_channel_config (0), + d_inputBufferSizeFrames (0), d_inputBufferSizeBytes (0), + d_outputBufferSizeFrames (0), d_outputBufferSizeBytes (0), + d_deviceBufferSizeFrames (0), d_deviceBufferSizeBytes (0), + d_leadSizeFrames (0), d_leadSizeBytes (0), + d_trailSizeFrames (0), d_trailSizeBytes (0), + d_extraBufferSizeFrames (0), d_extraBufferSizeBytes (0), + d_queueSampleCount (0), d_max_sample_count (0), + d_n_AvailableInputFrames (0), d_n_ActualInputFrames (0), + d_n_user_channels (0), d_n_max_channels (0), d_n_deviceChannels (0), + d_do_block (do_block), d_passThrough (false), + d_internal (0), d_cond_data (0), + d_buffers (0), + d_InputAU (0), d_InputBuffer (0), d_OutputBuffer (0), + d_AudioConverter (0) +{ + if (sample_rate <= 0) { + fprintf (stderr, "Invalid Sample Rate: %d\n", sample_rate); + throw std::invalid_argument ("audio_osx_source::audio_osx_source"); + } else + d_outputSampleRate = (Float64) sample_rate; + + if (channel_config <= 0 & channel_config != -1) { + fprintf (stderr, "Invalid Channel Config: %d\n", channel_config); + throw std::invalid_argument ("audio_osx_source::audio_osx_source"); + } else if (channel_config == -1) { +// no user input; try "device name" instead + int l_n_channels = (int) strtol (device_name.data(), (char **)NULL, 10); + if (l_n_channels == 0 & errno) { + fprintf (stderr, "Error Converting Device Name: %d\n", errno); + throw std::invalid_argument ("audio_osx_source::audio_osx_source"); + } + if (l_n_channels <= 0) + channel_config = 2; + else + channel_config = l_n_channels; + } + + d_channel_config = channel_config; + +// check that the max # of samples to store is valid + + if (max_sample_count == -1) + max_sample_count = sample_rate; + else if (max_sample_count <= 0) { + fprintf (stderr, "Invalid Max Sample Count: %d\n", max_sample_count); + throw std::invalid_argument ("audio_osx_source::audio_osx_source"); + } + + d_max_sample_count = max_sample_count; + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "source(): max # samples = %ld", d_max_sample_count); +#endif + + OSStatus err = noErr; + +// create the default AudioUnit for input + +// Open the default input unit + ComponentDescription InputDesc; + + InputDesc.componentType = kAudioUnitType_Output; + InputDesc.componentSubType = kAudioUnitSubType_HALOutput; + InputDesc.componentManufacturer = kAudioUnitManufacturer_Apple; + InputDesc.componentFlags = 0; + InputDesc.componentFlagsMask = 0; + + Component comp = FindNextComponent (NULL, &InputDesc); + if (comp == NULL) { + fprintf (stderr, "FindNextComponent Error\n"); + throw std::runtime_error ("audio_osx_source::audio_osx_source"); + } + + err = OpenAComponent (comp, &d_InputAU); + CheckErrorAndThrow (err, "OpenAComponent", + "audio_osx_source::audio_osx_source"); + + UInt32 enableIO; + +// must enable the AUHAL for input and disable output +// before setting the AUHAL's current device + +// Enable input on the AUHAL + enableIO = 1; + err = AudioUnitSetProperty (d_InputAU, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Input, + 1, // input element + &enableIO, + sizeof (UInt32)); + CheckErrorAndThrow (err, "AudioUnitSetProperty Input Enable", + "audio_osx_source::audio_osx_source"); + +// Disable output on the AUHAL + enableIO = 0; + err = AudioUnitSetProperty (d_InputAU, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Output, + 0, // output element + &enableIO, + sizeof (UInt32)); + CheckErrorAndThrow (err, "AudioUnitSetProperty Output Disable", + "audio_osx_source::audio_osx_source"); + +// set the default input device for our input AU + + SetDefaultInputDeviceAsCurrent (); + +#if _OSX_DO_LISTENERS_ +// set up a listener if default hardware input device changes + + err = AudioHardwareAddPropertyListener + (kAudioHardwarePropertyDefaultInputDevice, + (AudioHardwarePropertyListenerProc) HardwareListener, + this); + + CheckErrorAndThrow (err, "AudioHardwareAddPropertyListener", + "audio_osx_source::audio_osx_source"); + +// Add a listener for any changes in the input AU's output stream +// the function "UnitListener" will be called if the stream format +// changes for whatever reason + + err = AudioUnitAddPropertyListener + (d_InputAU, + kAudioUnitProperty_StreamFormat, + (AudioUnitPropertyListenerProc) UnitListener, + this); + CheckErrorAndThrow (err, "Adding Unit Property Listener", + "audio_osx_source::audio_osx_source"); +#endif + +// Now find out if it actually can do input. + + UInt32 hasInput = 0; + UInt32 dataSize = sizeof (hasInput); + err = AudioUnitGetProperty (d_InputAU, + kAudioOutputUnitProperty_HasIO, + kAudioUnitScope_Input, + 1, + &hasInput, + &dataSize); + CheckErrorAndThrow (err, "AudioUnitGetProperty HasIO", + "audio_osx_source::audio_osx_source"); + if (hasInput == 0) { + fprintf (stderr, "Selected Audio Device does not support Input.\n"); + throw std::runtime_error ("audio_osx_source::audio_osx_source"); + } + +// Set up a callback function to retrieve input from the Audio Device + + AURenderCallbackStruct AUCallBack; + + AUCallBack.inputProc = (AURenderCallback)(audio_osx_source::AUInputCallback); + AUCallBack.inputProcRefCon = this; + + err = AudioUnitSetProperty (d_InputAU, + kAudioOutputUnitProperty_SetInputCallback, + kAudioUnitScope_Global, + 0, + &AUCallBack, + sizeof (AURenderCallbackStruct)); + CheckErrorAndThrow (err, "AudioUnitSetProperty Input Callback", + "audio_osx_source::audio_osx_source"); + + UInt32 propertySize; + AudioStreamBasicDescription asbd_device, asbd_client, asbd_user; + +// asbd_device: ASBD of the device that is creating the input data stream +// asbd_client: ASBD of the client size (output) of the hardware device +// asbd_user: ASBD of the user's arguments + +// Get the Stream Format (device side) + + propertySize = sizeof (asbd_device); + err = AudioUnitGetProperty (d_InputAU, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 1, + &asbd_device, + &propertySize); + CheckErrorAndThrow (err, "AudioUnitGetProperty Device Input Stream Format", + "audio_osx_source::audio_osx_source"); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "---- Device Stream Format ----\n" ); + PrintStreamDesc (&asbd_device); +#endif + +// Get the Stream Format (client side) + propertySize = sizeof (asbd_client); + err = AudioUnitGetProperty (d_InputAU, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 1, + &asbd_client, + &propertySize); + CheckErrorAndThrow (err, "AudioUnitGetProperty Device Ouput Stream Format", + "audio_osx_source::audio_osx_source"); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "---- Client Stream Format ----\n"); + PrintStreamDesc (&asbd_client); +#endif + +// Set the format of all the AUs to the input/output devices channel count + +// get the max number of input (& thus output) channels supported by +// this device + d_n_max_channels = asbd_client.mChannelsPerFrame; + +// create the output io signature; +// no input siganture to set (source is hardware) + set_output_signature (gr_make_io_signature (1, + d_n_max_channels, + sizeof (float))); + +// allocate the output circular buffer(s), one per channel + d_buffers = (circular_buffer**) new + circular_buffer* [d_n_max_channels]; + UInt32 n_alloc = (UInt32) ceil ((double) d_max_sample_count); + for (UInt32 n = 0; n < d_n_max_channels; n++) { + d_buffers[n] = new circular_buffer (n_alloc, false, false); + } + + d_deviceSampleRate = asbd_device.mSampleRate; + d_n_deviceChannels = asbd_device.mChannelsPerFrame; + +// create an ASBD for the user's wants + + asbd_user.mSampleRate = d_outputSampleRate; + asbd_user.mFormatID = kAudioFormatLinearPCM; + asbd_user.mFormatFlags = (kLinearPCMFormatFlagIsFloat | + GR_PCM_ENDIANNESS | + kLinearPCMFormatFlagIsPacked | + kAudioFormatFlagIsNonInterleaved); + asbd_user.mBytesPerPacket = 4; + asbd_user.mFramesPerPacket = 1; + asbd_user.mBytesPerFrame = 4; + asbd_user.mChannelsPerFrame = d_n_max_channels; + asbd_user.mBitsPerChannel = 32; + + if (d_deviceSampleRate == d_outputSampleRate) { +// no need to do conversion if asbd_client matches user wants + d_passThrough = true; + d_leadSizeFrames = d_trailSizeFrames = 0L; + } else { + d_passThrough = false; +// Create the audio converter + + err = AudioConverterNew (&asbd_client, &asbd_user, &d_AudioConverter); + CheckErrorAndThrow (err, "AudioConverterNew", + "audio_osx_source::audio_osx_source"); + +// Set the audio converter sample rate quality to "max" ... +// requires more samples, but should sound nicer + + UInt32 ACQuality = kAudioConverterQuality_Max; + propertySize = sizeof (ACQuality); + err = AudioConverterSetProperty (d_AudioConverter, + kAudioConverterSampleRateConverterQuality, + propertySize, + &ACQuality); + CheckErrorAndThrow (err, "AudioConverterSetProperty " + "SampleRateConverterQuality", + "audio_osx_source::audio_osx_source"); + +// set the audio converter's prime method to "pre", +// which uses both leading and trailing frames +// from the "current input". All of this is handled +// internally by the AudioConverter; we just supply +// the frames for conversion. + +// UInt32 ACPrimeMethod = kConverterPrimeMethod_None; + UInt32 ACPrimeMethod = kConverterPrimeMethod_Pre; + propertySize = sizeof (ACPrimeMethod); + err = AudioConverterSetProperty (d_AudioConverter, + kAudioConverterPrimeMethod, + propertySize, + &ACPrimeMethod); + CheckErrorAndThrow (err, "AudioConverterSetProperty PrimeMethod", + "audio_osx_source::audio_osx_source"); + +// Get the size of the I/O buffer(s) to allow for pre-allocated buffers + +// lead frame info (trail frame info is ignored) + + AudioConverterPrimeInfo ACPrimeInfo = {0, 0}; + propertySize = sizeof (ACPrimeInfo); + err = AudioConverterGetProperty (d_AudioConverter, + kAudioConverterPrimeInfo, + &propertySize, + &ACPrimeInfo); + CheckErrorAndThrow (err, "AudioConverterGetProperty PrimeInfo", + "audio_osx_source::audio_osx_source"); + + switch (ACPrimeMethod) { + case (kConverterPrimeMethod_None): + d_leadSizeFrames = + d_trailSizeFrames = 0L; + break; + case (kConverterPrimeMethod_Normal): + d_leadSizeFrames = 0L; + d_trailSizeFrames = ACPrimeInfo.trailingFrames; + break; + default: + d_leadSizeFrames = ACPrimeInfo.leadingFrames; + d_trailSizeFrames = ACPrimeInfo.trailingFrames; + } + } + d_leadSizeBytes = d_leadSizeFrames * sizeof (Float32); + d_trailSizeBytes = d_trailSizeFrames * sizeof (Float32); + + propertySize = sizeof (d_deviceBufferSizeFrames); + err = AudioUnitGetProperty (d_InputAU, + kAudioDevicePropertyBufferFrameSize, + kAudioUnitScope_Global, + 0, + &d_deviceBufferSizeFrames, + &propertySize); + CheckErrorAndThrow (err, "AudioUnitGetProperty Buffer Frame Size", + "audio_osx_source::audio_osx_source"); + + d_deviceBufferSizeBytes = d_deviceBufferSizeFrames * sizeof (Float32); + d_inputBufferSizeBytes = d_deviceBufferSizeBytes + d_leadSizeBytes; + d_inputBufferSizeFrames = d_deviceBufferSizeFrames + d_leadSizeFrames; + +// outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in) +// since this is rarely exact, we need another buffer to hold +// "extra" samples not processed at any given sampling period +// this buffer must be at least 4 floats in size, but generally +// follows the rule that +// extraBufSize = ceil (rate_in / rate_out)*sizeof(float) + + d_extraBufferSizeFrames = ((UInt32) ceil (d_deviceSampleRate + / d_outputSampleRate) + * sizeof (float)); + if (d_extraBufferSizeFrames < 4) + d_extraBufferSizeFrames = 4; + d_extraBufferSizeBytes = d_extraBufferSizeFrames * sizeof (float); + + d_outputBufferSizeFrames = (UInt32) ceil (((Float64) d_inputBufferSizeFrames) + * d_outputSampleRate + / d_deviceSampleRate); + d_outputBufferSizeBytes = d_outputBufferSizeFrames * sizeof (float); + d_inputBufferSizeFrames += d_extraBufferSizeFrames; + +// pre-alloc all buffers + + AllocAudioBufferList (&d_InputBuffer, d_n_deviceChannels, + d_inputBufferSizeBytes); + if (d_passThrough == false) { + AllocAudioBufferList (&d_OutputBuffer, d_n_max_channels, + d_outputBufferSizeBytes); + } else { + d_OutputBuffer = d_InputBuffer; + } + +// create the stuff to regulate I/O + + d_internal = new mld_mutex (); + if (d_internal == NULL) + CheckErrorAndThrow (errno, "new mld_mutex (internal)", + "audio_osx_source::audio_osx_source"); + + d_cond_data = new mld_condition (); + if (d_cond_data == NULL) + CheckErrorAndThrow (errno, "new mld_condition (data)", + "audio_osx_source::audio_osx_source"); + +// initialize the AU for input + + err = AudioUnitInitialize (d_InputAU); + CheckErrorAndThrow (err, "AudioUnitInitialize", + "audio_osx_source::audio_osx_source"); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "audio_osx_source Parameters:\n"); + fprintf (stderr, " Device Sample Rate is %g\n", d_deviceSampleRate); + fprintf (stderr, " User Sample Rate is %g\n", d_outputSampleRate); + fprintf (stderr, " Max Sample Count is %ld\n", d_max_sample_count); + fprintf (stderr, " # Device Channels is %ld\n", d_n_deviceChannels); + fprintf (stderr, " # Max Channels is %ld\n", d_n_max_channels); + fprintf (stderr, " Device Buffer Size is Frames = %ld\n", + d_deviceBufferSizeFrames); + fprintf (stderr, " Lead Size is Frames = %ld\n", + d_leadSizeFrames); + fprintf (stderr, " Trail Size is Frames = %ld\n", + d_trailSizeFrames); + fprintf (stderr, " Input Buffer Size is Frames = %ld\n", + d_inputBufferSizeFrames); + fprintf (stderr, " Output Buffer Size is Frames = %ld\n", + d_outputBufferSizeFrames); +#endif +} + +void +audio_osx_source::AllocAudioBufferList (AudioBufferList** t_ABL, + UInt32 n_channels, + UInt32 bufferSizeBytes) +{ + FreeAudioBufferList (t_ABL); + UInt32 propertySize = (offsetof (AudioBufferList, mBuffers[0]) + + (sizeof (AudioBuffer) * n_channels)); + *t_ABL = (AudioBufferList*) calloc (1, propertySize); + (*t_ABL)->mNumberBuffers = n_channels; + + int counter = n_channels; + + while (--counter >= 0) { + (*t_ABL)->mBuffers[counter].mNumberChannels = 1; + (*t_ABL)->mBuffers[counter].mDataByteSize = bufferSizeBytes; + (*t_ABL)->mBuffers[counter].mData = calloc (1, bufferSizeBytes); + } +} + +void +audio_osx_source::FreeAudioBufferList (AudioBufferList** t_ABL) +{ +// free pre-allocated audio buffer, if it exists + if (*t_ABL != NULL) { + int counter = (*t_ABL)->mNumberBuffers; + while (--counter >= 0) + free ((*t_ABL)->mBuffers[counter].mData); + free (*t_ABL); + (*t_ABL) = 0; + } +} + +bool audio_osx_source::IsRunning () +{ + UInt32 AURunning = 0, AUSize = sizeof (UInt32); + + OSStatus err = AudioUnitGetProperty (d_InputAU, + kAudioOutputUnitProperty_IsRunning, + kAudioUnitScope_Global, + 0, + &AURunning, + &AUSize); + CheckErrorAndThrow (err, "AudioUnitGetProperty IsRunning", + "audio_osx_source::IsRunning"); + + return (AURunning); +} + +bool audio_osx_source::start () +{ + if (! IsRunning ()) { + OSStatus err = AudioOutputUnitStart (d_InputAU); + CheckErrorAndThrow (err, "AudioOutputUnitStart", + "audio_osx_source::start"); + } + + return (true); +} + +bool audio_osx_source::stop () +{ + if (IsRunning ()) { + OSStatus err = AudioOutputUnitStop (d_InputAU); + CheckErrorAndThrow (err, "AudioOutputUnitStart", + "audio_osx_source::stop"); + for (UInt32 n = 0; n < d_n_user_channels; n++) { + d_buffers[n]->abort (); + } + } + + return (true); +} + +audio_osx_source::~audio_osx_source () +{ + OSStatus err = noErr; + +// stop the AudioUnit + stop(); + +#if _OSX_DO_LISTENERS_ +// remove the listeners + + err = AudioUnitRemovePropertyListener + (d_InputAU, + kAudioUnitProperty_StreamFormat, + (AudioUnitPropertyListenerProc) UnitListener); + CheckError (err, "~audio_osx_source: AudioUnitRemovePropertyListener"); + + err = AudioHardwareRemovePropertyListener + (kAudioHardwarePropertyDefaultInputDevice, + (AudioHardwarePropertyListenerProc) HardwareListener); + CheckError (err, "~audio_osx_source: AudioHardwareRemovePropertyListener"); +#endif + +// free pre-allocated audio buffers + FreeAudioBufferList (&d_InputBuffer); + + if (d_passThrough == false) { + err = AudioConverterDispose (d_AudioConverter); + CheckError (err, "~audio_osx_source: AudioConverterDispose"); + FreeAudioBufferList (&d_OutputBuffer); + } + +// remove the audio unit + err = AudioUnitUninitialize (d_InputAU); + CheckError (err, "~audio_osx_source: AudioUnitUninitialize"); + + err = CloseComponent (d_InputAU); + CheckError (err, "~audio_osx_source: CloseComponent"); + +// empty and delete the queues + for (UInt32 n = 0; n < d_n_max_channels; n++) { + delete d_buffers[n]; + d_buffers[n] = 0; + } + delete [] d_buffers; + d_buffers = 0; + +// close and delete the control stuff + delete d_internal; + delete d_cond_data; +} + +audio_osx_source_sptr +audio_osx_make_source (int sampling_freq, + const std::string device_name, + bool do_block, + int channel_config, + int max_sample_count) +{ + return audio_osx_source_sptr (new audio_osx_source (sampling_freq, + device_name, + do_block, + channel_config, + max_sample_count)); +} + +bool +audio_osx_source::check_topology (int ninputs, int noutputs) +{ +// check # inputs to make sure it's valid + if (ninputs != 0) { + fprintf (stderr, "audio_osx_source::check_topology(): " + "number of input streams provided (%d) should be 0.\n", + ninputs); + throw std::runtime_error ("audio_osx_source::check_topology()"); + } + +// check # outputs to make sure it's valid + if ((noutputs < 1) | (noutputs > (int) d_n_max_channels)) { + fprintf (stderr, "audio_osx_source::check_topology(): " + "number of output streams provided (%d) should be in " + "[1,%ld] for the selected audio device.\n", + noutputs, d_n_max_channels); + throw std::runtime_error ("audio_osx_source::check_topology()"); + } + +// save the actual number of output (user) channels + d_n_user_channels = noutputs; + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "chk_topo: Actual # user output channels = %d\n", + noutputs); +#endif + + return (true); +} + +int +audio_osx_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ +// acquire control to do processing here only + d_internal->wait (); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "work1: SC = %4ld, #OI = %4d, #Chan = %ld\n", + d_queueSampleCount, noutput_items, output_items.size()); +#endif + +// ?: always block until there is something to output from the source +// or return anything that is available, even if it's less than desired? + + UInt32 actual_noutput_items = noutput_items; + + if (d_queueSampleCount < actual_noutput_items) { + if (d_queueSampleCount == 0) { +// no data; do_block decides what to do + if (d_do_block == true) { + while (d_queueSampleCount == 0) { +// release control so-as to allow data to be retrieved + d_internal->post (); +// block until there is data to return + d_cond_data->wait (); +// the condition's signal() was called; acquire control +// to keep thread safe + d_internal->wait (); + } + } else { +// not enough data & not blocking; return nothing + return (0); + } + } + actual_noutput_items = d_queueSampleCount; + } + + int l_counter = (int) output_items.size(); + +// get the items from the circular buffers + while (--l_counter >= 0) { + UInt32 t_n_output_items = actual_noutput_items; + d_buffers[l_counter]->dequeue ((float*) output_items[l_counter], + &t_n_output_items); + if (t_n_output_items != actual_noutput_items) { + fprintf (stderr, "audio_osx_source::work(): " + "number of available items changing " + "unexpectedly; expecting %ld, got %ld.\n", + actual_noutput_items, t_n_output_items); + throw std::runtime_error ("audio_osx_source::work()"); + } + } + + d_queueSampleCount -= actual_noutput_items; + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "work2: SC = %4ld, act#OI = %4ld\n", + d_queueSampleCount, actual_noutput_items); +#endif + +// release control to allow for other processing parts to run + d_internal->post (); + + return (actual_noutput_items); +} + +OSStatus +audio_osx_source::ConverterCallback (AudioConverterRef inAudioConverter, + UInt32* ioNumberDataPackets, + AudioBufferList* ioData, + AudioStreamPacketDescription** ioASPD, + void* inUserData) +{ +// take current device buffers and copy them to the tail of the input buffers +// the lead buffer is already there in the first d_leadSizeFrames slots + + audio_osx_source* This = static_cast(inUserData); + AudioBufferList* l_inputABL = This->d_InputBuffer; + UInt32 totalInputBufferSizeBytes = ((*ioNumberDataPackets) * sizeof (float)); + int counter = This->d_n_deviceChannels; + ioData->mNumberBuffers = This->d_n_deviceChannels; + This->d_n_ActualInputFrames = (*ioNumberDataPackets); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cc1: io#DP = %ld, TIBSB = %ld, #C = %d\n", + *ioNumberDataPackets, totalInputBufferSizeBytes, counter); +#endif + + while (--counter >= 0) { + AudioBuffer* l_ioD_AB = &(ioData->mBuffers[counter]); + l_ioD_AB->mNumberChannels = 1; + l_ioD_AB->mData = (float*)(l_inputABL->mBuffers[counter].mData); + l_ioD_AB->mDataByteSize = totalInputBufferSizeBytes; + } + + return (noErr); +} + +OSStatus +audio_osx_source::AUInputCallback (void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) +{ + OSStatus err = noErr; + audio_osx_source* This = static_cast(inRefCon); + + This->d_internal->wait (); + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cb0: in#F = %4ld, inBN = %ld, SC = %4ld\n", + inNumberFrames, inBusNumber, This->d_queueSampleCount); +#endif + +// Get the new audio data from the input device + + err = AudioUnitRender (This->d_InputAU, + ioActionFlags, + inTimeStamp, + 1, //inBusNumber, + inNumberFrames, + This->d_InputBuffer); + CheckErrorAndThrow (err, "AudioUnitRender", + "audio_osx_source::AUInputCallback"); + + UInt32 AvailableInputFrames = inNumberFrames; + This->d_n_AvailableInputFrames = inNumberFrames; + +// get the number of actual output frames, +// either via converting the buffer or not + + UInt32 ActualOutputFrames; + + if (This->d_passThrough == true) { + ActualOutputFrames = AvailableInputFrames; + } else { + UInt32 AvailableInputBytes = AvailableInputFrames * sizeof (float); + UInt32 AvailableOutputBytes = AvailableInputBytes; + UInt32 AvailableOutputFrames = AvailableOutputBytes / sizeof (float); + UInt32 propertySize = sizeof (AvailableOutputBytes); + err = AudioConverterGetProperty (This->d_AudioConverter, + kAudioConverterPropertyCalculateOutputBufferSize, + &propertySize, + &AvailableOutputBytes); + CheckErrorAndThrow (err, "AudioConverterGetProperty CalculateOutputBufferSize", "audio_osx_source::audio_osx_source"); + + AvailableOutputFrames = AvailableOutputBytes / sizeof (float); + +#if 0 +// when decimating too much, the output sounds warbly due to +// fluctuating # of output frames +// This should not be a surprise, but there's probably some +// clever programming that could lessed the effect ... +// like finding the "ideal" # of output frames, and keeping +// that number constant no matter the # of input frames + UInt32 l_InputBytes = AvailableOutputBytes; + propertySize = sizeof (AvailableOutputBytes); + err = AudioConverterGetProperty (This->d_AudioConverter, + kAudioConverterPropertyCalculateInputBufferSize, + &propertySize, + &l_InputBytes); + CheckErrorAndThrow (err, "AudioConverterGetProperty CalculateInputBufferSize", "audio_osx_source::audio_osx_source"); + + if (l_InputBytes < AvailableInputBytes) { +// OK to zero pad the input a little + AvailableOutputFrames += 1; + AvailableOutputBytes = AvailableOutputFrames * sizeof (float); + } +#endif + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cb1: avail: #IF = %ld, #OF = %ld\n", + AvailableInputFrames, AvailableOutputFrames); +#endif + ActualOutputFrames = AvailableOutputFrames; + +// convert the data to the correct rate +// on input, ActualOutputFrames is the number of available output frames + + err = AudioConverterFillComplexBuffer (This->d_AudioConverter, + (AudioConverterComplexInputDataProc)(This->ConverterCallback), + inRefCon, + &ActualOutputFrames, + This->d_OutputBuffer, + NULL); + CheckErrorAndThrow (err, "AudioConverterFillComplexBuffer", + "audio_osx_source::AUInputCallback"); + +// on output, ActualOutputFrames is the actual number of output frames + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cb2: actual: #IF = %ld, #OF = %ld\n", + This->d_n_ActualInputFrames, AvailableOutputFrames); + if (This->d_n_ActualInputFrames != AvailableInputFrames) + fprintf (stderr, "cb2.1: avail#IF = %ld, actual#IF = %ld\n", + AvailableInputFrames, This->d_n_ActualInputFrames); +#endif + } + +// add the output frames to the buffers' queue, checking for overflow + + int l_counter = This->d_n_user_channels; + int res = 0; + + while (--l_counter >= 0) { + float* inBuffer = (float*) This->d_OutputBuffer->mBuffers[l_counter].mData; + int l_res = This->d_buffers[l_counter]->enqueue (inBuffer, ActualOutputFrames); + if (l_res == -1) + res = -1; + } + + if (res == -1) { +// data coming in too fast +// drop oldest buffer + fputs ("aO", stderr); + fflush (stderr); +// set the local number of samples available to the max + This->d_queueSampleCount = This->d_buffers[0]->buffer_length_items (); + } else { +// keep up the local sample count + This->d_queueSampleCount += ActualOutputFrames; + } + +#if _OSX_AU_DEBUG_ + fprintf (stderr, "cb5: #OI = %4ld, #Cnt = %4ld, mSC = %ld, \n", + ActualOutputFrames, This->d_queueSampleCount, + This->d_max_sample_count); +#endif + +// signal that data is available, if appropraite + This->d_cond_data->signal (); + +// release control to allow for other processing parts to run + This->d_internal->post (); + + return (err); +} + +void +audio_osx_source::SetDefaultInputDeviceAsCurrent +() +{ +// set the default input device + AudioDeviceID deviceID; + UInt32 dataSize = sizeof (AudioDeviceID); + AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice, + &dataSize, + &deviceID); + OSStatus err = AudioUnitSetProperty (d_InputAU, + kAudioOutputUnitProperty_CurrentDevice, + kAudioUnitScope_Global, + 0, + &deviceID, + sizeof (AudioDeviceID)); + CheckErrorAndThrow (err, "AudioUnitSetProperty Current Device", + "audio_osx_source::SetDefaultInputDeviceAsCurrent"); +} + +#if _OSX_DO_LISTENERS_ +OSStatus +audio_osx_source::HardwareListener +(AudioHardwarePropertyID inPropertyID, + void *inClientData) +{ + OSStatus err = noErr; + audio_osx_source* This = static_cast(inClientData); + + fprintf (stderr, "a_o_s::HardwareListener\n"); + +// set the new default hardware input device for use by our AU + + This->SetDefaultInputDeviceAsCurrent (); + +// reset the converter to tell it that the stream has changed + + err = AudioConverterReset (This->d_AudioConverter); + CheckErrorAndThrow (err, "AudioConverterReset", + "audio_osx_source::UnitListener"); + + return (err); +} + +OSStatus +audio_osx_source::UnitListener +(void *inRefCon, + AudioUnit ci, + AudioUnitPropertyID inID, + AudioUnitScope inScope, + AudioUnitElement inElement) +{ + OSStatus err = noErr; + audio_osx_source* This = static_cast(inRefCon); + AudioStreamBasicDescription asbd; + + fprintf (stderr, "a_o_s::UnitListener\n"); + +// get the converter's input ASBD (for printing) + + UInt32 propertySize = sizeof (asbd); + err = AudioConverterGetProperty (This->d_AudioConverter, + kAudioConverterCurrentInputStreamDescription, + &propertySize, + &asbd); + CheckErrorAndThrow (err, "AudioConverterGetProperty " + "CurrentInputStreamDescription", + "audio_osx_source::UnitListener"); + + fprintf (stderr, "UnitListener: Input Source changed.\n" + "Old Source Output Info:\n"); + PrintStreamDesc (&asbd); + +// get the new input unit's output ASBD + + propertySize = sizeof (asbd); + err = AudioUnitGetProperty (This->d_InputAU, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, 1, + &asbd, &propertySize); + CheckErrorAndThrow (err, "AudioUnitGetProperty StreamFormat", + "audio_osx_source::UnitListener"); + + fprintf (stderr, "New Source Output Info:\n"); + PrintStreamDesc (&asbd); + +// set the converter's input ASBD to this + + err = AudioConverterSetProperty (This->d_AudioConverter, + kAudioConverterCurrentInputStreamDescription, + propertySize, + &asbd); + CheckErrorAndThrow (err, "AudioConverterSetProperty " + "CurrentInputStreamDescription", + "audio_osx_source::UnitListener"); + +// reset the converter to tell it that the stream has changed + + err = AudioConverterReset (This->d_AudioConverter); + CheckErrorAndThrow (err, "AudioConverterReset", + "audio_osx_source::UnitListener"); + + return (err); +} +#endif diff --git a/gr-audio-osx/src/audio_osx_source.h b/gr-audio-osx/src/audio_osx_source.h new file mode 100644 index 00000000..1799588e --- /dev/null +++ b/gr-audio-osx/src/audio_osx_source.h @@ -0,0 +1,132 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_OSX_SOURCE_H +#define INCLUDED_AUDIO_OSX_SOURCE_H + +#include +#include +#include +#include +#include + +class audio_osx_source; +typedef boost::shared_ptr audio_osx_source_sptr; + +audio_osx_source_sptr +audio_osx_make_source (int sample_rate = 44100, + const std::string device_name = "", + bool do_block = true, + int channel_config = -1, + int max_sample_count = -1); + +/*! + * \brief audio source using OSX + * + * Input signature is one or two streams of floats. + * Samples must be in the range [-1,1]. + */ + +class audio_osx_source : public gr_sync_block { + friend audio_osx_source_sptr + audio_osx_make_source (int sample_rate, + const std::string device_name, + bool do_block, + int channel_config, + int max_sample_count); + + Float64 d_deviceSampleRate, d_outputSampleRate; + int d_channel_config; + UInt32 d_inputBufferSizeFrames, d_inputBufferSizeBytes; + UInt32 d_outputBufferSizeFrames, d_outputBufferSizeBytes; + UInt32 d_deviceBufferSizeFrames, d_deviceBufferSizeBytes; + UInt32 d_leadSizeFrames, d_leadSizeBytes; + UInt32 d_trailSizeFrames, d_trailSizeBytes; + UInt32 d_extraBufferSizeFrames, d_extraBufferSizeBytes; + UInt32 d_queueSampleCount, d_max_sample_count; + UInt32 d_n_AvailableInputFrames, d_n_ActualInputFrames; + UInt32 d_n_user_channels, d_n_max_channels, d_n_deviceChannels; + bool d_do_block, d_passThrough, d_waiting_for_data; + mld_mutex_ptr d_internal; + mld_condition_ptr d_cond_data; + circular_buffer** d_buffers; + +// AudioUnits and Such + AudioUnit d_InputAU; + AudioBufferList* d_InputBuffer; + AudioBufferList* d_OutputBuffer; + AudioConverterRef d_AudioConverter; + +protected: + audio_osx_source (int sample_rate = 44100, + const std::string device_name = "", + bool do_block = true, + int channel_config = -1, + int max_sample_count = -1); + +public: + ~audio_osx_source (); + + bool start (); + bool stop (); + bool IsRunning (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +private: + void SetDefaultInputDeviceAsCurrent (); + + void AllocAudioBufferList (AudioBufferList** t_ABL, + UInt32 n_channels, + UInt32 inputBufferSizeBytes); + + void FreeAudioBufferList (AudioBufferList** t_ABL); + + static OSStatus ConverterCallback (AudioConverterRef inAudioConverter, + UInt32* ioNumberDataPackets, + AudioBufferList* ioData, + AudioStreamPacketDescription** outASPD, + void* inUserData); + + static OSStatus AUInputCallback (void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData); +#if _OSX_DO_LISTENERS_ + static OSStatus UnitListener (void *inRefCon, + AudioUnit ci, + AudioUnitPropertyID inID, + AudioUnitScope inScope, + AudioUnitElement inElement); + + static OSStatus HardwareListener (AudioHardwarePropertyID inPropertyID, + void *inClientData); +#endif +}; + +#endif /* INCLUDED_AUDIO_OSX_SOURCE_H */ diff --git a/gr-audio-osx/src/circular_buffer.h b/gr-audio-osx/src/circular_buffer.h new file mode 100644 index 00000000..f644e7d0 --- /dev/null +++ b/gr-audio-osx/src/circular_buffer.h @@ -0,0 +1,326 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CIRCULAR_BUFFER_H_ +#define _CIRCULAR_BUFFER_H_ + +#include "mld_threads.h" +#include + +#define DO_DEBUG 0 + +template class circular_buffer +{ +private: +// the buffer to use + T* d_buffer; + +// the following are in Items (type T) + UInt32 d_bufLen_I, d_readNdx_I, d_writeNdx_I; + UInt32 d_n_avail_write_I, d_n_avail_read_I; + +// stuff to control access to class internals + mld_mutex_ptr d_internal; + mld_condition_ptr d_readBlock, d_writeBlock; + +// booleans to decide how to control reading, writing, and aborting + bool d_doWriteBlock, d_doFullRead, d_doAbort; + + void delete_mutex_cond () { + if (d_internal) { + delete d_internal; + d_internal = NULL; + } + if (d_readBlock) { + delete d_readBlock; + d_readBlock = NULL; + } + if (d_writeBlock) { + delete d_writeBlock; + d_writeBlock = NULL; + } + }; + +public: + circular_buffer (UInt32 bufLen_I, + bool doWriteBlock = true, bool doFullRead = false) { + if (bufLen_I == 0) + throw std::runtime_error ("circular_buffer(): " + "Number of items to buffer must be > 0.\n"); + d_bufLen_I = bufLen_I; + d_buffer = (T*) new T[d_bufLen_I]; + d_doWriteBlock = doWriteBlock; + d_doFullRead = doFullRead; + d_internal = NULL; + d_readBlock = d_writeBlock = NULL; + reset (); +#if DO_DEBUG + fprintf (stderr, "c_b(): buf len (items) = %ld, " + "doWriteBlock = %s, doFullRead = %s\n", d_bufLen_I, + (d_doWriteBlock ? "true" : "false"), + (d_doFullRead ? "true" : "false")); +#endif + }; + + ~circular_buffer () { + delete_mutex_cond (); + delete [] d_buffer; + }; + + inline UInt32 n_avail_write_items () { + d_internal->lock (); + UInt32 retVal = d_n_avail_write_I; + d_internal->unlock (); + return (retVal); + }; + + inline UInt32 n_avail_read_items () { + d_internal->lock (); + UInt32 retVal = d_n_avail_read_I; + d_internal->unlock (); + return (retVal); + }; + + inline UInt32 buffer_length_items () {return (d_bufLen_I);}; + inline bool do_write_block () {return (d_doWriteBlock);}; + inline bool do_full_read () {return (d_doFullRead);}; + + void reset () { + d_doAbort = false; + bzero (d_buffer, d_bufLen_I * sizeof (T)); + d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0; + d_n_avail_write_I = d_bufLen_I; + delete_mutex_cond (); + d_internal = new mld_mutex (); + d_readBlock = new mld_condition (); + d_writeBlock = new mld_condition (); + }; + +/* + * enqueue: add the given buffer of item-length to the queue, + * first-in-first-out (FIFO). + * + * inputs: + * buf: a pointer to the buffer holding the data + * + * bufLen_I: the buffer length in items (of the instantiated type) + * + * returns: + * -1: on overflow (write is not blocking, and data is being + * written faster than it is being read) + * 0: if nothing to do (0 length buffer) + * 1: if success + * 2: in the process of aborting, do doing nothing + * + * will throw runtime errors if inputs are improper: + * buffer pointer is NULL + * buffer length is larger than the instantiated buffer length + */ + + int enqueue (T* buf, UInt32 bufLen_I) { +#if DO_DEBUG + fprintf (stderr, "enqueue: buf = %X, bufLen = %ld, #av_wr = %ld, " + "#av_rd = %ld.\n", (unsigned int)buf, bufLen_I, + d_n_avail_write_I, d_n_avail_read_I); +#endif + if (bufLen_I > d_bufLen_I) { + fprintf (stderr, "cannot add buffer longer (%ld" + ") than instantiated length (%ld" + ").\n", bufLen_I, d_bufLen_I); + throw std::runtime_error ("circular_buffer::enqueue()"); + } + + if (bufLen_I == 0) + return (0); + if (!buf) + throw std::runtime_error ("circular_buffer::enqueue(): " + "input buffer is NULL.\n"); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); + return (2); + } + if (bufLen_I > d_n_avail_write_I) { + if (d_doWriteBlock) { + while (bufLen_I > d_n_avail_write_I) { +#if DO_DEBUG + fprintf (stderr, "enqueue: #len > #a, waiting.\n"); +#endif + d_internal->unlock (); + d_writeBlock->wait (); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); +#if DO_DEBUG + fprintf (stderr, "enqueue: #len > #a, aborting.\n"); +#endif + return (2); + } +#if DO_DEBUG + fprintf (stderr, "enqueue: #len > #a, done waiting.\n"); +#endif + } + } else { + d_n_avail_read_I = d_bufLen_I - bufLen_I; + d_n_avail_write_I = bufLen_I; +#if DO_DEBUG + fprintf (stderr, "circular_buffer::enqueue: overflow\n"); +#endif + return (-1); + } + } + UInt32 n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0; + if (n_now_I > bufLen_I) + n_now_I = bufLen_I; + else if (n_now_I < bufLen_I) + n_start_I = bufLen_I - n_now_I; + bcopy (buf, &(d_buffer[d_writeNdx_I]), n_now_I * sizeof (T)); + if (n_start_I) { + bcopy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T)); + d_writeNdx_I = n_start_I; + } else + d_writeNdx_I += n_now_I; + d_n_avail_read_I += bufLen_I; + d_n_avail_write_I -= bufLen_I; + d_readBlock->signal (); + d_internal->unlock (); + return (1); + }; + +/* + * dequeue: removes from the queue the number of items requested, or + * available, into the given buffer on a FIFO basis. + * + * inputs: + * buf: a pointer to the buffer into which to copy the data + * + * bufLen_I: pointer to the number of items to remove in items + * (of the instantiated type) + * + * returns: + * 0: if nothing to do (0 length buffer) + * 1: if success + * 2: in the process of aborting, do doing nothing + * + * will throw runtime errors if inputs are improper: + * buffer pointer is NULL + * buffer length pointer is NULL + * buffer length is larger than the instantiated buffer length + */ + + int dequeue (T* buf, UInt32* bufLen_I) { +#if DO_DEBUG + fprintf (stderr, "dequeue: buf = %X, *bufLen = %ld, #av_wr = %ld, " + "#av_rd = %ld.\n", (unsigned int)buf, *bufLen_I, + d_n_avail_write_I, d_n_avail_read_I); +#endif + if (!bufLen_I) + throw std::runtime_error ("circular_buffer::dequeue(): " + "input bufLen pointer is NULL.\n"); + if (!buf) + throw std::runtime_error ("circular_buffer::dequeue(): " + "input buffer pointer is NULL.\n"); + UInt32 l_bufLen_I = *bufLen_I; + if (l_bufLen_I == 0) + return (0); + if (l_bufLen_I > d_bufLen_I) { + fprintf (stderr, "cannot remove buffer longer (%ld" + ") than instantiated length (%ld" + ").\n", l_bufLen_I, d_bufLen_I); + throw std::runtime_error ("circular_buffer::dequeue()"); + } + + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); + return (2); + } + if (d_doFullRead) { + while (d_n_avail_read_I < l_bufLen_I) { +#if DO_DEBUG + fprintf (stderr, "dequeue: #a < #len, waiting.\n"); +#endif + d_internal->unlock (); + d_readBlock->wait (); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); +#if DO_DEBUG + fprintf (stderr, "dequeue: #a < #len, aborting.\n"); +#endif + return (2); + } +#if DO_DEBUG + fprintf (stderr, "dequeue: #a < #len, done waiting.\n"); +#endif + } + } else { + while (d_n_avail_read_I == 0) { +#if DO_DEBUG + fprintf (stderr, "dequeue: #a == 0, waiting.\n"); +#endif + d_internal->unlock (); + d_readBlock->wait (); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); +#if DO_DEBUG + fprintf (stderr, "dequeue: #a == 0, aborting.\n"); +#endif + return (2); + } +#if DO_DEBUG + fprintf (stderr, "dequeue: #a == 0, done waiting.\n"); +#endif + } + } + if (l_bufLen_I > d_n_avail_read_I) + l_bufLen_I = d_n_avail_read_I; + UInt32 n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0; + if (n_now_I > l_bufLen_I) + n_now_I = l_bufLen_I; + else if (n_now_I < l_bufLen_I) + n_start_I = l_bufLen_I - n_now_I; + bcopy (&(d_buffer[d_readNdx_I]), buf, n_now_I * sizeof (T)); + if (n_start_I) { + bcopy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T)); + d_readNdx_I = n_start_I; + } else + d_readNdx_I += n_now_I; + *bufLen_I = l_bufLen_I; + d_n_avail_read_I -= l_bufLen_I; + d_n_avail_write_I += l_bufLen_I; + d_writeBlock->signal (); + d_internal->unlock (); + return (1); + }; + + void abort () { + d_internal->lock (); + d_doAbort = true; + d_writeBlock->signal (); + d_readBlock->signal (); + d_internal->unlock (); + }; +}; + +#endif /* _CIRCULAR_BUFFER_H_ */ diff --git a/gr-audio-osx/src/mld_threads.h b/gr-audio-osx/src/mld_threads.h new file mode 100644 index 00000000..12adc23e --- /dev/null +++ b/gr-audio-osx/src/mld_threads.h @@ -0,0 +1,255 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _INCLUDED_MLD_THREADS_H_ +#define _INCLUDED_MLD_THREADS_H_ + +/* classes which allow for either pthreads or omni_threads */ + +#ifdef _USE_OMNI_THREADS_ +#include +#else +#include +#endif + +#include + +#define __INLINE__ inline + +class mld_condition_t; + +class mld_mutex_t { +#ifdef _USE_OMNI_THREADS_ + typedef omni_mutex l_mutex, *l_mutex_ptr; +#else + typedef pthread_mutex_t l_mutex, *l_mutex_ptr; +#endif + + friend class mld_condition_t; + +private: + l_mutex_ptr d_mutex; + +protected: + inline l_mutex_ptr mutex () { return (d_mutex); }; + +public: + __INLINE__ mld_mutex_t () { +#ifdef _USE_OMNI_THREADS_ + d_mutex = new omni_mutex (); +#else + d_mutex = (l_mutex_ptr) new l_mutex; + int l_ret = pthread_mutex_init (d_mutex, NULL); + if (l_ret != 0) { + fprintf (stderr, "Error %d creating mutex.\n", l_ret); + throw std::runtime_error ("mld_mutex_t::mld_mutex_t()\n"); + } +#endif + }; + + __INLINE__ ~mld_mutex_t () { + unlock (); +#ifndef _USE_OMNI_THREADS_ + int l_ret = pthread_mutex_destroy (d_mutex); + if (l_ret != 0) { + fprintf (stderr, "mld_mutex_t::~mld_mutex_t(): " + "Error %d destroying mutex.\n", l_ret); + } +#endif + delete d_mutex; + d_mutex = NULL; + }; + + __INLINE__ void lock () { +#ifdef _USE_OMNI_THREADS_ + d_mutex->lock (); +#else + int l_ret = pthread_mutex_lock (d_mutex); + if (l_ret != 0) { + fprintf (stderr, "mld_mutex_t::lock(): " + "Error %d locking mutex.\n", l_ret); + } +#endif + }; + + __INLINE__ void unlock () { +#ifdef _USE_OMNI_THREADS_ + d_mutex->unlock (); +#else + int l_ret = pthread_mutex_unlock (d_mutex); + if (l_ret != 0) { + fprintf (stderr, "mld_mutex_t::unlock(): " + "Error %d locking mutex.\n", l_ret); + } +#endif + }; + + __INLINE__ bool trylock () { +#ifdef _USE_OMNI_THREADS_ + int l_ret = d_mutex->trylock (); +#else + int l_ret = pthread_mutex_unlock (d_mutex); +#endif + return (l_ret == 0 ? true : false); + }; + + inline void acquire () { lock(); }; + inline void release () { unlock(); }; + inline void wait () { lock(); }; + inline void post () { unlock(); }; +}; + +typedef mld_mutex_t mld_mutex, *mld_mutex_ptr; + +class mld_condition_t { +#ifdef _USE_OMNI_THREADS_ + typedef omni_condition l_condition, *l_condition_ptr; +#else + typedef pthread_cond_t l_condition, *l_condition_ptr; +#endif + +private: + l_condition_ptr d_condition; + mld_mutex_ptr d_mutex; + bool d_waiting; + +public: + __INLINE__ mld_condition_t () { + d_waiting = false; + d_mutex = new mld_mutex (); +#ifdef _USE_OMNI_THREADS_ + d_condition = new omni_condition (d_mutex->mutex ()); +#else + d_condition = (l_condition_ptr) new l_condition; + int l_ret = pthread_cond_init (d_condition, NULL); + if (l_ret != 0) { + fprintf (stderr, "Error %d creating condition.\n", l_ret); + throw std::runtime_error ("mld_condition_t::mld_condition_t()\n"); + } +#endif + }; + + __INLINE__ ~mld_condition_t () { + signal (); +#ifndef _USE_OMNI_THREADS_ + int l_ret = pthread_cond_destroy (d_condition); + if (l_ret != 0) { + fprintf (stderr, "mld_condition_t::mld_condition_t(): " + "Error %d destroying condition.\n", l_ret); + } +#endif + delete d_condition; + d_condition = NULL; + delete d_mutex; + d_mutex = NULL; + }; + + __INLINE__ void signal () { + if (d_waiting == true) { +#ifdef _USE_OMNI_THREADS_ + d_condition->signal (); +#else + int l_ret = pthread_cond_signal (d_condition); + if (l_ret != 0) { + fprintf (stderr, "mld_condition_t::signal(): " + "Error %d.\n", l_ret); + } +#endif + d_waiting = false; + } + }; + + __INLINE__ void wait () { + if (d_waiting == false) { + d_waiting = true; +#ifdef _USE_OMNI_THREADS_ + d_condition->wait (); +#else + int l_ret = pthread_cond_wait (d_condition, d_mutex->mutex ()); + if (l_ret != 0) { + fprintf (stderr, "mld_condition_t::wait(): " + "Error %d.\n", l_ret); + } +#endif + } + }; +}; + +typedef mld_condition_t mld_condition, *mld_condition_ptr; + +class mld_thread_t { +#ifdef _USE_OMNI_THREADS_ + typedef omni_thread l_thread, *l_thread_ptr; +#else + typedef pthread_t l_thread, *l_thread_ptr; +#endif + +private: +#ifndef _USE_OMNI_THREADS_ + l_thread d_thread; + void (*d_start_routine)(void*); + void *d_arg; +#else + l_thread_ptr d_thread; +#endif + +#ifndef _USE_OMNI_THREADS_ + static void* local_start_routine (void *arg) { + mld_thread_t* This = (mld_thread_t*) arg; + (*(This->d_start_routine))(This->d_arg); + return (NULL); + }; +#endif + +public: + __INLINE__ mld_thread_t (void (*start_routine)(void *), void *arg) { +#ifdef _USE_OMNI_THREADS_ + d_thread = new omni_thread (start_routine, arg); + d_thread->start (); +#else + d_start_routine = start_routine; + d_arg = arg; + int l_ret = pthread_create (&d_thread, NULL, local_start_routine, this); + if (l_ret != 0) { + fprintf (stderr, "Error %d creating thread.\n", l_ret); + throw std::runtime_error ("mld_thread_t::mld_thread_t()\n"); + } +#endif + }; + + __INLINE__ ~mld_thread_t () { +#ifdef _USE_OMNI_THREADS_ +// delete d_thread; + d_thread = NULL; +#else + int l_ret = pthread_detach (d_thread); + if (l_ret != 0) { + fprintf (stderr, "Error %d detaching thread.\n", l_ret); + throw std::runtime_error ("mld_thread_t::~mld_thread_t()\n"); + } +#endif + }; +}; + +typedef mld_thread_t mld_thread, *mld_thread_ptr; + +#endif /* _INCLUDED_MLD_THREADS_H_ */ diff --git a/gr-audio-osx/src/qa_osx.py b/gr-audio-osx/src/qa_osx.py new file mode 100755 index 00000000..1e85c158 --- /dev/null +++ b/gr-audio-osx/src/qa_osx.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio. +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_osx + +class qa_osx (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have OSX drivers, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-osx/src/run_tests.in b/gr-audio-osx/src/run_tests.in new file mode 100644 index 00000000..52de4dd1 --- /dev/null +++ b/gr-audio-osx/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-osx/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-osx/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-osx/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-audio-osx/src/test_audio_loop.py b/gr-audio-osx/src/test_audio_loop.py new file mode 100755 index 00000000..825908f5 --- /dev/null +++ b/gr-audio-osx/src/test_audio_loop.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio. +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", + type="string", + default="", + help="audio output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-I", "--audio-input", + type="string", + default="", + help="audio input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", + type="eng_float", + default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_output) + dst = audio.sink (sample_rate, options.audio_output) + + max_chan = max (src.output_signature().max_streams(), + dst.output_signature().max_streams()) + + for i in range (max_chan): + self.connect ((src, i), (dst, i)) + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gr-audio-portaudio/AUTHORS b/gr-audio-portaudio/AUTHORS new file mode 100644 index 00000000..65ca9014 --- /dev/null +++ b/gr-audio-portaudio/AUTHORS @@ -0,0 +1,2 @@ +Eric Blossom +Ramakrishnan Muthukrishnan diff --git a/gr-audio-portaudio/ChangeLog b/gr-audio-portaudio/ChangeLog new file mode 100644 index 00000000..36838902 --- /dev/null +++ b/gr-audio-portaudio/ChangeLog @@ -0,0 +1,31 @@ +2006-03-17 Eric Blossom + + * src/audio_portaudio_sink.{h,cc}: revised to use a gr_buffer as the + ring buffer. + +2006-03-12 Stephane Fillod + + * src/audio_portaudio_source.{h,cc}: first cut from gr-audio-jack sources. + * src/audio_portaudio_sink.{h,cc}: first cut from gr-audio-jack sources. + + +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-portaudio/Makefile.am b/gr-audio-portaudio/Makefile.am new file mode 100644 index 00000000..d7a05ea8 --- /dev/null +++ b/gr-audio-portaudio/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = gr-audio-portaudio.conf +SUBDIRS = src + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gr-audio-portaudio.conf diff --git a/gr-audio-portaudio/README b/gr-audio-portaudio/README new file mode 100644 index 00000000..6074c0b3 --- /dev/null +++ b/gr-audio-portaudio/README @@ -0,0 +1,92 @@ +These instructions are intended for Linux. On other systems you will have to +construct something compatible to build gr-audio-portaudio. + +In order to use portaudio with gnuradio you will need to download and install +a late version of portaudio. Please cd to a directory where the cvs command +below will be allowed to build the portaudio directory tree. + +cvs -d:pserver:anonymous@www.portaudio.com:/home/cvs co -r v19-devel portaudio + +This will make a directory portaudio unless you already have one. It will +check out the Portaudio API version 2 release 1.9. + +In the directory where this README is found, there is a patch file. Hopefully +this patch will not be needed for long. Portaudio is working with us to use +auto*, libtool, etc. The patch is autoconfiscate.patch. + +cd to the portaudio directory and run + +patch -p0 + + // We only need IASIOThiscallResolver at all if we are on Win32. For other + // platforms we simply bypass the IASIOThiscallResolver definition to allow us +Index: pa_asio/pa_asio.cpp +=================================================================== +RCS file: /home/cvs/portaudio/pa_asio/pa_asio.cpp,v +retrieving revision 1.7.2.68 +diff -u -b -B -w -p -r1.7.2.68 pa_asio.cpp +--- pa_asio/pa_asio.cpp 5 Dec 2005 04:55:28 -0000 1.7.2.68 ++++ pa_asio/pa_asio.cpp 19 Mar 2006 22:26:14 -0000 +@@ -106,7 +106,7 @@ + must be closed). + */ + +- ++#include + + #include + #include +Index: pa_common/pa_allocation.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_allocation.c,v +retrieving revision 1.1.2.6 +diff -u -b -B -w -p -r1.1.2.6 pa_allocation.c +--- pa_common/pa_allocation.c 20 Dec 2004 12:07:51 -0000 1.1.2.6 ++++ pa_common/pa_allocation.c 19 Mar 2006 22:26:15 -0000 +@@ -35,6 +35,8 @@ + */ + + ++#include ++ + #include "pa_allocation.h" + #include "pa_util.h" + +Index: pa_common/pa_converters.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_converters.c,v +retrieving revision 1.1.2.27 +diff -u -b -B -w -p -r1.1.2.27 pa_converters.c +--- pa_common/pa_converters.c 2 Nov 2005 12:14:07 -0000 1.1.2.27 ++++ pa_common/pa_converters.c 19 Mar 2006 22:26:23 -0000 +@@ -49,6 +49,8 @@ + */ + + ++#include ++ + #include "pa_converters.h" + #include "pa_dither.h" + #include "pa_endianness.h" +Index: pa_common/pa_cpuload.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_cpuload.c,v +retrieving revision 1.1.2.14 +diff -u -b -B -w -p -r1.1.2.14 pa_cpuload.c +--- pa_common/pa_cpuload.c 8 Jan 2004 22:01:12 -0000 1.1.2.14 ++++ pa_common/pa_cpuload.c 19 Mar 2006 22:26:24 -0000 +@@ -41,6 +41,8 @@ + */ + + ++#include ++ + #include "pa_cpuload.h" + + #include +Index: pa_common/pa_dither.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_dither.c,v +retrieving revision 1.1.2.6 +diff -u -b -B -w -p -r1.1.2.6 pa_dither.c +--- pa_common/pa_dither.c 28 May 2005 22:49:02 -0000 1.1.2.6 ++++ pa_common/pa_dither.c 19 Mar 2006 22:26:24 -0000 +@@ -34,6 +34,8 @@ + */ + + ++#include ++ + #include "pa_dither.h" + #include "pa_types.h" + +Index: pa_common/pa_front.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_front.c,v +retrieving revision 1.1.2.52 +diff -u -b -B -w -p -r1.1.2.52 pa_front.c +--- pa_common/pa_front.c 7 Dec 2005 20:10:34 -0000 1.1.2.52 ++++ pa_common/pa_front.c 19 Mar 2006 22:26:30 -0000 +@@ -89,6 +89,8 @@ enquire about status on the PortAudio ma + */ + + ++#include ++ + #include + #include + #include +Index: pa_common/pa_process.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_process.c,v +retrieving revision 1.1.2.51 +diff -u -b -B -w -p -r1.1.2.51 pa_process.c +--- pa_common/pa_process.c 27 Oct 2005 23:28:48 -0000 1.1.2.51 ++++ pa_common/pa_process.c 19 Mar 2006 22:26:35 -0000 +@@ -72,6 +72,8 @@ + */ + + ++#include ++ + #include + #include /* memset() */ + +Index: pa_common/pa_skeleton.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_skeleton.c,v +retrieving revision 1.1.2.39 +diff -u -b -B -w -p -r1.1.2.39 pa_skeleton.c +--- pa_common/pa_skeleton.c 26 Nov 2003 14:56:09 -0000 1.1.2.39 ++++ pa_common/pa_skeleton.c 19 Mar 2006 22:26:38 -0000 +@@ -40,6 +40,8 @@ + */ + + ++#include ++ + #include /* strlen() */ + + #include "pa_util.h" +Index: pa_common/pa_stream.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/Attic/pa_stream.c,v +retrieving revision 1.1.2.12 +diff -u -b -B -w -p -r1.1.2.12 pa_stream.c +--- pa_common/pa_stream.c 20 Sep 2003 21:31:00 -0000 1.1.2.12 ++++ pa_common/pa_stream.c 19 Mar 2006 22:26:39 -0000 +@@ -36,6 +36,8 @@ + */ + + ++#include ++ + #include "pa_stream.h" + + +Index: pa_common/pa_trace.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_common/pa_trace.c,v +retrieving revision 1.1.1.1.2.4 +diff -u -b -B -w -p -r1.1.1.1.2.4 pa_trace.c +--- pa_common/pa_trace.c 2 Nov 2005 12:06:44 -0000 1.1.1.1.2.4 ++++ pa_common/pa_trace.c 19 Mar 2006 22:26:39 -0000 +@@ -35,6 +35,8 @@ + */ + + ++#include ++ + #include + #include + #include +Index: pa_jack/pa_jack.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_jack/Attic/pa_jack.c,v +retrieving revision 1.1.2.20 +diff -u -b -B -w -p -r1.1.2.20 pa_jack.c +--- pa_jack/pa_jack.c 2 Oct 2005 22:02:26 -0000 1.1.2.20 ++++ pa_jack/pa_jack.c 19 Mar 2006 22:26:46 -0000 +@@ -35,6 +35,8 @@ + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + ++#include ++ + #include + #include + #include +@@ -56,7 +58,7 @@ + #include "pa_process.h" + #include "pa_allocation.h" + #include "pa_cpuload.h" +-#include "../pablio/ringbuffer.c" ++#include "pablio/ringbuffer.c" + + static int aErr_; + static PaError paErr_; /* For use with ENSURE_PA */ +Index: pa_linux_alsa/pa_linux_alsa.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_linux_alsa/Attic/pa_linux_alsa.c,v +retrieving revision 1.1.2.90 +diff -u -b -B -w -p -r1.1.2.90 pa_linux_alsa.c +--- pa_linux_alsa/pa_linux_alsa.c 19 Mar 2006 12:28:44 -0000 1.1.2.90 ++++ pa_linux_alsa/pa_linux_alsa.c 19 Mar 2006 22:27:00 -0000 +@@ -34,6 +34,8 @@ + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + ++#include ++ + #define ALSA_PCM_NEW_HW_PARAMS_API + #define ALSA_PCM_NEW_SW_PARAMS_API + #include +Index: pa_mac/pa_mac_hostapis.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_mac/Attic/pa_mac_hostapis.c,v +retrieving revision 1.1.2.1 +diff -u -b -B -w -p -r1.1.2.1 pa_mac_hostapis.c +--- pa_mac/pa_mac_hostapis.c 27 May 2004 22:39:58 -0000 1.1.2.1 ++++ pa_mac/pa_mac_hostapis.c 19 Mar 2006 22:27:00 -0000 +@@ -33,6 +33,7 @@ + Mac OS host API initialization function table. + */ + ++#include + + #include "pa_hostapi.h" + +Index: pa_mac_core/pa_mac_core.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_mac_core/pa_mac_core.c,v +retrieving revision 1.8.2.11 +diff -u -b -B -w -p -r1.8.2.11 pa_mac_core.c +--- pa_mac_core/pa_mac_core.c 27 Feb 2006 14:25:50 -0000 1.8.2.11 ++++ pa_mac_core/pa_mac_core.c 19 Mar 2006 22:27:08 -0000 +@@ -45,6 +45,8 @@ + @brief AUHAL implementation of PortAudio + */ + ++#include ++ + #include /* strlen(), memcmp() etc. */ + + #include +Index: pa_mac_core/pa_mac_core_old.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_mac_core/Attic/pa_mac_core_old.c,v +retrieving revision 1.1.2.1 +diff -u -b -B -w -p -r1.1.2.1 pa_mac_core_old.c +--- pa_mac_core/pa_mac_core_old.c 24 Dec 2005 01:22:52 -0000 1.1.2.1 ++++ pa_mac_core/pa_mac_core_old.c 19 Mar 2006 22:27:14 -0000 +@@ -34,6 +34,8 @@ + * + */ + ++#include ++ + #include + #include + #include +Index: pa_mac_core/pa_mac_core_utilities.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_mac_core/Attic/pa_mac_core_utilities.c,v +retrieving revision 1.1.2.2 +diff -u -b -B -w -p -r1.1.2.2 pa_mac_core_utilities.c +--- pa_mac_core/pa_mac_core_utilities.c 9 Dec 2005 19:43:14 -0000 1.1.2.2 ++++ pa_mac_core/pa_mac_core_utilities.c 19 Mar 2006 22:27:14 -0000 +@@ -10,6 +10,8 @@ + * by Bjorn Roche. + */ + ++#include ++ + /* + * Translates MacOS generated errors into PaErrors + */ +Index: pa_mac_sm/pa_mac_sm.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_mac_sm/Attic/pa_mac_sm.c,v +retrieving revision 1.1.2.1 +diff -u -b -B -w -p -r1.1.2.1 pa_mac_sm.c +--- pa_mac_sm/pa_mac_sm.c 7 Jun 2002 21:20:48 -0000 1.1.2.1 ++++ pa_mac_sm/pa_mac_sm.c 19 Mar 2006 22:27:21 -0000 +@@ -76,6 +76,8 @@ O- Add support for native sample data fo + O- Review buffer sizing. Should it be based on result of siDeviceBufferInfo query? + O- Determine default devices somehow. + */ ++#include ++ + #include + #include + #include +Index: pa_sgi/pa_sgi.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_sgi/pa_sgi.c,v +retrieving revision 1.2.2.20 +diff -u -b -B -w -p -r1.2.2.20 pa_sgi.c +--- pa_sgi/pa_sgi.c 3 Jan 2004 19:20:09 -0000 1.2.2.20 ++++ pa_sgi/pa_sgi.c 19 Mar 2006 22:27:27 -0000 +@@ -123,6 +123,8 @@ + a outputs stereo. One can observe this in SGI's 'Audio Queue Monitor'. + */ + ++#include ++ + #include /* For strlen() but also for strerror()! */ + #include /* printf() */ + #include /* fabs() */ +Index: pa_unix/pa_unix_hostapis.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_unix/Attic/pa_unix_hostapis.c,v +retrieving revision 1.1.2.5 +diff -u -b -B -w -p -r1.1.2.5 pa_unix_hostapis.c +--- pa_unix/pa_unix_hostapis.c 2 Oct 2003 12:35:46 -0000 1.1.2.5 ++++ pa_unix/pa_unix_hostapis.c 19 Mar 2006 22:27:28 -0000 +@@ -30,6 +30,8 @@ + */ + + ++#include ++ + #include "pa_hostapi.h" + + PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); +Index: pa_unix/pa_unix_util.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_unix/Attic/pa_unix_util.c,v +retrieving revision 1.1.2.8 +diff -u -b -B -w -p -r1.1.2.8 pa_unix_util.c +--- pa_unix/pa_unix_util.c 20 Nov 2005 13:46:13 -0000 1.1.2.8 ++++ pa_unix/pa_unix_util.c 19 Mar 2006 22:27:28 -0000 +@@ -31,6 +31,8 @@ + */ + + ++#include ++ + #include + #include + #include +Index: pa_unix_oss/pa_unix_oss.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_unix_oss/pa_unix_oss.c,v +retrieving revision 1.6.2.27 +diff -u -b -B -w -p -r1.6.2.27 pa_unix_oss.c +--- pa_unix_oss/pa_unix_oss.c 21 Feb 2006 19:13:56 -0000 1.6.2.27 ++++ pa_unix_oss/pa_unix_oss.c 19 Mar 2006 22:27:35 -0000 +@@ -35,6 +35,8 @@ + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + ++#include ++ + #include + #include + #include +@@ -42,7 +44,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -52,14 +53,21 @@ + #include + #include + +-#ifdef __FreeBSD__ ++#ifdef HAVE_SYS_SOUNDCARD_H + # include ++#elif HAVE_LINUX_SOUNDCARD_H ++# include ++#elif HAVE_SOUNDCARD_H ++# include ++#else ++# include /* JH20010905 */ ++#endif ++ ++#ifdef __FreeBSD__ + # define DEVICE_NAME_BASE "/dev/dsp" + #elif defined __linux__ +-# include + # define DEVICE_NAME_BASE "/dev/dsp" + #else +-# include /* JH20010905 */ + # define DEVICE_NAME_BASE "/dev/audio" + #endif + +@@ -1913,7 +1921,12 @@ static signed long GetStreamWriteAvailab + PaOssStream *stream = (PaOssStream*)s; + int delay = 0; + ++/* ++ * FIXME: SNDCTL_DSP_GETODELAY does not exist on NetBSD ++ */ ++#ifdef SNDCTL_DSP_GETODELAY + if( ioctl( stream->playback->fd, SNDCTL_DSP_GETODELAY, &delay ) < 0 ) ++#endif + return paUnanticipatedHostError; + + return (PaOssStreamComponent_BufferSize( stream->playback ) - delay) / PaOssStreamComponent_FrameSize( stream->playback ); +Index: pa_unix_oss/recplay.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_unix_oss/recplay.c,v +retrieving revision 1.1.1.1 +diff -u -b -B -w -p -r1.1.1.1 recplay.c +--- pa_unix_oss/recplay.c 22 Jan 2002 00:52:44 -0000 1.1.1.1 ++++ pa_unix_oss/recplay.c 19 Mar 2006 22:27:35 -0000 +@@ -4,6 +4,8 @@ + * Minimal record and playback test. + * + */ ++#include ++ + #include + #include + #include +Index: pa_win/pa_win_hostapis.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win/Attic/pa_win_hostapis.c,v +retrieving revision 1.1.2.10 +diff -u -b -B -w -p -r1.1.2.10 pa_win_hostapis.c +--- pa_win/pa_win_hostapis.c 8 Sep 2004 17:31:37 -0000 1.1.2.10 ++++ pa_win/pa_win_hostapis.c 19 Mar 2006 22:27:36 -0000 +@@ -36,6 +36,7 @@ + the Unix version does, we should consider being consistent. + */ + ++#include + + #include "pa_hostapi.h" + +Index: pa_win/pa_win_util.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win/Attic/pa_win_util.c,v +retrieving revision 1.1.2.7 +diff -u -b -B -w -p -r1.1.2.7 pa_win_util.c +--- pa_win/pa_win_util.c 15 Sep 2003 18:30:26 -0000 1.1.2.7 ++++ pa_win/pa_win_util.c 19 Mar 2006 22:27:36 -0000 +@@ -37,6 +37,9 @@ + bug. (see msdn kb Q274323). + */ + ++#include ++ ++ + #include + #include /* for timeGetTime() */ + +Index: pa_win/pa_x86_plain_converters.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win/Attic/pa_x86_plain_converters.c,v +retrieving revision 1.1.2.2 +diff -u -b -B -w -p -r1.1.2.2 pa_x86_plain_converters.c +--- pa_win/pa_x86_plain_converters.c 28 Feb 2003 01:49:59 -0000 1.1.2.2 ++++ pa_win/pa_x86_plain_converters.c 19 Mar 2006 22:27:40 -0000 +@@ -1,3 +1,5 @@ ++#include ++ + #include "pa_x86_plain_converters.h" + + #include "pa_converters.h" +Index: pa_win_ds/dsound_wrapper.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win_ds/dsound_wrapper.c,v +retrieving revision 1.1.1.1.2.11 +diff -u -b -B -w -p -r1.1.1.1.2.11 dsound_wrapper.c +--- pa_win_ds/dsound_wrapper.c 7 Sep 2003 13:04:53 -0000 1.1.1.1.2.11 ++++ pa_win_ds/dsound_wrapper.c 19 Mar 2006 22:27:43 -0000 +@@ -33,6 +33,8 @@ + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ ++#include ++ + #include + #include + #include +Index: pa_win_ds/pa_win_ds.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win_ds/Attic/pa_win_ds.c,v +retrieving revision 1.1.2.51 +diff -u -b -B -w -p -r1.1.2.51 pa_win_ds.c +--- pa_win_ds/pa_win_ds.c 26 Jan 2006 01:13:18 -0000 1.1.2.51 ++++ pa_win_ds/pa_win_ds.c 19 Mar 2006 22:27:49 -0000 +@@ -58,6 +58,8 @@ + O- fix "patest_stop.c" + */ + ++#include ++ + #include + #include /* strlen() */ + +Index: pa_win_wdmks/pa_win_wdmks.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win_wdmks/Attic/pa_win_wdmks.c,v +retrieving revision 1.1.2.4 +diff -u -b -B -w -p -r1.1.2.4 pa_win_wdmks.c +--- pa_win_wdmks/pa_win_wdmks.c 19 Nov 2005 10:14:01 -0000 1.1.2.4 ++++ pa_win_wdmks/pa_win_wdmks.c 19 Mar 2006 22:28:00 -0000 +@@ -42,6 +42,8 @@ + of a device for the duration of active stream using those devices + */ + ++#include ++ + #include + + /* Debugging/tracing support */ +Index: pa_win_wmme/pa_win_wmme.c +=================================================================== +RCS file: /home/cvs/portaudio/pa_win_wmme/pa_win_wmme.c,v +retrieving revision 1.6.2.88 +diff -u -b -B -w -p -r1.6.2.88 pa_win_wmme.c +--- pa_win_wmme/pa_win_wmme.c 16 Feb 2006 01:56:45 -0000 1.6.2.88 ++++ pa_win_wmme/pa_win_wmme.c 19 Mar 2006 22:28:14 -0000 +@@ -100,6 +100,8 @@ Non-critical stuff for the future: + Events (when necessary) inside the ReadStream() and WriteStream() functions. + */ + ++#include ++ + #include + #include + #include +--- /dev/null 2006-03-10 00:02:48.821312048 +0100 ++++ Makefile.am 2006-03-19 22:49:42.000000000 +0100 +@@ -0,0 +1,215 @@ ++# ++# PortAudio V19 Makefile.am ++# ++# Stéphane Fillod ++# ++ ++INCLUDES = -I$(top_srcdir)/pa_common ++ ++COMMON_SRC = \ ++ pa_common/pa_allocation.c \ ++ pa_common/pa_converters.c \ ++ pa_common/pa_cpuload.c \ ++ pa_common/pa_dither.c \ ++ pa_common/pa_front.c \ ++ pa_common/pa_process.c \ ++ pa_common/pa_skeleton.c \ ++ pa_common/pa_stream.c \ ++ pa_common/pa_trace.c ++ ++libportaudio_coreaudio_la_SOURCES = \ ++ pa_mac/pa_mac_hostapis.c \ ++ pa_mac_core/pa_mac_core.c ++ ++libportaudio_mac_asio_la_SOURCES = \ ++ pa_asio/iasiothiscallresolver.cpp ++libportaudio_mac_asio_la_LIBADD = @ASIO_OBJS@ ++ ++libportaudio_dsound_la_SOURCES = \ ++ pa_win_ds/pa_win_ds.c \ ++ pa_win_ds/dsound_wrapper.c \ ++ pa_win/pa_win_hostapis.c \ ++ pa_win/pa_win_util.c ++ ++libportaudio_win_asio_la_SOURCES = \ ++ pa_asio/pa_asio.cpp \ ++ pa_win/pa_win_hostapis.c \ ++ pa_win/pa_win_util.c \ ++ pa_asio/iasiothiscallresolver.cpp ++libportaudio_win_asio_la_LIBADD = @ASIO_OBJS@ ++ ++libportaudio_wdmks_la_SOURCES = \ ++ pa_win_wdmks/pa_win_wdmks.c \ ++ pa_win/pa_win_hostapis.c \ ++ pa_win/pa_win_util.c ++ ++libportaudio_wmme_la_SOURCES = \ ++ pa_win_wmme/pa_win_wmme.c \ ++ pa_win/pa_win_hostapis.c \ ++ pa_win/pa_win_util.c ++ ++libportaudio_sgi_la_SOURCES = \ ++ pa_sgi/pa_sgi.c ++ ++libportaudio_alsa_la_SOURCES = \ ++ pa_linux_alsa/pa_linux_alsa.c ++ ++libportaudio_jack_la_SOURCES = \ ++ pa_jack/pa_jack.c ++ ++libportaudio_oss_la_SOURCES = \ ++ pa_unix_oss/pa_unix_oss.c ++ ++libportaudio_unix_la_SOURCES = \ ++ pa_unix/pa_unix_hostapis.c \ ++ pa_unix/pa_unix_util.c ++ ++EXTRA_LTLIBRARIES = \ ++ libportaudio-coreaudio.la \ ++ libportaudio-mac-asio.la \ ++ libportaudio-dsound.la \ ++ libportaudio-win-asio.la \ ++ libportaudio-wdmks.la \ ++ libportaudio-wmme.la \ ++ libportaudio-sgi.la \ ++ libportaudio-alsa.la \ ++ libportaudio-jack.la \ ++ libportaudio-oss.la \ ++ libportaudio-unix.la ++ ++noinst_LTLIBRARIES = @PA_LIBADD@ ++lib_LTLIBRARIES = libportaudio.la ++ ++ ++libportaudio_la_SOURCES = \ ++ $(COMMON_SRC) ++ ++# -no-undefined is required by Win32 and MacOSX, should be harmless otherwise ++libportaudio_la_LDFLAGS = $(WINLDFLAGS) -no-undefined -version-info @PA_ABI@:@PA_REV@:@PA_AGE@ ++libportaudio_la_CFLAGS = $(AM_CFLAGS) ++libportaudio_la_LIBADD = @PA_LIBADD@ -lm ++libportaudio_la_DEPENDENCIES = @PA_LIBADD@ ++ ++ ++noinst_HEADERS = \ ++ pa_asio/iasiothiscallresolver.h \ ++ pa_asio/pa_asio.h \ ++ pa_beos/PlaybackNode.h \ ++ pablio/pablio.h \ ++ pablio/ringbuffer.h \ ++ pa_common/pa_allocation.h \ ++ pa_common/pa_converters.h \ ++ pa_common/pa_cpuload.h \ ++ pa_common/pa_dither.h \ ++ pa_common/pa_endianness.h \ ++ pa_common/pa_hostapi.h \ ++ pa_common/pa_process.h \ ++ pa_common/pa_stream.h \ ++ pa_common/pa_trace.h \ ++ pa_common/pa_types.h \ ++ pa_common/pa_util.h \ ++ pa_dll_switch/PaDllEntry.h \ ++ pa_dll_switch/portaudio.h \ ++ pa_linux_alsa/pa_linux_alsa.h \ ++ pa_mac_core/pa_mac_core.h \ ++ pa_unix/pa_unix_util.h \ ++ pa_win_ds/dsound_wrapper.h \ ++ pa_win/pa_x86_plain_converters.h \ ++ pa_win_wmme/pa_win_wmme.h ++ ++include_HEADERS = \ ++ pa_common/portaudio.h ++ ++ ++TESTS = \ ++ pa_tests/paqa_errs \ ++ pa_tests/patest1 \ ++ pa_tests/patest_buffer \ ++ pa_tests/patest_callbackstop \ ++ pa_tests/patest_clip \ ++ pa_tests/patest_dither \ ++ pa_tests/patest_hang \ ++ pa_tests/patest_in_overflow \ ++ pa_tests/patest_latency \ ++ pa_tests/patest_leftright \ ++ pa_tests/patest_longsine \ ++ pa_tests/patest_many \ ++ pa_tests/patest_maxsines \ ++ pa_tests/patest_multi_sine \ ++ pa_tests/patest_out_underflow \ ++ pa_tests/patest_pink \ ++ pa_tests/patest_prime \ ++ pa_tests/patest_read_record \ ++ pa_tests/patest_record \ ++ pa_tests/patest_ringmix \ ++ pa_tests/patest_saw \ ++ pa_tests/patest_sine8 \ ++ pa_tests/patest_sine \ ++ pa_tests/patest_sine_formats \ ++ pa_tests/patest_sine_time \ ++ pa_tests/patest_start_stop \ ++ pa_tests/patest_stop \ ++ pa_tests/patest_sync \ ++ pa_tests/patest_toomanysines \ ++ pa_tests/patest_underflow \ ++ pa_tests/patest_wire \ ++ pa_tests/patest_write_sine \ ++ pa_tests/pa_devs \ ++ pa_tests/pa_fuzz \ ++ pa_tests/pa_minlat \ ++ pa_tests/paqa_devs ++ ++check_PROGRAMS = $(TESTS) ++ ++LDADD = libportaudio.la ++ ++# Most of these don't compile yet. Put them in TESTS, above, if ++# you want to try to compile them... ++ALL_TESTS = \ ++ pa_tests/debug_convert \ ++ pa_tests/debug_dither_calc \ ++ pa_tests/debug_dual \ ++ pa_tests/debug_multi_in \ ++ pa_tests/debug_multi_out \ ++ pa_tests/debug_record \ ++ pa_tests/debug_record_reuse \ ++ pa_tests/debug_sine_amp \ ++ pa_tests/debug_sine \ ++ pa_tests/debug_sine_formats \ ++ pa_tests/debug_srate \ ++ pa_tests/debug_test1 \ ++ $(TESTS) ++ ++pkgconfigdir = $(libdir)/pkgconfig ++pkgconfig_DATA = portaudio-2.0.pc ++ ++ ++SUBDIRS= ++DIST_SUBDIRS= ++ ++ACLOCAL_AMFLAGS = -I config ++ ++doc: config.doxy ++ doxygen config.doxy ++ ++# pa_asio pa_beos pablio pa_common pa_dll_switch pa_jack pa_linux_alsa pa_mac pa_mac_core pa_mac_sm pa_sgi pa_tests pa_unix pa_unix_oss pa_win pa_win_ds pa_win_wdmks pa_win_wmme ++ ++PABLIO = \ ++ pablio/pablio.def \ ++ pablio/README.txt \ ++ pablio/ringbuffer.h \ ++ pablio/test_rw_echo.c \ ++ pablio/test_w_saw.c \ ++ pablio/pablio.c \ ++ pablio/pablio.h \ ++ pablio/ringbuffer.c \ ++ pablio/test_rw.c \ ++ pablio/test_w_saw8.c ++ ++EXTRA_DIST = \ ++ $(PABLIO) \ ++ config.doxy \ ++ LICENSE.txt \ ++ README.txt \ ++ portaudio-2.0.pc.in \ ++ V19-devel-readme.txt +--- /dev/null 2006-03-10 00:02:48.821312048 +0100 ++++ configure.ac 2006-03-19 22:49:13.000000000 +0100 +@@ -0,0 +1,278 @@ ++dnl ++dnl portaudio V19 configure.ac script ++dnl ++dnl Stephane Fillod, Dominic Mazzoni, Arve Knudsen ++dnl ++ ++dnl Require autoconf >= 2.57 ++AC_PREREQ(2.57) ++ ++dnl Init autoconf and make sure configure is being called ++dnl from the right directory ++AC_INIT([portaudio], [2.0cvs], [portaudio@techweb.rfa.org]) ++AC_CONFIG_SRCDIR([pa_common/portaudio.h]) ++AC_CONFIG_HEADERS(config.h) ++AC_CANONICAL_TARGET([]) ++ ++dnl Automake Initialisation. ++AM_INIT_AUTOMAKE(AC_PACKAGE_TARNAME, AC_PACKAGE_VERSION, -) ++AM_MAINTAINER_MODE ++ ++dnl Portaudio library interface version, see libtool(info), esp. ++dnl node 6.3 "Updating version info" ++PA_ABI=19 ++PA_REV=0 ++PA_AGE=0 ++AC_SUBST(PA_ABI) ++AC_SUBST(PA_REV) ++AC_SUBST(PA_AGE) ++ ++ ++dnl Checks for programs. ++ ++AC_PROG_CC ++AC_PROG_CXX ++AC_PROG_RANLIB ++AC_PROG_INSTALL ++AC_PROG_MAKE_SET ++ ++AC_AIX ++AC_ISC_POSIX ++AC_MINIX ++AM_PROG_CC_STDC ++AC_PROG_GCC_TRADITIONAL ++AC_C_CONST ++AC_C_INLINE ++ ++dnl Check for Mingw support ++#GR_PWIN32 ++ ++dnl libtool Initialisation ++AC_LIBTOOL_WIN32_DLL ++AC_PROG_LIBTOOL ++ ++ACX_PTHREAD ++ ++dnl This must be one of the first tests we do or it will fail... ++AC_C_BIGENDIAN ++ ++dnl checks for various host APIs and arguments to configure that ++dnl turn them on or off ++ ++AC_CHECK_LIB(asound, snd_pcm_open, [have_alsa=yes], [have_alsa=no]) ++ ++ ++PKG_CHECK_MODULES(JACK, jack, [have_jack=yes], [have_jack=no]) ++PKG_CHECK_LIB(jack_client_new, [$JACK_LIBS], [$JACK_CFLAGS], [have_jack=yes], [have_jack=no]) ++ ++AC_CHECK_HEADERS([sys/soundcard.h linux/soundcard.h soundcard.h machine/soundcard.h]) ++AC_CHECK_HEADERS(sys/ioctl.h, [have_oss=yes], [have_oss=no]) ++ ++dnl sizeof checks: we will need a 16-bit and a 32-bit type ++ ++AC_CHECK_SIZEOF(short) ++AC_CHECK_SIZEOF(int) ++AC_CHECK_SIZEOF(long) ++ ++dnl Specify options ++ ++AC_ARG_WITH(alsa, ++ [ --with-alsa (default=yes)], ++ [with_alsa=$withval], [with_alsa=$have_alsa]) ++ ++AC_ARG_WITH(jack, ++ [ --with-jack (default=yes)], ++ [with_jack=$withval], [with_jack=$have_jack]) ++ ++AC_ARG_WITH(oss, ++ [ --with-oss (default=yes)], ++ [with_oss=$withval], [with_oss=$have_oss]) ++ ++AC_ARG_WITH(winapi, ++ [ --with-winapi ((wmme/directx/asio) default=wmme)], ++ [with_winapi=$withval], [with_winapi="wmme"]) ++ ++dnl Mac API added for ASIO, can have other api's listed ++AC_ARG_WITH(macapi, ++ [ --with-macapi ((asio/core/sm) default=core)], ++ [with_macapi=$withval], [with_macapi="core"]) ++ ++AC_ARG_WITH(asiodir, ++ [ --with-asiodir (default=/usr/local/asiosdk2)], ++ [with_asiodir=$withval], [with_asiodir="/usr/local/asiosdk2"]) ++ ++AC_ARG_WITH(dxdir, ++ [ --with-dxdir (default=/usr/local/dx7sdk)], ++ [with_dxdir=$withval], [with_dxdir="/usr/local/dx7sdk"]) ++ ++AC_ARG_ENABLE(debug-output, ++ [ --enable-debug-output], ++ [if test x$enableval != xno ; then ++ AC_DEFINE(PA_ENABLE_DEBUG_OUTPUT,,[Enable debugging messages]) ++ fi ++ ]) ++ ++dnl BSD configuration ++AC_HAVE_LIBRARY(ossaudio) ++ ++dnl Mac OS X configuration ++ ++AC_CHECK_LIB(CoreAudio, OpenAComponent, ++ [ ++ have_coreaudio=yes ++ PA_LIBADD="$PA_LIBADD libportaudio-coreaudio.la" ++ AC_DEFINE([PA_USE_COREAUDIO], [], [Define to use Mac OS X CoreAudio]) ++ #LIBS="-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon" ++ LIBS="-lCoreAudio -lAudioToolbox -lAudioUnit -lCarbon" ++ ], have_coreaudio=no) ++ ++ASIO_CFLAGS="" ++ASIO_OBJS="" ++ ++if [[ $with_asiodir ]] ; then ++ ASIODIR="$with_asiodir" ++fi ++ ++if [[ $with_macapi = "asio" ]] ; then ++ echo "ASIODIR: $ASIODIR" ++ ASIO_CFLAGS="-Ipa_asio -I$ASIDIR/host/mac -I$ASIODIR/common" ++ ASIO_OBJS=$ASIODIR/common/asio.o $ASIODIR/host/asiodrivers.o $ASIODIR/host/mac/asioshlib.o ++ PA_LIBADD="$PA_LIBADD libportaudio-mac-asio.la" ++fi ++ ++if [[ $with_winapi = "asio" ]] ; then ++ echo "ASIODIR: $ASIODIR" ++ ASIO_CFLAGS="-ffast-math -fomit-frame-pointer -Ipa_asio -I$ASIDIR/host/pc -I$ASIODIR/common -I$ASIODIR/host -DPA_NO_WMME -DPA_NO_DS -DPA_NO_WDMKS -DWINDOWS" ++ ASIO_OBJS=$ASIODIR/common/asio.o $ASIODIR/host/asiodrivers.o $ASIODIR/host/pc/asiolist.o ++ LIBS="$LIBS -lwinmm -lole32 -luuid" ++ PA_LIBADD="$PA_LIBADD libportaudio-win-asio.la" ++fi ++ ++ ++dnl MingW/Win configuration ++ ++AC_TRY_LINK_LIB(dsound, [DSW_InitOutputBuffer(0,0,0,0);], [ ++ #include ++ #include ++ ], [-I$DXDIR/include], ++ [ ++ have_directx=yes ++ DXDIR="$with_dxdir" ++ echo "DXDIR: $DXDIR" ++ # LDFLAGS -L./dx7sdk/lib ? ++ LIBS="-lwinmm -ldsound -lole32" ++ CFLAGS="$CFLAGS -I$DXDIR/include -DPA_NO_WMME -DPA_NO_ASIO -DPA_NO_WDMKS" ++ PA_LIBADD="$PA_LIBADD libportaudio-dsound.la" ++ ], have_directx=no) ++ ++AC_TRY_LINK_LIB(kernel32, [DeviceIoControl(0,0,0,0,0,0,0,0);],[ ++ #include ++ #include ++ #include ++ ], [-I$DXDIR/include], ++ [ ++ have_wdmks=yes ++ DXDIR="$with_dxdir" ++ echo "DXDIR: $DXDIR" ++ # LDFLAGS -L./dx7sdk/lib ? ++ LIBS="-lwinmm -luuid -lsetupapi -lole32" ++ CFLAGS="$CFLAGS -I$DXDIR/include -DPA_NO_WMME -DPA_NO_DS -DPA_NO_ASIO" ++ PA_LIBADD="$PA_LIBADD libportaudio-wdmks.la" ++ ], have_wdmks=no) ++ ++# WMME default ? ++AC_TRY_LINK_LIB(winmm, [waveOutOpen(0,0,0,0,0,0);],[ ++ #include ++ #include ++ ], [], ++ [ ++ have_wmme=yes ++ LIBS="-lwinmm -lole32 -luuid" ++ CFLAGS="$CFLAGS -DPA_NO_DS -DPA_NO_ASIO -DPA_NO_WDMKS" ++ PA_LIBADD="$PA_LIBADD libportaudio-wmme.la" ++ ], have_wmme=no) ++ ++ ++dnl Unix configuration ++ ++dnl SGI IRIX audio library (AL) configuration (Pieter, oct 2-13, 2003). ++dnl The 'dmedia' library is needed to read the Unadjusted System Time (UST). ++dnl ++ ++AC_CHECK_LIB(audio, alOpenPort, [have_AL=1], [have_AL=0]) ++AC_CHECK_LIB(dmedia, dmGetUST, [have_dmedia=1], [have_dmedia=0]) ++ ++ ++if [[ $have_AL = "yes" ] && [ $have_dmedia = "yes" ]] ; then ++ dnl See the '#ifdef PA_USE_SGI' in file pa_unix/pa_unix_hostapis.c ++ dnl which selects the appropriate PaXXX_Initialize() function. ++ dnl ++ ++ LIBS="-ldmedia -laudio" ++ AC_DEFINE([PA_USE_SGI], [], [Define to use special SGI system support]) ++ PA_LIBADD="$PA_LIBADD libportaudio-sgi.la" ++ ++ # TODO: ++ #AC_MSG_ERROR([IRIX audio library not found!]) ++ #AC_MSG_ERROR([IRIX digital media library not found!]) ++fi ++ ++ ++if [[ $have_alsa = "yes" ] && [ $with_alsa != "no" ]] ; then ++ LIBS="$LIBS -lasound" ++ AC_DEFINE([PA_USE_ALSA], [], [Define to use ALSA]) ++ PA_LIBADD="$PA_LIBADD libportaudio-alsa.la" ++fi ++ ++if [[ $have_jack = "yes" ] && [ $with_jack != "no" ]] ; then ++ LIBS="$LIBS $JACK_LIBS" ++ CFLAGS="$CFLAGS $JACK_CFLAGS" ++ AC_DEFINE([PA_USE_JACK], [], [Define to use JACK]) ++ PA_LIBADD="$PA_LIBADD libportaudio-jack.la" ++fi ++ ++if [[ $with_oss != "no" ]] ; then ++ AC_DEFINE([PA_USE_OSS], [], [Define to use Open Sound System]) ++ PA_LIBADD="$PA_LIBADD libportaudio-oss.la" ++fi ++ ++dnl SGI books say -lpthread should be the last of the libs mentioned. ++if [[ $acx_pthread_ok = "yes" ]] ; then ++ LIBS="$LIBS $PTHREAD_LIBS" ++ PA_LIBADD="$PA_LIBADD libportaudio-unix.la" ++else ++ if [[ $with_winapi != "wmme" -a $with_winapi != "directx" -a $with_winapi != "asio" ]] ; then ++ AC_MSG_ERROR([libpthread not found!]) ++ fi ++fi ++ ++ ++if [[ $with_macapi = "asio" ] || [ $with_winapi = "asio" ]] ; then ++ echo "ASIODIR: $ASIODIR" ++ ++ CFLAGS="$CFLAGS $ASIO_CFLAGS" ++fi ++ ++if [[ $ac_cv_c_bigendian = "yes" ]] ; then ++ CFLAGS="$CFLAGS -DPA_BIG_ENDIAN" ++else ++ CFLAGS="$CFLAGS -DPA_LITTLE_ENDIAN" ++fi ++ ++ ++CXXFLAGS="$CXXFLAGS" ++ ++#CFLAGS="-g -O2 -Wall -pedantic -pipe" ++ ++CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ ++ ++dnl extra variables ++AC_SUBST(PA_LIBADD) ++AC_SUBST(ASIO_OBJS) ++AC_SUBST(PTHREAD_CFLAGS) ++AC_SUBST(CXXFLAGS) ++AC_SUBST(NASM) ++AC_SUBST(NASMOPT) ++ ++AC_OUTPUT([Makefile portaudio-2.0.pc]) +--- /dev/null 2006-03-10 00:02:48.821312048 +0100 ++++ config/acx_pthread.m4 2006-03-17 15:41:05.000000000 +0100 +@@ -0,0 +1,190 @@ ++dnl Available from the GNU Autoconf Macro Archive at: ++dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html ++dnl ++AC_DEFUN([ACX_PTHREAD], [ ++AC_REQUIRE([AC_CANONICAL_HOST]) ++AC_LANG_SAVE ++AC_LANG_C ++acx_pthread_ok=no ++ ++# We used to check for pthread.h first, but this fails if pthread.h ++# requires special compiler flags (e.g. on True64 or Sequent). ++# It gets checked for in the link test anyway. ++ ++# First of all, check if the user has set any of the PTHREAD_LIBS, ++# etcetera environment variables, and if threads linking works using ++# them: ++if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ save_LIBS="$LIBS" ++ LIBS="$PTHREAD_LIBS $LIBS" ++ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) ++ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) ++ AC_MSG_RESULT($acx_pthread_ok) ++ if test x"$acx_pthread_ok" = xno; then ++ PTHREAD_LIBS="" ++ PTHREAD_CFLAGS="" ++ fi ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++fi ++ ++# We must check for the threads library under a number of different ++# names; the ordering is very important because some systems ++# (e.g. DEC) have both -lpthread and -lpthreads, where one of the ++# libraries is broken (non-POSIX). ++ ++# Create a list of thread flags to try. Items starting with a "-" are ++# C compiler flags, and other items are library names, except for "none" ++# which indicates that we try without any flags at all. ++ ++acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" ++ ++# The ordering *is* (sometimes) important. Some notes on the ++# individual items follow: ++ ++# pthreads: AIX (must check this before -lpthread) ++# none: in case threads are in libc; should be tried before -Kthread and ++# other compiler flags to prevent continual compiler warnings ++# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) ++# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) ++# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ++# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) ++# -pthreads: Solaris/gcc ++# -mthreads: Mingw32/gcc, Lynx/gcc ++# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it ++# doesn't hurt to check since this sometimes defines pthreads too; ++# also defines -D_REENTRANT) ++# pthread: Linux, etcetera ++# --thread-safe: KAI C++ ++ ++case "${host_cpu}-${host_os}" in ++ *solaris*) ++ ++ # On Solaris (at least, for some versions), libc contains stubbed ++ # (non-functional) versions of the pthreads routines, so link-based ++ # tests will erroneously succeed. (We need to link with -pthread or ++ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather ++ # a function called by this macro, so we could check for that, but ++ # who knows whether they'll stub that too in a future libc.) So, ++ # we'll just look for -pthreads and -lpthread first: ++ ++ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ++ ;; ++esac ++ ++if test x"$acx_pthread_ok" = xno; then ++for flag in $acx_pthread_flags; do ++ ++ case $flag in ++ none) ++ AC_MSG_CHECKING([whether pthreads work without any flags]) ++ ;; ++ ++ -*) ++ AC_MSG_CHECKING([whether pthreads work with $flag]) ++ PTHREAD_CFLAGS="$flag" ++ ;; ++ ++ *) ++ AC_MSG_CHECKING([for the pthreads library -l$flag]) ++ PTHREAD_LIBS="-l$flag" ++ ;; ++ esac ++ ++ save_LIBS="$LIBS" ++ save_CFLAGS="$CFLAGS" ++ LIBS="$PTHREAD_LIBS $LIBS" ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ ++ # Check for various functions. We must include pthread.h, ++ # since some functions may be macros. (On the Sequent, we ++ # need a special flag -Kthread to make this header compile.) ++ # We check for pthread_join because it is in -lpthread on IRIX ++ # while pthread_create is in libc. We check for pthread_attr_init ++ # due to DEC craziness with -lpthreads. We check for ++ # pthread_cleanup_push because it is one of the few pthread ++ # functions on Solaris that doesn't have a non-functional libc stub. ++ # We try pthread_create on general principles. ++ AC_TRY_LINK([#include ], ++ [pthread_t th; pthread_join(th, 0); ++ pthread_attr_init(0); pthread_cleanup_push(0, 0); ++ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], ++ [acx_pthread_ok=yes]) ++ ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++ ++ AC_MSG_RESULT($acx_pthread_ok) ++ if test "x$acx_pthread_ok" = xyes; then ++ break; ++ fi ++ ++ PTHREAD_LIBS="" ++ PTHREAD_CFLAGS="" ++done ++fi ++ ++# Various other checks: ++if test "x$acx_pthread_ok" = xyes; then ++ save_LIBS="$LIBS" ++ LIBS="$PTHREAD_LIBS $LIBS" ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ ++ # Detect AIX lossage: threads are created detached by default ++ # and the JOINABLE attribute has a nonstandard name (UNDETACHED). ++ AC_MSG_CHECKING([for joinable pthread attribute]) ++ AC_TRY_LINK([#include ], ++ [int attr=PTHREAD_CREATE_JOINABLE;], ++ ok=PTHREAD_CREATE_JOINABLE, ok=unknown) ++ if test x"$ok" = xunknown; then ++ AC_TRY_LINK([#include ], ++ [int attr=PTHREAD_CREATE_UNDETACHED;], ++ ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) ++ fi ++ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then ++ AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, ++ [Define to the necessary symbol if this constant ++ uses a non-standard name on your system.]) ++ fi ++ AC_MSG_RESULT(${ok}) ++ if test x"$ok" = xunknown; then ++ AC_MSG_WARN([we do not know how to create joinable pthreads]) ++ fi ++ ++ AC_MSG_CHECKING([if more special flags are required for pthreads]) ++ flag=no ++ case "${host_cpu}-${host_os}" in ++ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; ++ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; ++ esac ++ AC_MSG_RESULT(${flag}) ++ if test "x$flag" != xno; then ++ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" ++ fi ++ ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++ ++ # More AIX lossage: must compile with cc_r ++ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) ++else ++ PTHREAD_CC="$CC" ++fi ++ ++AC_SUBST(PTHREAD_LIBS) ++AC_SUBST(PTHREAD_CFLAGS) ++AC_SUBST(PTHREAD_CC) ++ ++# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: ++if test x"$acx_pthread_ok" = xyes; then ++ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) ++ : ++else ++ acx_pthread_ok=no ++ $2 ++fi ++AC_LANG_RESTORE ++])dnl ACX_PTHREAD +--- /dev/null 2006-03-10 00:02:48.821312048 +0100 ++++ config/pkg_check.m4 2006-03-17 22:12:37.000000000 +0100 +@@ -0,0 +1,49 @@ ++ ++AC_DEFUN([PKG_CHECK_LIB], [ ++AC_REQUIRE([AC_CANONICAL_HOST]) ++AC_LANG_SAVE ++AC_LANG_C ++ ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS $3" ++ save_LIBS="$LIBS" ++ LIBS="$2 $LIBS" ++ AC_MSG_CHECKING([for $1 in LIBS=$2 with CFLAGS=$3]) ++ AC_TRY_LINK_FUNC([$1], pkg_check_try_link=yes, pkg_check_try_link=no) ++ AC_MSG_RESULT($pkg_check_try_link) ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++ ++# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: ++if test x"$pkg_check_try_link" = xyes; then ++ $4 ++else ++ $5 ++fi ++AC_LANG_RESTORE ++])dnl PKG_CHECK_LIB ++ ++ ++AC_DEFUN([AC_TRY_LINK_LIB], [ ++AC_REQUIRE([AC_CANONICAL_HOST]) ++AC_LANG_SAVE ++AC_LANG_C ++ ++ save_CFLAGS="$CFLAGS" ++ CFLAGS="$CFLAGS $4" ++ save_LIBS="$LIBS" ++ LIBS="-l$1 $LIBS" ++ AC_MSG_CHECKING([for $2 in $1]) ++ AC_TRY_LINK([$3], [$2], ac_try_link_lib=yes, ac_try_link_lib=no) ++ AC_MSG_RESULT($ac_try_link_lib) ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++ ++# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: ++if test x"$ac_try_link_lib" = xyes; then ++ $5 ++else ++ $6 ++fi ++AC_LANG_RESTORE ++])dnl AC_TRY_LINK_LIB +--- /dev/null 2006-03-10 00:02:48.821312048 +0100 ++++ bootstrap 2006-03-19 23:33:58.000000000 +0100 +@@ -0,0 +1,9 @@ ++#!/bin/sh ++ ++rm -rf config.cache autom4te*.cache ++ ++aclocal-1.9 -I config ++autoconf2.50 ++autoheader2.50 ++libtoolize --automake ++automake-1.9 --add-missing --foreign diff --git a/gr-audio-portaudio/gr-audio-portaudio.conf b/gr-audio-portaudio/gr-audio-portaudio.conf new file mode 100644 index 00000000..0dd14744 --- /dev/null +++ b/gr-audio-portaudio/gr-audio-portaudio.conf @@ -0,0 +1,10 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[audio_portaudio] + +#default_input_device = hw:0,0 +#default_output_device = hw:0,0 + +verbose = false diff --git a/gr-audio-portaudio/src/Makefile.am b/gr-audio-portaudio/src/Makefile.am new file mode 100644 index 00000000..1b6d518e --- /dev/null +++ b/gr-audio-portaudio/src/Makefile.am @@ -0,0 +1,92 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +LIBS += $(GNURADIO_CORE_LIBS) + +# Install this stuff so that it ends up as the gnuradio.audio_portaudio module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in + +TESTS = run_tests + +LOCAL_IFILES = \ + audio_portaudio.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_portaudio.cc \ + audio_portaudio.py + +ourpython_PYTHON = \ + audio_portaudio.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) -I/usr/include + +ourlib_LTLIBRARIES = _audio_portaudio.la + + +_audio_portaudio_la_SOURCES = \ + audio_portaudio.cc \ + audio_portaudio_sink.cc \ + audio_portaudio_source.cc \ + gri_portaudio.cc + +grinclude_HEADERS = \ + audio_portaudio_sink.h \ + audio_portaudio_source.h + +noinst_HEADERS = \ + gri_portaudio.h + + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_portaudio_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +_audio_portaudio_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +audio_portaudio.cc audio_portaudio.py: $(ALL_IFILES) audio_portaudio_sink.h audio_portaudio_source.h + $(SWIG) $(SWIGPYTHONARGS) -module audio_portaudio -o audio_portaudio.cc $< + + +noinst_PYTHON = \ + qa_portaudio.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc diff --git a/gr-audio-portaudio/src/audio_portaudio.i b/gr-audio-portaudio/src/audio_portaudio.i new file mode 100644 index 00000000..35fc5c63 --- /dev/null +++ b/gr-audio-portaudio/src/audio_portaudio.i @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_portaudio_sink.h" +#include "audio_portaudio_source.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_portaudio,source) + +audio_portaudio_source_sptr +audio_portaudio_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_portaudio_source : public gr_sync_block { + + protected: + audio_portaudio_source (int sampling_rate, + const std::string device_name, + bool ok_to_block + ) throw (std::runtime_error); + + public: + ~audio_portaudio_source (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_portaudio,sink) + +audio_portaudio_sink_sptr +audio_portaudio_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true + ) throw (std::runtime_error); + +class audio_portaudio_sink : public gr_sync_block { + + protected: + audio_portaudio_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block + ) throw (std::runtime_error); + + public: + ~audio_portaudio_sink (); +}; diff --git a/gr-audio-portaudio/src/audio_portaudio_sink.cc b/gr-audio-portaudio/src/audio_portaudio_sink.cc new file mode 100644 index 00000000..06bcc957 --- /dev/null +++ b/gr-audio-portaudio/src/audio_portaudio_sink.cc @@ -0,0 +1,340 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in he hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOGGING 0 // define to 0 or 1 + +#define SAMPLE_FORMAT paFloat32 +typedef float sample_t; + +// Number of portaudio buffers in the ringbuffer +static const unsigned int N_BUFFERS = 4; + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_portaudio", "default_output_device", ""); +} + +void +audio_portaudio_sink::create_ringbuffer(void) +{ + int bufsize_samples = d_portaudio_buffer_size_frames * d_output_parameters.channelCount; + + if (d_verbose) + fprintf(stderr,"ring buffer size = %d frames\n", + N_BUFFERS*bufsize_samples/d_output_parameters.channelCount); + + // FYI, the buffer indicies are in units of samples. + d_writer = gr_make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t)); + d_reader = gr_buffer_add_reader(d_writer, 0); +} + +/* + * This routine will be called by the PortAudio engine when audio is needed. + * It may called at interrupt level on some machines so don't do anything + * that could mess up the system like calling malloc() or free(). + * + * Our job is to write framesPerBuffer frames into outputBuffer. + */ +int +portaudio_sink_callback (const void *inputBuffer, + void *outputBuffer, + unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *arg) +{ + audio_portaudio_sink *self = (audio_portaudio_sink *)arg; + int nreqd_samples = + framesPerBuffer * self->d_output_parameters.channelCount; + + int navail_samples = self->d_reader->items_available(); + + if (nreqd_samples <= navail_samples){ // We've got enough data... + if (LOGGING) + self->d_log->printf("PAsink cb: f/b = %4ld\n", framesPerBuffer); + // copy from ringbuffer into output buffer + memcpy(outputBuffer, + self->d_reader->read_pointer(), + nreqd_samples * sizeof(sample_t)); + self->d_reader->update_read_pointer(nreqd_samples); + + // Tell the sink thread there is new room in the ringbuffer. + self->d_ringbuffer_ready.post(); + return paContinue; + } + + else { // underrun + if (LOGGING) + self->d_log->printf("PAsink cb: f/b = %4ld UNDERRUN\n", framesPerBuffer); + + self->d_nunderuns++; + ::write(2, "aU", 2); // FIXME change to non-blocking call + + // FIXME we should transfer what we've got and pad the rest + memset(outputBuffer, 0, nreqd_samples * sizeof(sample_t)); + + self->d_ringbuffer_ready.post(); // Tell the sink to get going! + return paContinue; + } +} + + +// ---------------------------------------------------------------- + +audio_portaudio_sink_sptr +audio_portaudio_make_sink (int sampling_rate, const std::string dev, bool ok_to_block) +{ + return audio_portaudio_sink_sptr (new audio_portaudio_sink (sampling_rate, + dev, ok_to_block)); +} + +audio_portaudio_sink::audio_portaudio_sink(int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_portaudio_sink", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + d_sampling_rate(sampling_rate), + d_device_name(device_name.empty() ? default_device_name() : device_name), + d_ok_to_block(ok_to_block), + d_verbose(gr_prefs::singleton()->get_bool("audio_portaudio", "verbose", false)), + d_portaudio_buffer_size_frames(0), + d_stream(0), + d_ringbuffer_ready(1, 1), // binary semaphore + d_nunderuns(0) +{ + memset(&d_output_parameters, 0, sizeof(d_output_parameters)); + if (LOGGING) + d_log = gri_logger::singleton(); + + PaError err; + int i, numDevices; + PaDeviceIndex device = 0; + const PaDeviceInfo *deviceInfo = NULL; + + err = Pa_Initialize(); + if (err != paNoError) { + bail ("Initialize failed", err); + } + + if (d_verbose) + gri_print_devices(); + + numDevices = Pa_GetDeviceCount(); + if (numDevices < 0) + bail("Pa Device count failed", 0); + if (numDevices == 0) + bail("no devices available", 0); + + if (d_device_name.empty()) + { + // FIXME Get smarter about picking something + fprintf(stderr,"\nUsing Default Device\n"); + device = Pa_GetDefaultOutputDevice(); + deviceInfo = Pa_GetDeviceInfo(device); + fprintf(stderr,"%s is the chosen device using %s as the host\n", + deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name); + } + else + { + bool found = false; + fprintf(stderr,"\nTest Devices\n"); + for (i=0;iname); + if (strstr(deviceInfo->name, d_device_name.c_str())){ + fprintf(stderr," Chosen!\n"); + device = gri_pa_find_device_by_name(deviceInfo->name); + fprintf(stderr,"%s using %s as the host\n",d_device_name.c_str(), + Pa_GetHostApiInfo(deviceInfo->hostApi)->name), fflush(stderr); + found = true; + deviceInfo = Pa_GetDeviceInfo(device); + i = numDevices; // force loop exit + } + fprintf(stderr,"\n"),fflush(stderr); + } + + if (!found){ + bail("Failed to find specified device name", 0); + exit(1); + } + } + + + d_output_parameters.device = device; + d_output_parameters.channelCount = deviceInfo->maxOutputChannels; + d_output_parameters.sampleFormat = SAMPLE_FORMAT; + d_output_parameters.suggestedLatency = deviceInfo->defaultLowOutputLatency; + d_output_parameters.hostApiSpecificStreamInfo = NULL; + + // We fill in the real channelCount in check_topology when we know + // how many inputs are connected to us. + + // Now that we know the maximum number of channels (allegedly) + // supported by the h/w, we can compute a reasonable input + // signature. The portaudio specs say that they'll accept any + // number of channels from 1 to max. + set_input_signature(gr_make_io_signature(1, deviceInfo->maxOutputChannels, + sizeof (sample_t))); +} + + +bool +audio_portaudio_sink::check_topology (int ninputs, int noutputs) +{ + PaError err; + + if (Pa_IsStreamActive(d_stream)) + { + Pa_CloseStream(d_stream); + d_stream = 0; + d_reader.reset(); // boost::shared_ptr for d_reader = 0 + d_writer.reset(); // boost::shared_ptr for d_write = 0 + } + + d_output_parameters.channelCount = ninputs; // # of channels we're really using + +#if 1 + d_portaudio_buffer_size_frames = (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 1024 frame buffers at 48000 + fprintf(stderr, "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency to 21.3333333.. ms + 0.0213333333, (double)d_sampling_rate); +#endif + err = Pa_OpenStream(&d_stream, + NULL, // No input + &d_output_parameters, + d_sampling_rate, + d_portaudio_buffer_size_frames, + paClipOff, + &portaudio_sink_callback, + (void*)this); + + if (err != paNoError) { + output_error_msg ("OpenStream failed", err); + return false; + } + +#if 0 + const PaStreamInfo *psi = Pa_GetStreamInfo(d_stream); + + d_portaudio_buffer_size_frames = (int)(d_output_parameters.suggestedLatency * psi->sampleRate); + fprintf(stderr, "Latency = %7.4f, psi->sampleRate = %g\n", + d_output_parameters.suggestedLatency, psi->sampleRate); +#endif + + fprintf(stderr, "d_portaudio_buffer_size_frames = %d\n", d_portaudio_buffer_size_frames); + + assert(d_portaudio_buffer_size_frames != 0); + + create_ringbuffer(); + + err = Pa_StartStream(d_stream); + if (err != paNoError) { + output_error_msg ("StartStream failed", err); + return false; + } + + return true; +} + +audio_portaudio_sink::~audio_portaudio_sink () +{ + Pa_StopStream(d_stream); // wait for output to drain + Pa_CloseStream(d_stream); + Pa_Terminate(); +} + +/* + * This version consumes everything sent to it, blocking if required. + * I think this will allow us better control of the total buffering/latency + * in the audio path. + */ +int +audio_portaudio_sink::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]; + const unsigned nchan = d_output_parameters.channelCount; // # of channels == samples/frame + + int k; + for (k = 0; k < noutput_items; ){ + + int nframes = d_writer->space_available() / nchan; // How much space in ringbuffer + if (nframes == 0){ // no room... + if (d_ok_to_block){ + d_ringbuffer_ready.wait(); // block here, then try again + continue; + } + else { + // There's no room and we're not allowed to block. + // (A USRP is most likely controlling the pacing through the pipeline.) + // We drop the samples on the ground, and say we processed them all ;) + // + // FIXME, there's probably room for a bit more finesse here. + return noutput_items; + } + } + + // We can write the smaller of the request and the room we've got + int nf = std::min(noutput_items - k, nframes); + + float *p = (float *) d_writer->write_pointer(); + for (int i = 0; i < nf; i++){ + for (unsigned int c = 0; c < nchan; c++){ + *p++ = in[c][k + i]; + } + } + d_writer->update_write_pointer(nf * nchan); + k += nf; + } + + return k; // tell how many we actually did +} + +void +audio_portaudio_sink::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "audio_portaudio_sink[%s]: %s: %s\n", + d_device_name.c_str (), msg, Pa_GetErrorText(err)); +} + +void +audio_portaudio_sink::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("audio_portaudio_sink"); +} diff --git a/gr-audio-portaudio/src/audio_portaudio_sink.h b/gr-audio-portaudio/src/audio_portaudio_sink.h new file mode 100644 index 00000000..2069f7c8 --- /dev/null +++ b/gr-audio-portaudio/src/audio_portaudio_sink.h @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_AUDIO_PORTAUDIO_SINK_H +#define INCLUDED_AUDIO_PORTAUDIO_SINK_H + +#include +#include +#include +#include +#include +#include +#include + +class audio_portaudio_sink; +typedef boost::shared_ptr audio_portaudio_sink_sptr; + +/*! + * \PORTAUDIO audio sink. + * \param sampling_rate sampling rate in Hz + * \param dev PORTAUDIO device name, e.g., "pa:" + * \param ok_to_block true if it's ok for us to block + */ +audio_portaudio_sink_sptr +audio_portaudio_make_sink (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +PaStreamCallback portaudio_sink_callback; + + +/*! + * \ Audio sink using PORTAUDIO + * + * Input samples must be in the range [-1,1]. + */ +class audio_portaudio_sink : public gr_sync_block { + friend audio_portaudio_sink_sptr + audio_portaudio_make_sink (int sampling_rate, + const std::string device_name, + bool ok_to_block); + + friend PaStreamCallback portaudio_sink_callback; + + + unsigned int d_sampling_rate; + std::string d_device_name; + bool d_ok_to_block; + bool d_verbose; + + unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer + + PaStream *d_stream; + PaStreamParameters d_output_parameters; + + gr_buffer_sptr d_writer; // buffer used between work and callback + gr_buffer_reader_sptr d_reader; + omni_semaphore d_ringbuffer_ready; // binary semaphore + + + // random stats + int d_nunderuns; // count of underruns + gri_logger_sptr d_log; // handle to non-blocking logging instance + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + void create_ringbuffer(); + + + protected: + audio_portaudio_sink (int sampling_rate, const std::string device_name, + bool ok_to_block); + + public: + ~audio_portaudio_sink (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_PORTAUDIO_SINK_H */ diff --git a/gr-audio-portaudio/src/audio_portaudio_source.cc b/gr-audio-portaudio/src/audio_portaudio_source.cc new file mode 100644 index 00000000..3741e826 --- /dev/null +++ b/gr-audio-portaudio/src/audio_portaudio_source.cc @@ -0,0 +1,355 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in he hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOGGING 0 // define to 0 or 1 + +#define SAMPLE_FORMAT paFloat32 +typedef float sample_t; + +// Number of portaudio buffers in the ringbuffer +static const unsigned int N_BUFFERS = 4; + +static std::string +default_device_name () +{ + return gr_prefs::singleton()->get_string("audio_portaudio", "default_input_device", ""); +} + +void +audio_portaudio_source::create_ringbuffer(void) +{ + int bufsize_samples = d_portaudio_buffer_size_frames * d_input_parameters.channelCount; + + if (d_verbose) + fprintf(stderr, "ring buffer size = %d frames\n", + N_BUFFERS*bufsize_samples/d_input_parameters.channelCount); + + // FYI, the buffer indicies are in units of samples. + d_writer = gr_make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t)); + d_reader = gr_buffer_add_reader(d_writer, 0); +} + +/* + * This routine will be called by the PortAudio engine when audio is needed. + * It may called at interrupt level on some machines so don't do anything + * that could mess up the system like calling malloc() or free(). + * + * Our job is to copy framesPerBuffer frames from inputBuffer. + */ +int +portaudio_source_callback (const void *inputBuffer, + void *outputBuffer, + unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *arg) +{ + audio_portaudio_source *self = (audio_portaudio_source *)arg; + int nchan = self->d_input_parameters.channelCount; + int nframes_to_copy = framesPerBuffer; + int nframes_room = self->d_writer->space_available() / nchan; + + if (nframes_to_copy <= nframes_room){ // We've got room for the data .. + if (LOGGING) + self->d_log->printf("PAsrc cb: f/b = %4ld\n", framesPerBuffer); + + // copy from input buffer to ringbuffer + memcpy(self->d_writer->write_pointer(), + inputBuffer, + nframes_to_copy * nchan * sizeof(sample_t)); + self->d_writer->update_write_pointer(nframes_to_copy * nchan); + + // Tell the source thread there is new data in the ringbuffer. + self->d_ringbuffer_ready.post(); + return paContinue; + } + + else { // overrun + if (LOGGING) + self->d_log->printf("PAsrc cb: f/b = %4ld OVERRUN\n", framesPerBuffer); + + self->d_noverruns++; + ::write(2, "aU", 2); // FIXME change to non-blocking call + +#if 0 + // copy any frames that will fit + memcpy(self->d_writer->write_pointer(), + inputBuffer, + nframes_room * nchan * sizeof(sample_t)); + self->d_writer->update_write_pointer(nframes_room * nchan); +#endif + + self->d_ringbuffer_ready.post(); // Tell the sink to get going! + return paContinue; + } +} + + +// ---------------------------------------------------------------- + +audio_portaudio_source_sptr +audio_portaudio_make_source (int sampling_rate, const std::string dev, bool ok_to_block) +{ + return audio_portaudio_source_sptr (new audio_portaudio_source (sampling_rate, + dev, ok_to_block)); +} + +audio_portaudio_source::audio_portaudio_source(int sampling_rate, + const std::string device_name, + bool ok_to_block) + : gr_sync_block ("audio_portaudio_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + d_sampling_rate(sampling_rate), + d_device_name(device_name.empty() ? default_device_name() : device_name), + d_ok_to_block(ok_to_block), + d_verbose(gr_prefs::singleton()->get_bool("audio_portaudio", "verbose", false)), + d_portaudio_buffer_size_frames(0), + d_stream(0), + d_ringbuffer_ready(1, 1), // binary semaphore + d_noverruns(0) +{ + memset(&d_input_parameters, 0, sizeof(d_input_parameters)); + if (LOGGING) + d_log = gri_logger::singleton(); + + PaError err; + int i, numDevices; + PaDeviceIndex device = 0; + const PaDeviceInfo *deviceInfo = NULL; + + + err = Pa_Initialize(); + if (err != paNoError) { + bail ("Initialize failed", err); + } + + if (d_verbose) + gri_print_devices(); + + numDevices = Pa_GetDeviceCount(); + if (numDevices < 0) + bail("Pa Device count failed", 0); + if (numDevices == 0) + bail("no devices available", 0); + + if (d_device_name.empty()) + { + // FIXME Get smarter about picking something + device = Pa_GetDefaultInputDevice(); + deviceInfo = Pa_GetDeviceInfo(device); + fprintf(stderr,"%s is the chosen device using %s as the host\n", + deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name); + } + else + { + bool found = false; + + for (i=0;iname); + if (strstr(deviceInfo->name, d_device_name.c_str())){ + fprintf(stderr," Chosen!\n"); + device = gri_pa_find_device_by_name(deviceInfo->name); + fprintf(stderr,"%s using %s as the host\n",d_device_name.c_str(), + Pa_GetHostApiInfo(deviceInfo->hostApi)->name), fflush(stderr); + found = true; + deviceInfo = Pa_GetDeviceInfo(device); + i = numDevices; // force loop exit + } + fprintf(stderr,"\n"),fflush(stderr); + } + + if (!found){ + bail("Failed to find specified device name", 0); + } + } + + + d_input_parameters.device = device; + d_input_parameters.channelCount = deviceInfo->maxInputChannels; + d_input_parameters.sampleFormat = SAMPLE_FORMAT; + d_input_parameters.suggestedLatency = deviceInfo->defaultLowInputLatency; + d_input_parameters.hostApiSpecificStreamInfo = NULL; + + // We fill in the real channelCount in check_topology when we know + // how many inputs are connected to us. + + // Now that we know the maximum number of channels (allegedly) + // supported by the h/w, we can compute a reasonable output + // signature. The portaudio specs say that they'll accept any + // number of channels from 1 to max. + set_output_signature(gr_make_io_signature(1, deviceInfo->maxInputChannels, + sizeof (sample_t))); +} + + +bool +audio_portaudio_source::check_topology (int ninputs, int noutputs) +{ + PaError err; + + if (Pa_IsStreamActive(d_stream)) + { + Pa_CloseStream(d_stream); + d_stream = 0; + d_reader.reset(); // boost::shared_ptr for d_reader = 0 + d_writer.reset(); // boost::shared_ptr for d_write = 0 + } + + d_input_parameters.channelCount = noutputs; // # of channels we're really using + +#if 1 + d_portaudio_buffer_size_frames = (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 512 frame buffers at 48000 + fprintf(stderr, "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency to 21.3333333.. ms + 0.0213333333, (double)d_sampling_rate); +#endif + err = Pa_OpenStream(&d_stream, + &d_input_parameters, + NULL, // No output + d_sampling_rate, + d_portaudio_buffer_size_frames, + paClipOff, + &portaudio_source_callback, + (void*)this); + + if (err != paNoError) { + output_error_msg ("OpenStream failed", err); + return false; + } + +#if 0 + const PaStreamInfo *psi = Pa_GetStreamInfo(d_stream); + + d_portaudio_buffer_size_frames = (int)(d_input_parameters.suggestedLatency * psi->sampleRate); + fprintf(stderr, "Latency = %7.4f, psi->sampleRate = %g\n", + d_input_parameters.suggestedLatency, psi->sampleRate); +#endif + + fprintf(stderr, "d_portaudio_buffer_size_frames = %d\n", d_portaudio_buffer_size_frames); + + assert(d_portaudio_buffer_size_frames != 0); + + create_ringbuffer(); + + err = Pa_StartStream(d_stream); + if (err != paNoError) { + output_error_msg ("StartStream failed", err); + return false; + } + + return true; +} + +audio_portaudio_source::~audio_portaudio_source () +{ + Pa_StopStream(d_stream); // wait for output to drain + Pa_CloseStream(d_stream); + Pa_Terminate(); +} + +int +audio_portaudio_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float **out = (float **) &output_items[0]; + const unsigned nchan = d_input_parameters.channelCount; // # of channels == samples/frame + + int k; + for (k = 0; k < noutput_items; ){ + + int nframes = d_reader->items_available() / nchan; // # of frames in ringbuffer + if (nframes == 0){ // no data right now... + if (k > 0) // If we've produced anything so far, return that + return k; + + if (d_ok_to_block){ + d_ringbuffer_ready.wait(); // block here, then try again + continue; + } + + assert(k == 0); + + // There's no data and we're not allowed to block. + // (A USRP is most likely controlling the pacing through the pipeline.) + // This is an underun. The scheduler wouldn't have called us if it + // had anything better to do. Thus we really need to produce some amount + // of "fill". + // + // There are lots of options for comfort noise, etc. + // FIXME We'll fill with zeros for now. Yes, it will "click"... + + // Fill with some frames of zeros + int nf = std::min(noutput_items - k, (int) d_portaudio_buffer_size_frames); + for (int i = 0; i < nf; i++){ + for (unsigned int c = 0; c < nchan; c++){ + out[c][k + i] = 0; + } + } + k += nf; + return k; + } + + // We can read the smaller of the request and what's in the buffer. + int nf = std::min(noutput_items - k, nframes); + + const float *p = (const float *) d_reader->read_pointer(); + for (int i = 0; i < nf; i++){ + for (unsigned int c = 0; c < nchan; c++){ + out[c][k + i] = *p++; + } + } + d_reader->update_read_pointer(nf * nchan); + k += nf; + } + + return k; // tell how many we actually did +} + +void +audio_portaudio_source::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "audio_portaudio_source[%s]: %s: %s\n", + d_device_name.c_str (), msg, Pa_GetErrorText(err)); +} + +void +audio_portaudio_source::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("audio_portaudio_source"); +} diff --git a/gr-audio-portaudio/src/audio_portaudio_source.h b/gr-audio-portaudio/src/audio_portaudio_source.h new file mode 100644 index 00000000..25b0c4ba --- /dev/null +++ b/gr-audio-portaudio/src/audio_portaudio_source.h @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_AUDIO_PORTAUDIO_SOURCE_H +#define INCLUDED_AUDIO_PORTAUDIO_SOURCE_H + +#include +#include +#include +#include +#include +#include +#include + +class audio_portaudio_source; +typedef boost::shared_ptr audio_portaudio_source_sptr; + +/*! + * \PORTAUDIO audio source. + * \param sampling_rate sampling rate in Hz + * \param dev PORTAUDIO device name, e.g., "pa:" + * \param ok_to_block true if it's ok for us to block + */ +audio_portaudio_source_sptr +audio_portaudio_make_source (int sampling_rate, + const std::string dev = "", + bool ok_to_block = true); + +PaStreamCallback portaudio_source_callback; + + +/*! + * \ Audio source using PORTAUDIO + * + * Input samples must be in the range [-1,1]. + */ +class audio_portaudio_source : public gr_sync_block { + friend audio_portaudio_source_sptr + audio_portaudio_make_source (int sampling_rate, + const std::string device_name, + bool ok_to_block); + + friend PaStreamCallback portaudio_source_callback; + + + unsigned int d_sampling_rate; + std::string d_device_name; + bool d_ok_to_block; + bool d_verbose; + + unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer + + PaStream *d_stream; + PaStreamParameters d_input_parameters; + + gr_buffer_sptr d_writer; // buffer used between work and callback + gr_buffer_reader_sptr d_reader; + omni_semaphore d_ringbuffer_ready; // binary semaphore + + // random stats + int d_noverruns; // count of overruns + gri_logger_sptr d_log; // handle to non-blocking logging instance + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + void create_ringbuffer(); + + + protected: + audio_portaudio_source (int sampling_rate, const std::string device_name, + bool ok_to_block); + + public: + ~audio_portaudio_source (); + + bool check_topology (int ninputs, int noutputs); + + int work (int ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_AUDIO_PORTAUDIO_SOURCE_H */ diff --git a/gr-audio-portaudio/src/gri_portaudio.cc b/gr-audio-portaudio/src/gri_portaudio.cc new file mode 100644 index 00000000..a2b08afb --- /dev/null +++ b/gr-audio-portaudio/src/gri_portaudio.cc @@ -0,0 +1,111 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +PaDeviceIndex +gri_pa_find_device_by_name(const char *name) +{ + int i; + int numDevices; + const PaDeviceInfo *pdi; + int len = strlen( name ); + PaDeviceIndex result = paNoDevice; + numDevices = Pa_GetDeviceCount(); + for( i=0; iname, len ) == 0 ) + { + result = i; + break; + } + } + return result; +} + + +void +gri_print_devices() +{ + int numDevices, defaultDisplayed, myDevice=0; + const PaDeviceInfo *deviceInfo; + + numDevices = Pa_GetDeviceCount(); + if (numDevices < 0) + return; + + printf("Number of devices found = %d\n", numDevices); + + for (int i=0; i < numDevices; i++ ) { + deviceInfo = Pa_GetDeviceInfo( i ); + printf( "--------------------------------------- device #%d\n", i ); + /* Mark global and API specific default devices */ + defaultDisplayed = 0; + if( i == Pa_GetDefaultInputDevice() ) + { + myDevice = i; + printf( "[ Default Input" ); + defaultDisplayed = 1; + } + else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultInputDevice ) + { + const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); + printf( "[ Default %s Input", hostInfo->name ); + defaultDisplayed = 1; + } + + if( i == Pa_GetDefaultOutputDevice() ) + { + printf( (defaultDisplayed ? "," : "[") ); + printf( " Default Output" ); + defaultDisplayed = 1; + } + else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultOutputDevice ) + { + const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); + printf( (defaultDisplayed ? "," : "[") ); + printf( " Default %s Output", hostInfo->name ); + defaultDisplayed = 1; + } + if( defaultDisplayed ) + printf( " ]\n" ); + + /* print device info fields */ + printf( "Name = %s\n", deviceInfo->name ); + printf( "Host API = %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name ); + printf( "Max inputs = %d", deviceInfo->maxInputChannels ); + printf( ", Max outputs = %d\n", deviceInfo->maxOutputChannels ); + + printf( "Default low input latency = %8.3f\n", deviceInfo->defaultLowInputLatency ); + printf( "Default low output latency = %8.3f\n", deviceInfo->defaultLowOutputLatency ); + printf( "Default high input latency = %8.3f\n", deviceInfo->defaultHighInputLatency ); + printf( "Default high output latency = %8.3f\n", deviceInfo->defaultHighOutputLatency ); + } +} diff --git a/gr-audio-portaudio/src/gri_portaudio.h b/gr-audio-portaudio/src/gri_portaudio.h new file mode 100644 index 00000000..ca84aec0 --- /dev/null +++ b/gr-audio-portaudio/src/gri_portaudio.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_PORTAUDIO_H +#define INCLUDED_GRI_PORTAUDIO_H + +#include +#include + +PaDeviceIndex gri_pa_find_device_by_name(const char *name); +void gri_print_devices(); + +#endif /* INCLUDED_GRI_PORTAUDIO_H */ diff --git a/gr-audio-portaudio/src/qa_portaudio.py b/gr-audio-portaudio/src/qa_portaudio.py new file mode 100755 index 00000000..53569045 --- /dev/null +++ b/gr-audio-portaudio/src/qa_portaudio.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_portaudio + +class qa_portaudio (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have PORTAUDIO drivers, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-portaudio/src/run_tests.in b/gr-audio-portaudio/src/run_tests.in new file mode 100644 index 00000000..2f2f40e8 --- /dev/null +++ b/gr-audio-portaudio/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-portaudio/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-portaudio/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-portaudio/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-audio-windows/AUTHORS b/gr-audio-windows/AUTHORS new file mode 100644 index 00000000..a11898d6 --- /dev/null +++ b/gr-audio-windows/AUTHORS @@ -0,0 +1,2 @@ +Eric Blossom +Martin Dvh diff --git a/gr-audio-windows/ChangeLog b/gr-audio-windows/ChangeLog new file mode 100644 index 00000000..3e5ffe02 --- /dev/null +++ b/gr-audio-windows/ChangeLog @@ -0,0 +1,42 @@ +2005-08-09 Eric Blossom + + * config/gr_python.m4: tweak for cygwin from Andrew Beck. + * src/audio_windows_sink.h: #define NOMINMAX to keep windows from + defining min and max under Cygwin. + +2005-07-23 Stephane Fillod + + * config/gr_libgnuradio_core_extra_ldflags.m4: new + * config/Makefile.am, configure.ac, src/Makefile.am: added + EXTRA_LDFLAGS for --enable-runtime-pseudo-reloc option. + * config/gr_python.m4: update from gnuradio-core + +2005-07-07 Eric Blossom + + * src/audio_windows_source.cc: reformatted slightly. + +2005-05-12 Martin Dvh + + Initial version based loosely on gr-audio-oss-0.6 + only audio_sink for now (audio_source is empty stub) + +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-windows/Makefile.am b/gr-audio-windows/Makefile.am new file mode 100644 index 00000000..ed5e7524 --- /dev/null +++ b/gr-audio-windows/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src diff --git a/gr-audio-windows/README b/gr-audio-windows/README new file mode 100644 index 00000000..70fbe3ad --- /dev/null +++ b/gr-audio-windows/README @@ -0,0 +1,66 @@ + +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +gr-audio-windows will add an audio-sink to gnuradio for windows + +Requirements for building: +make sure you have the following installed: +mingw +libtool (recent version ,built yourself, (if needed remove old libtool macros from /usr/share/aclocal)) +msys +python2.4 (just install the prebuild binary for windows) +boost (built yourself, maybe just unpacking the source somewhere will do, we only use header files) +cppunit (built yourself) +gnuradio-core (built with mingw) + +Building: +sources from cvs: +edit bootstrap to your needs (see below for example) +./bootstrap +./configure /configure --with-cppunit-prefix=/whereiscppunit --with-boost-include-dir=/c/whereisboost PYTHON=/c/Python24/python am_cv_python_pythondir=/c/Python24/Lib/site-packages am_cv_python_pyexecdir=/c/Python24/Lib/site-packages +make +make check +make install + + +If you have multiple versions of aclocal then edit bootstrap and change aclocal and automake to the latest version + +You really need a recent libtool to get this built on mingw. +If you build it with default options it will be placed in /usr/local, but the default libtool will still be in /usr. +This will result in old m4 macros will be used by aclocal. +So if you have a more recent libtool installed in /usr/local add -I /usr/local/share/aclocal to the aclocal commandline in bootstrap. +(And add any other directories with the most recent m4 macros) +You could also uninstall (delete) the old libtool macros in /usr/share/aclocal + +bootstrap example: + +!/bin/sh +rm -fr config.cache autom4te*.cache +aclocal-1.8 -I /usr/local/share/aclocal -I config +autoconf +autoheader +libtoolize --automake +automake-1.8 --add-missing + + +configuration example: +./configure --with-cppunit-prefix=/usr/local --with-boost-include-dir=/d/boost_1_32_0/include/boost-1_32 PYTHON=/d/Python24/python am_cv_python_pythondir=/d/Python24/Lib/site-packages am_cv_python_pyexecdir=/d/Python24/Lib/site-packages + +Martin Dvh, juli 2005 diff --git a/gr-audio-windows/src/Makefile.am b/gr-audio-windows/src/Makefile.am new file mode 100644 index 00000000..3d9446d3 --- /dev/null +++ b/gr-audio-windows/src/Makefile.am @@ -0,0 +1,87 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.audio_windows module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in +TESTS = run_tests + +LOCAL_IFILES = \ + audio_windows.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_windows.cc \ + audio_windows.py + +ourpython_PYTHON = \ + audio_windows.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGCPPPYTHONARGS = -python $(PYTHON_CPPFLAGS) \ + -I$(swigincludedir) -I$(grincludedir) + +ourlib_LTLIBRARIES = _audio_windows.la + +_audio_windows_la_SOURCES = \ + audio_windows.cc \ + audio_windows_sink.cc \ + audio_windows_source.cc + + +grinclude_HEADERS = \ + audio_windows_sink.h \ + audio_windows_source.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_windows_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + $(GNURADIO_CORE_LIBS) \ + -lwinmm \ + -lstdc++ + +_audio_windows_la_LDFLAGS = -no-undefined -module -avoid-version \ + $(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +audio_windows.cc audio_windows.py: audio_windows.i + $(SWIG) $(SWIGCPPPYTHONARGS) -module audio_windows -o audio_windows.cc $< + + +noinst_PYTHON = qa_audio_windows.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc diff --git a/gr-audio-windows/src/audio_windows.i b/gr-audio-windows/src/audio_windows.i new file mode 100644 index 00000000..99e9e43a --- /dev/null +++ b/gr-audio-windows/src/audio_windows.i @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_windows_sink.h" +#include "audio_windows_source.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_windows,sink) + +audio_windows_sink_sptr +audio_windows_make_sink (int sampling_freq, + const std::string dev = "" + ) throw (std::runtime_error); + + +class audio_windows_sink : public gr_sync_block { + protected: + audio_windows_sink (int sampling_freq, const std::string device_name = ""); + + public: + ~audio_windows_sink (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_windows,source) + +audio_windows_source_sptr +audio_windows_make_source (int sampling_freq, + const std::string dev = "" + ) throw (std::runtime_error); + +class audio_windows_source : public gr_sync_block { + protected: + audio_windows_source (int sampling_freq, const std::string device_name = ""); + + public: + ~audio_windows_source (); +}; diff --git a/gr-audio-windows/src/audio_windows_sink.cc b/gr-audio-windows/src/audio_windows_sink.cc new file mode 100644 index 00000000..ff1d19cd --- /dev/null +++ b/gr-audio-windows/src/audio_windows_sink.cc @@ -0,0 +1,324 @@ +/* -*- c++ -*- */ +/* +* Copyright 2004 Free Software Foundation, Inc. +* +* This file is part of GNU Radio +* +* GNU Radio is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* GNU Radio is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GNU Radio; see the file COPYING. If not, write to +* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +* Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const double CHUNK_TIME = 0.1; //0.001; // 100 ms + +// FIXME these should query some kind of user preference + +static std::string +default_device_name () +{ + return "WAVE_MAPPER"; +} + +audio_windows_sink::audio_windows_sink (int sampling_freq, const std::string device_name) + : gr_sync_block ("audio_windows_sink", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (0, 0, 0)), + d_sampling_freq (sampling_freq), + d_device_name (device_name.empty ()? default_device_name () : device_name), + d_fd (-1), d_buffer (0), d_chunk_size (0) +{ + d_wave_write_event = CreateEvent (NULL, FALSE, FALSE, NULL); + if (open_waveout_device () < 0) + { + //fprintf (stderr, "audio_windows_sink:open_waveout_device() failed\n"); + perror ("audio_windows_sink:open_waveout_device( ) failed\n"); + throw + std::runtime_error ("audio_windows_sink:open_waveout_device() failed"); + } + + d_chunk_size = (int) (d_sampling_freq * CHUNK_TIME); + set_output_multiple (d_chunk_size); + + d_buffer = new short[d_chunk_size * 2]; + +} + +audio_windows_sink::~audio_windows_sink () +{ + /* Free the callback Event */ + CloseHandle (d_wave_write_event); + waveOutClose (d_h_waveout); + delete[]d_buffer; +} + +audio_windows_sink_sptr +audio_windows_make_sink (int sampling_freq, const std::string dev) +{ + return audio_windows_sink_sptr (new + audio_windows_sink (sampling_freq, dev)); +} + + +int +audio_windows_sink::work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items) +{ + const float *f0, *f1; + bool playtestsound = false; + if (playtestsound) + { + // dummy + + f0 = (const float *) input_items[0]; + + for (int i = 0; i < noutput_items; i += d_chunk_size) + { + for (int j = 0; j < d_chunk_size; j++) + { + d_buffer[2 * j + 0] = (short) (sin (2.0 * 3.1415926535897932384626 * (float) j * 1000.0 / (float) d_sampling_freq) * 8192 + 0); //+32767 + d_buffer[2 * j + 1] = d_buffer[2 * j + 0]; + } + f0 += d_chunk_size; + if (write_waveout + ((HPSTR) d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + { + fprintf (stderr, "audio_windows_sink: write failed\n"); + perror ("audio_windows_sink: write failed"); + } + } + // break; + } + else + { + switch (input_items.size ()) + { + + case 1: // mono input + + f0 = (const float *) input_items[0]; + + for (int i = 0; i < noutput_items; i += d_chunk_size) + { + for (int j = 0; j < d_chunk_size; j++) + { + d_buffer[2 * j + 0] = (short) (f0[j] * 32767); + d_buffer[2 * j + 1] = (short) (f0[j] * 32767); + } + f0 += d_chunk_size; + if (write_waveout + ((HPSTR) d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + { + //fprintf (stderr, "audio_windows_sink: write failed\n"); + perror ("audio_windows_sink: write failed"); + } + } + break; + + case 2: // stereo input + + f0 = (const float *) input_items[0]; + f1 = (const float *) input_items[1]; + + for (int i = 0; i < noutput_items; i += d_chunk_size) + { + for (int j = 0; j < d_chunk_size; j++) + { + d_buffer[2 * j + 0] = (short) (f0[j] * 32767); + d_buffer[2 * j + 1] = (short) (f1[j] * 32767); + } + f0 += d_chunk_size; + f1 += d_chunk_size; + if (write_waveout + ((HPSTR) d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + { + //fprintf (stderr, "audio_windows_sink: write failed\n"); + perror ("audio_windows_sink: write failed"); + } + } + break; + } + } + return noutput_items; +} + +int +audio_windows_sink::string_to_int (const std::string & s) +{ + int i; + std::istringstream (s) >> i; + return i; +} //ToInt() + +int +audio_windows_sink::open_waveout_device (void) +{ + + UINT /*UINT_PTR */ u_device_id; + /** Identifier of the waveform-audio output device to open. It can be either a device identifier or a handle of an open waveform-audio input device. You can use the following flag instead of a device identifier. + * + * Value Meaning + * WAVE_MAPPER The function selects a waveform-audio output device capable of playing the given format. + */ + if (d_device_name.empty () || default_device_name () == d_device_name) + u_device_id = WAVE_MAPPER; + else + u_device_id = (UINT) string_to_int (d_device_name); + // Open a waveform device for output using event callback. + + unsigned long result; + //HWAVEOUT outHandle; + WAVEFORMATEX wave_format; + + /* Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo */ + wave_format.wFormatTag = WAVE_FORMAT_PCM; + wave_format.nChannels = 2; + wave_format.nSamplesPerSec = d_sampling_freq; //44100; + wave_format.wBitsPerSample = 16; + wave_format.nBlockAlign = + wave_format.nChannels * (wave_format.wBitsPerSample / 8); + wave_format.nAvgBytesPerSec = + wave_format.nSamplesPerSec * wave_format.nBlockAlign; + wave_format.cbSize = 0; + + /* Open the (preferred) Digital Audio Out device. */ + result = waveOutOpen (&d_h_waveout, WAVE_MAPPER, &wave_format, (DWORD_PTR) d_wave_write_event, 0, CALLBACK_EVENT | WAVE_ALLOWSYNC); //|WAVE_FORMAT_DIRECT | CALLBACK_EVENT| WAVE_ALLOWSYNC + if (result) + { + fprintf (stderr, + "audio_windows_sink: Failed to open waveform output device.\n"); + perror ("audio_windows_sink: Failed to open waveform output device."); + //LocalUnlock(hFormat); + //LocalFree(hFormat); + //mmioClose(hmmio, 0); + return -1; + } + + // + // Do not Swallow the "open" event. + // + //WaitForSingleObject(d_wave_write_event, INFINITE); + + // Allocate and lock memory for the header. + + d_h_wave_hdr = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof (WAVEHDR)); + if (d_h_wave_hdr == NULL) + { + //GlobalUnlock(hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Not enough memory for header.\n"); + perror ("audio_windows_sink: Not enough memory for header."); + return -1; + } + + d_lp_wave_hdr = (LPWAVEHDR) GlobalLock (d_h_wave_hdr); + if (d_lp_wave_hdr == NULL) + { + //GlobalUnlock(hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Failed to lock memory for header.\n"); + perror ("audio_windows_sink: Failed to lock memory for header."); + return -1; + } + //d_lp_wave_hdr->dwFlags = WHDR_DONE; + return 0; +} + +int +audio_windows_sink::write_waveout (HPSTR lp_data, DWORD dw_data_size) +{ + UINT w_result; + int teller = 100; + // After allocation, set up and prepare header. + /*while ((d_lp_wave_hdr->dwFlags & WHDR_DONE)==0 && teller>0) + { + teller--; + Sleep(1); + } */ + // Wait until previous wave write completes (first event is the open event). + WaitForSingleObject (d_wave_write_event, 100); //INFINITE + d_lp_wave_hdr->lpData = lp_data; + d_lp_wave_hdr->dwBufferLength = dw_data_size; + d_lp_wave_hdr->dwFlags = 0L; + /* Clear the WHDR_DONE bit (which the driver set last time that + this WAVEHDR was sent via waveOutWrite and was played). Some + drivers need this to be cleared */ + //d_lp_wave_hdr->dwFlags &= ~WHDR_DONE; + + d_lp_wave_hdr->dwLoops = 0L; + w_result = + waveOutPrepareHeader (d_h_waveout, d_lp_wave_hdr, sizeof (WAVEHDR)); + if (w_result != 0) + { + //GlobalUnlock( hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Failed to waveOutPrepareHeader. error %i\n",w_result); + perror ("audio_windows_sink: Failed to waveOutPrepareHeader"); + } + // Now the data block can be sent to the output device. The + // waveOutWrite function returns immediately and waveform + // data is sent to the output device in the background. + //while (! readyforplayback) Sleep(1); + //readyforplayback=false; + // + // + + w_result = waveOutWrite (d_h_waveout, d_lp_wave_hdr, sizeof (WAVEHDR)); + if (w_result != 0) + { + //GlobalUnlock( hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Failed to write block to device.error %i\n",w_result); + perror ("audio_windows_sink: Failed to write block to device"); + switch (w_result) + { + case MMSYSERR_INVALHANDLE: + fprintf (stderr, "Specified device handle is invalid. \n"); + break; + case MMSYSERR_NODRIVER: + fprintf (stderr, " No device driver is present. \n"); + break; + case MMSYSERR_NOMEM: + fprintf (stderr, " Unable to allocate or lock memory. \n"); + break; + case WAVERR_UNPREPARED: + fprintf (stderr, + " The data block pointed to by the pwh parameter hasn't been prepared. \n"); + break; + default: + fprintf (stderr, "Unknown error %i\n", w_result); + } + waveOutUnprepareHeader (d_h_waveout, d_lp_wave_hdr, sizeof (WAVEHDR)); + return -1; + } + // WaitForSingleObject(d_wave_write_event, INFINITE); + return 0; +} diff --git a/gr-audio-windows/src/audio_windows_sink.h b/gr-audio-windows/src/audio_windows_sink.h new file mode 100644 index 00000000..0d7e630d --- /dev/null +++ b/gr-audio-windows/src/audio_windows_sink.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_WINDOWS_SINK_H +#define INCLUDED_AUDIO_WINDOWS_SINK_H + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX // stops windef.h defining max/min under cygwin + +#include +#include + +#include +#include + + +class audio_windows_sink; +typedef boost::shared_ptr audio_windows_sink_sptr; + +audio_windows_sink_sptr +audio_windows_make_sink (int sampling_freq, const std::string dev = ""); + +/*! + * \brief audio sink using winmm mmsystem (win32 only) + * + * input signature is one or two streams of floats. + * Input samples must be in the range [-1,1]. + */ + +class audio_windows_sink : public gr_sync_block +{ + friend + audio_windows_sink_sptr + audio_windows_make_sink (int sampling_freq, const std::string device_name); + + int d_sampling_freq; + std::string d_device_name; + int d_fd; + short *d_buffer; + int d_chunk_size; + HWAVEOUT d_h_waveout; + HGLOBAL d_h_wave_hdr; + LPWAVEHDR d_lp_wave_hdr; + HANDLE d_wave_write_event; + +protected: + int + string_to_int (const std::string & s); + audio_windows_sink (int sampling_freq, const std::string device_name = ""); + int + open_waveout_device (void); + int + write_waveout (HPSTR lp_data, DWORD dw_data_size); + +public: + ~audio_windows_sink (); + + int + work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items); +}; + +#endif /* INCLUDED_AUDIO_WINDOWS_SINK_H */ diff --git a/gr-audio-windows/src/audio_windows_source.cc b/gr-audio-windows/src/audio_windows_source.cc new file mode 100644 index 00000000..8879e3b2 --- /dev/null +++ b/gr-audio-windows/src/audio_windows_source.cc @@ -0,0 +1,208 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +//include +//include +#include +#include +#include +#include +#include +#include +#include + + +static const double CHUNK_TIME = 0.005; // 5 ms + +// FIXME these should query some kind of user preference + +static std::string +default_device_name () +{ + return "/dev/dsp"; +} + +audio_windows_source::audio_windows_source (int sampling_freq, const std::string device_name) + : gr_sync_block ("audio_windows_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 2, sizeof (float))), + d_sampling_freq (sampling_freq), + d_device_name (device_name.empty ()? default_device_name () : device_name), + d_fd (-1), d_buffer (0), d_chunk_size (0) +{ + //FIXME TODO implement me +#if 0 + if ((d_fd = open (d_device_name.c_str (), O_RDONLY)) < 0) + { + fprintf (stderr, "audio_windows_source: "); + perror (d_device_name.c_str ()); + throw + std::runtime_error ("audio_windows_source"); + } + + d_chunk_size = (int) (d_sampling_freq * CHUNK_TIME); + set_output_multiple (d_chunk_size); + + d_buffer = new short[d_chunk_size * 2]; + + int format = AFMT_S16_NE; + int orig_format = format; + if (ioctl (d_fd, SNDCTL_DSP_SETFMT, &format) < 0) + { + std:: + cerr << "audio_windows_source: " << d_device_name << + " ioctl failed\n"; + perror (d_device_name.c_str ()); + throw + std::runtime_error ("audio_windows_source"); + } + + if (format != orig_format) + { + fprintf (stderr, "audio_windows_source: unable to support format %d\n", + orig_format); + fprintf (stderr, " card requested %d instead.\n", format); + } + + // set to stereo no matter what. Some hardware only does stereo + int channels = 2; + if (ioctl (d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2) + { + perror ("audio_windows_source: could not set STEREO mode"); + throw + std::runtime_error ("audio_windows_source"); + } + + // set sampling freq + int sf = sampling_freq; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0) + { + std::cerr << "audio_windows_source: " + << d_device_name << ": invalid sampling_freq " + << sampling_freq << "\n"; + sampling_freq = 8000; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0) + { + std:: + cerr << + "audio_windows_source: failed to set sampling_freq to 8000\n"; + throw + std::runtime_error ("audio_windows_source"); + } + } +#endif +} + +audio_windows_source::~audio_windows_source () +{ + /*close (d_fd); + delete [] d_buffer; + */ +} + +audio_windows_source_sptr +audio_windows_make_source (int sampling_freq, const std::string dev) +{ + return audio_windows_source_sptr (new + audio_windows_source (sampling_freq, + dev)); +} + + +int +audio_windows_source::work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items) +{ + //FIXME TODO implement me +#if 0 + float *f0 = (float *) output_items[0]; + float *f1 = (float *) output_items[1]; // will be invalid if this is mono output + + const int shorts_per_item = 2; // L + R + const int bytes_per_item = shorts_per_item * sizeof (short); + + // To minimize latency, never return more than CHUNK_TIME + // worth of samples per call to work. + // FIXME, we need an API to set this value + + noutput_items = std::min (noutput_items, d_chunk_size); + + int base = 0; + int ntogo = noutput_items; + + while (ntogo > 0) + { + int nbytes = std::min (ntogo, d_chunk_size) * bytes_per_item; + int result_nbytes = read (d_fd, d_buffer, nbytes); + + if (result_nbytes < 0) + { + perror ("audio_windows_source"); + return -1; // say we're done + } + + if ((result_nbytes & (bytes_per_item - 1)) != 0) + { + fprintf (stderr, "audio_windows_source: internal error.\n"); + throw std::runtime_error ("internal error"); + } + + int result_nitems = result_nbytes / bytes_per_item; + + // now unpack samples into output streams + + switch (output_items.size ()) + { + case 1: // mono output + for (int i = 0; i < result_nitems; i++) + { + f0[base + i] = d_buffer[2 * i + 0] * (1.0 / 32767); + } + break; + + case 2: // stereo output + for (int i = 0; i < result_nitems; i++) + { + f0[base + i] = d_buffer[2 * i + 0] * (1.0 / 32767); + f1[base + i] = d_buffer[2 * i + 1] * (1.0 / 32767); + } + break; + + default: + assert (0); + } + + ntogo -= result_nitems; + base += result_nitems; + } + + return noutput_items - ntogo; +#endif + return -1; // EOF +} diff --git a/gr-audio-windows/src/audio_windows_source.h b/gr-audio-windows/src/audio_windows_source.h new file mode 100644 index 00000000..718ac2f9 --- /dev/null +++ b/gr-audio-windows/src/audio_windows_source.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_WINDOWS_SOURCE_H +#define INCLUDED_AUDIO_WINDOWS_SOURCE_H + +#include +#include + + +class audio_windows_source; +typedef boost::shared_ptr audio_windows_source_sptr; + +audio_windows_source_sptr +audio_windows_make_source (int sampling_freq, const std::string dev = ""); + +/*! + * \brief audio source using winmm mmsystem (win32 only) + * + * Output signature is one or two streams of floats. + * Output samples will be in the range [-1,1]. + */ + +class audio_windows_source : public gr_sync_block +{ + friend + audio_windows_source_sptr + audio_windows_make_source (int sampling_freq, + const std::string device_name); + + int d_sampling_freq; + std::string d_device_name; + int d_fd; + short *d_buffer; + int d_chunk_size; + +protected: + audio_windows_source (int sampling_freq, const std::string device_name = ""); + +public: + ~audio_windows_source (); + + int + work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items); +}; + +#endif /* INCLUDED_AUDIO_WINDOWS_SOURCE_H */ diff --git a/gr-audio-windows/src/qa_audio_windows.py b/gr-audio-windows/src/qa_audio_windows.py new file mode 100755 index 00000000..e7663a8b --- /dev/null +++ b/gr-audio-windows/src/qa_audio_windows.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_windows + +class qa_oss (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have audio drivers, soundcard, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-windows/src/run_tests.in b/gr-audio-windows/src/run_tests.in new file mode 100755 index 00000000..6eb59638 --- /dev/null +++ b/gr-audio-windows/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-windows/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-windows/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-windows/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-comedi/AUTHORS b/gr-comedi/AUTHORS new file mode 100644 index 00000000..624606f0 --- /dev/null +++ b/gr-comedi/AUTHORS @@ -0,0 +1 @@ +Stephane Fillod diff --git a/gr-comedi/ChangeLog b/gr-comedi/ChangeLog new file mode 100644 index 00000000..92ee15bc --- /dev/null +++ b/gr-comedi/ChangeLog @@ -0,0 +1,25 @@ +2005-10-10 Stephane Fillod + + * src/comedi_source.{h,cc}: new. + * src/comedi_sink.{h,cc}: new. + +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-comedi/Makefile.am b/gr-comedi/Makefile.am new file mode 100644 index 00000000..0b0234e3 --- /dev/null +++ b/gr-comedi/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src diff --git a/gr-comedi/src/Makefile.am b/gr-comedi/src/Makefile.am new file mode 100644 index 00000000..3311cd56 --- /dev/null +++ b/gr-comedi/src/Makefile.am @@ -0,0 +1,91 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.comedi module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in + +TESTS = run_tests + +LOCAL_IFILES = \ + comedi.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + comedi.cc \ + comedi.py + +ourpython_PYTHON = \ + comedi.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGCPPPYTHONARGS = -c++ -python $(PYTHON_CPPFLAGS) $(STD_DEFINES_AND_INCLUDES) +# -I$(swigincludedir) $(S-I$(grincludedir) -I$(comediincludedir) + +ourlib_LTLIBRARIES = _comedi.la + +_comedi_la_SOURCES = \ + comedi.cc \ + comedi_sink_s.cc \ + comedi_source_s.cc \ + gri_comedi.cc + +grinclude_HEADERS = \ + comedi_sink_s.h \ + comedi_source_s.h + +noinst_HEADERS = \ + gri_comedi.h + + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_comedi_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + $(GNURADIO_CORE_LIBS) \ + -lstdc++ + +_comedi_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +comedi.cc comedi.py: comedi.i + $(SWIG) $(SWIGCPPPYTHONARGS) -module comedi -o comedi.cc $< + + +noinst_PYTHON = \ + qa_comedi.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc diff --git a/gr-comedi/src/comedi.i b/gr-comedi/src/comedi.i new file mode 100644 index 00000000..18f4f441 --- /dev/null +++ b/gr-comedi/src/comedi.i @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "comedi_sink_s.h" +#include "comedi_source_s.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(comedi,source_s) + +comedi_source_s_sptr +comedi_make_source_s (int sampling_freq, + const std::string dev = "" + ) throw (std::runtime_error); + +class comedi_source_s : public gr_sync_block { + + protected: + comedi_source_s (int sampling_freq, + const std::string device_name + ) throw (std::runtime_error); + + public: + ~comedi_source_s (); + + bool start(); + bool stop(); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(comedi,sink_s) + +comedi_sink_s_sptr +comedi_make_sink_s (int sampling_freq, + const std::string dev = "" + ) throw (std::runtime_error); + +class comedi_sink_s : public gr_sync_block { + + protected: + comedi_sink_s (int sampling_freq, + const std::string device_name + ) throw (std::runtime_error); + + public: + ~comedi_sink_s (); +}; diff --git a/gr-comedi/src/comedi_sink_s.cc b/gr-comedi/src/comedi_sink_s.cc new file mode 100644 index 00000000..2c1ffb7d --- /dev/null +++ b/gr-comedi/src/comedi_sink_s.cc @@ -0,0 +1,233 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + + +/* + * comedi_sink_s is untested because I don't own appropriate hardware. + * Feedback is welcome! --SF + */ + +static std::string +default_device_name () +{ + return "/dev/comedi0"; +} + + +// ---------------------------------------------------------------- + +comedi_sink_s_sptr +comedi_make_sink_s (int sampling_freq, const std::string dev) +{ + return comedi_sink_s_sptr (new comedi_sink_s (sampling_freq, dev)); +} + +comedi_sink_s::comedi_sink_s (int sampling_freq, + const std::string device_name) + : gr_sync_block ("comedi_sink_s", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sampling_freq (sampling_freq), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_dev (0), + d_subdevice (COMEDI_SUBD_AO), + d_n_chan (1), // number of input channels + d_map (0), + d_buffer_size (0), + d_buf_front (0), + d_buf_back (0) +{ + int aref=AREF_GROUND; + int range=0; + + d_dev = comedi_open(d_device_name.c_str()); + if (d_dev == 0){ + comedi_perror(d_device_name.c_str()); + throw std::runtime_error ("comedi_sink_s"); + } + + unsigned int chanlist[256]; + + for(int i=0; i d_n_chan) + throw std::runtime_error ("comedi_sink_s"); + + return true; +} + +comedi_sink_s::~comedi_sink_s () +{ + if (d_map) { + munmap(d_map, d_buffer_size); + d_map = 0; + } + + comedi_close(d_dev); +} + +int +comedi_sink_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int ret; + + int work_left = noutput_items * sizeof(sampl_t) * d_n_chan; + sampl_t *pbuf = (sampl_t*)d_map; + + do { + + do { + ret = comedi_get_buffer_contents(d_dev,d_subdevice); + if (ret < 0) + bail ("comedi_get_buffer_contents", comedi_errno()); + + assert(ret % sizeof(sampl_t) == 0); + assert(work_left % sizeof(sampl_t) == 0); + + ret = std::min(ret, work_left); + d_buf_front += ret; + + assert(d_buffer_size%d_n_chan == 0); + if (d_buf_front-d_buf_back > (unsigned)d_buffer_size) { + d_buf_front+=d_buffer_size; + d_buf_back +=d_buffer_size; + } + + if(d_buf_front==d_buf_back){ + usleep(1000000*std::min(work_left,d_buffer_size/2)/(d_sampling_freq*sizeof(sampl_t)*d_n_chan)); + continue; + } + } while (d_buf_front==d_buf_back); + + for(unsigned i=d_buf_back/sizeof(sampl_t);i0); + + return noutput_items; +} + + +void +comedi_sink_s::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "comedi_sink_s[%s]: %s: %s\n", + d_device_name.c_str(), msg, comedi_strerror(err)); +} + +void +comedi_sink_s::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("comedi_sink_s"); +} diff --git a/gr-comedi/src/comedi_sink_s.h b/gr-comedi/src/comedi_sink_s.h new file mode 100644 index 00000000..08fce251 --- /dev/null +++ b/gr-comedi/src/comedi_sink_s.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_COMEDI_SINK_H +#define INCLUDED_COMEDI_SINK_H + +#include +#include +#include +#include + +class comedi_sink_s; +typedef boost::shared_ptr comedi_sink_s_sptr; + +/*! + * \brief make an COMEDI sink. + * + * \param sampling_freq sampling rate in Hz + * \param dev COMEDI device name, e.g., "/dev/comedi0" + */ +comedi_sink_s_sptr +comedi_make_sink_s (int sampling_freq, + const std::string dev = "/dev/comedi0"); + +/*! + * \brief sink using COMEDI + * + * The sink has one input stream of signed short integers. + * + * Input samples must be in the range [-32768,32767]. + */ +class comedi_sink_s : public gr_sync_block { + friend comedi_sink_s_sptr + comedi_make_sink_s (int sampling_freq, const std::string device_name); + + // typedef for pointer to class work method + typedef int (comedi_sink_s::*work_t)(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int d_sampling_freq; + std::string d_device_name; + + comedi_t *d_dev; + int d_subdevice; + int d_n_chan; + void *d_map; + int d_buffer_size; + unsigned d_buf_front; + unsigned d_buf_back; + + // random stats + int d_nunderuns; // count of underruns + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + + protected: + comedi_sink_s (int sampling_freq, const std::string device_name); + + public: + ~comedi_sink_s (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_COMEDI_SINK_H */ diff --git a/gr-comedi/src/comedi_source_s.cc b/gr-comedi/src/comedi_source_s.cc new file mode 100644 index 00000000..5041c9c3 --- /dev/null +++ b/gr-comedi/src/comedi_source_s.cc @@ -0,0 +1,229 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + + +// FIXME these should query some kind of user preference + + +static std::string +default_device_name () +{ + return "/dev/comedi0"; +} + +// ---------------------------------------------------------------- + +comedi_source_s_sptr +comedi_make_source_s (int sampling_freq, const std::string dev) +{ + return comedi_source_s_sptr (new comedi_source_s (sampling_freq, dev)); +} + +comedi_source_s::comedi_source_s (int sampling_freq, + const std::string device_name) + : gr_sync_block ("comedi_source_s", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)), + d_sampling_freq (sampling_freq), + d_device_name (device_name.empty() ? default_device_name() : device_name), + d_dev (0), + d_subdevice (0/*COMEDI_SUBD_AI*/), + d_n_chan (1), // number of input channels + d_map (0), + d_buffer_size (0), + d_buf_front (0), + d_buf_back (0) +{ + int aref=AREF_GROUND; + int range=0; + + d_dev = comedi_open(d_device_name.c_str()); + if (d_dev == 0){ + comedi_perror(d_device_name.c_str()); + throw std::runtime_error ("comedi_source_s"); + } + + unsigned int chanlist[256]; + + for(int i=0; i d_n_chan) + throw std::runtime_error ("comedi_source_s"); + + return true; +} + +comedi_source_s::~comedi_source_s () +{ + if (d_map) { + munmap(d_map, d_buffer_size); + d_map = 0; + } + + comedi_close(d_dev); +} + +int +comedi_source_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int ret; + + int work_left = noutput_items * sizeof(sampl_t) * d_n_chan; + sampl_t *pbuf = (sampl_t*)d_map; + + do { + + do { + ret = comedi_get_buffer_contents(d_dev,d_subdevice); + if (ret < 0) + bail ("comedi_get_buffer_contents", comedi_errno()); + + assert(ret % sizeof(sampl_t) == 0); + assert(work_left % sizeof(sampl_t) == 0); + + ret = std::min(ret, work_left); + d_buf_front += ret; + + assert(d_buffer_size%d_n_chan == 0); + if (d_buf_front-d_buf_back > (unsigned)d_buffer_size) { + d_buf_front+=d_buffer_size; + d_buf_back +=d_buffer_size; + } + + if(d_buf_front==d_buf_back){ + usleep(1000000*std::min(work_left,d_buffer_size/2)/(d_sampling_freq*sizeof(sampl_t)*d_n_chan)); + continue; + } + } while (d_buf_front==d_buf_back); + + for(unsigned i=d_buf_back/sizeof(sampl_t);i0); + + return noutput_items; +} + +void +comedi_source_s::output_error_msg (const char *msg, int err) +{ + fprintf (stderr, "comedi_source_s[%s]: %s: %s\n", + d_device_name.c_str(), msg, comedi_strerror(err)); +} + +void +comedi_source_s::bail (const char *msg, int err) throw (std::runtime_error) +{ + output_error_msg (msg, err); + throw std::runtime_error ("comedi_source_s"); +} diff --git a/gr-comedi/src/comedi_source_s.h b/gr-comedi/src/comedi_source_s.h new file mode 100644 index 00000000..e759c43a --- /dev/null +++ b/gr-comedi/src/comedi_source_s.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_COMEDI_SOURCE_S_H +#define INCLUDED_COMEDI_SOURCE_S_H + +#include +#include +#include +#include + +class comedi_source_s; +typedef boost::shared_ptr comedi_source_s_sptr; + +/*! + * \brief make a COMEDI source. + * + * \param sampling_freq sampling rate in Hz + * \param dev COMEDI device name, e.g., "/dev/comedi0" + */ +comedi_source_s_sptr +comedi_make_source_s (int sampling_freq, + const std::string dev = "/dev/comedi0"); + +/*! + * \brief source using COMEDI + * + * The source has one to many input stream of signed short integers. + * + * Output samples will be in the range [-32768,32767]. + */ +class comedi_source_s : public gr_sync_block { + friend comedi_source_s_sptr + comedi_make_source_s (int sampling_freq, const std::string device_name); + + // typedef for pointer to class work method + typedef int (comedi_source_s::*work_t)(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int d_sampling_freq; + std::string d_device_name; + + comedi_t *d_dev; + int d_subdevice; + int d_n_chan; + void *d_map; + int d_buffer_size; + unsigned d_buf_front; + unsigned d_buf_back; + + // random stats + int d_noverruns; // count of overruns + + void output_error_msg (const char *msg, int err); + void bail (const char *msg, int err) throw (std::runtime_error); + + + protected: + comedi_source_s (int sampling_freq, const std::string device_name); + + public: + ~comedi_source_s (); + + bool check_topology (int ninputs, int noutputs); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_COMEDI_SOURCE_S_H */ diff --git a/gr-comedi/src/gri_comedi.cc b/gr-comedi/src/gri_comedi.cc new file mode 100644 index 00000000..e4562629 --- /dev/null +++ b/gr-comedi/src/gri_comedi.cc @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + + diff --git a/gr-comedi/src/gri_comedi.h b/gr-comedi/src/gri_comedi.h new file mode 100644 index 00000000..5e1f00e9 --- /dev/null +++ b/gr-comedi/src/gri_comedi.h @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_COMEDI_H +#define INCLUDED_GRI_COMEDI_H + +#include + +#endif /* INCLUDED_GRI_COMEDI_H */ diff --git a/gr-comedi/src/qa_comedi.py b/gr-comedi/src/qa_comedi.py new file mode 100755 index 00000000..98b2f918 --- /dev/null +++ b/gr-comedi/src/qa_comedi.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import comedi + +class qa_comedi (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have COMEDI library, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-comedi/src/run_tests.in b/gr-comedi/src/run_tests.in new file mode 100644 index 00000000..6c0ba9d1 --- /dev/null +++ b/gr-comedi/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-comedi/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-comedi/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-comedi/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-error-correcting-codes/AUTHORS b/gr-error-correcting-codes/AUTHORS new file mode 100644 index 00000000..bb4f6a68 --- /dev/null +++ b/gr-error-correcting-codes/AUTHORS @@ -0,0 +1 @@ +Michael Dickens diff --git a/gr-error-correcting-codes/ChangeLog b/gr-error-correcting-codes/ChangeLog new file mode 100644 index 00000000..6c49533d --- /dev/null +++ b/gr-error-correcting-codes/ChangeLog @@ -0,0 +1,31 @@ +2006-07-09 Eric Blossom + + * src/lib/gr_streams_encode_convolutional.{h,cc,i}: fixes to + access second constructor via SWIG. + + * src/lib/libecc/code_metrics.cc: added missing include. + +2006-07-03 Michael Dickens + + * In development. + +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-error-correcting-codes/Makefile.am b/gr-error-correcting-codes/Makefile.am new file mode 100644 index 00000000..67a9e921 --- /dev/null +++ b/gr-error-correcting-codes/Makefile.am @@ -0,0 +1,27 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src +DIST_SUBDIRS = src + +MOSTLYCLEANFILES = *~ diff --git a/gr-error-correcting-codes/src/Makefile.am b/gr-error-correcting-codes/src/Makefile.am new file mode 100644 index 00000000..a7da9c7a --- /dev/null +++ b/gr-error-correcting-codes/src/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib python + +MOSTLYCLEANFILES = *~ diff --git a/gr-error-correcting-codes/src/lib/Makefile.am b/gr-error-correcting-codes/src/lib/Makefile.am new file mode 100644 index 00000000..3168a58f --- /dev/null +++ b/gr-error-correcting-codes/src/lib/Makefile.am @@ -0,0 +1,101 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = libecc + +LIBS += $(GNURADIO_CORE_LIBS) + +# Install this stuff so that it ends up as the gnuradio.und module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpythondir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(GNURADIO_INCLUDES) + +SWIGCPPPYTHONARGS = -fvirtual -python -modern $(PYTHON_CPPFLAGS) \ + $(GNURADIO_INCLUDES) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +LOCAL_IFILES = \ + gr_syms_to_metrics.i \ + gr_metrics_decode_viterbi_full_block.i \ + gr_streams_encode_convolutional.i \ + gr_streams_encode_turbo.i \ + ecc.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _howto shared library +# and knows how to call our extensions. + +BUILT_SOURCES = \ + ecc.cc \ + ecc.py + +# This gets ecc.py installed in the right place +ourpython_PYTHON = \ + __init__.py \ + ecc.py + +ourlib_LTLIBRARIES = _ecc.la + +# These are the source files that go into the shared library +_ecc_la_SOURCES = \ + gr_syms_to_metrics.cc \ + gr_metrics_decode_viterbi_full_block.cc \ + gr_streams_encode_convolutional.cc \ + gr_streams_encode_turbo.cc \ + ecc.cc + +# magic flags +_ecc_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against the c++ standard library +_ecc_la_LIBADD = \ + libecc/libecc.la \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + gr_syms_to_metrics.h \ + gr_metrics_decode_viterbi_full_block.h \ + gr_streams_encode_convolutional.h \ + gr_streams_encode_turbo.h + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = $(LOCAL_IFILES) + +ecc.cc ecc.py: ecc.i $(ALL_IFILES) + $(SWIG) $(SWIGCPPPYTHONARGS) -module ecc -o ecc.cc $< + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc *.loT *~ + +CONFIG_CLEAN_FILES = *.in diff --git a/gr-error-correcting-codes/src/lib/__init__.py b/gr-error-correcting-codes/src/lib/__init__.py new file mode 100644 index 00000000..911b38b5 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/__init__.py @@ -0,0 +1,20 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio. +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-error-correcting-codes/src/lib/ecc.i b/gr-error-correcting-codes/src/lib/ecc.i new file mode 100644 index 00000000..32ea9d2b --- /dev/null +++ b/gr-error-correcting-codes/src/lib/ecc.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); +%include "exception.i" +%import "gnuradio.i" + +%{ + +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include +#include +#include +#include +#include + +%} + +%include "gr_streams_encode_convolutional.i" +%include "gr_streams_encode_turbo.i" +%include "gr_metrics_decode_viterbi_full_block.i" +%include "gr_syms_to_metrics.i" diff --git a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc b/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc new file mode 100644 index 00000000..94a7fe44 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc @@ -0,0 +1,228 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_metrics_decode_viterbi_full_block_sptr +gr_make_metrics_decode_viterbi_full_block +(int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state) +{ + return gr_metrics_decode_viterbi_full_block_sptr + (new gr_metrics_decode_viterbi_full_block + (sample_precision, + frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generator, + do_termination, + start_memory_state, + end_memory_state)); +} + +gr_metrics_decode_viterbi_full_block_feedback_sptr +gr_make_metrics_decode_viterbi_full_block_feedback +(int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state) +{ + return gr_metrics_decode_viterbi_full_block_feedback_sptr + (new gr_metrics_decode_viterbi_full_block + (sample_precision, + frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generator, + code_feedback, + do_termination, + start_memory_state, + end_memory_state)); +} + +gr_metrics_decode_viterbi_full_block::gr_metrics_decode_viterbi_full_block +(int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state) + : gr_block ("metrics_decode_viterbi_full_block", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)) +{ + d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generator, + do_termination, + start_memory_state, + end_memory_state); + + setup_io_signatures (sample_precision, n_code_inputs, n_code_outputs); +} + +gr_metrics_decode_viterbi_full_block::gr_metrics_decode_viterbi_full_block +(int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state) + : gr_block ("metrics_decode_viterbi_full_block_feedback", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)) +{ + d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generator, + code_feedback, + do_termination, + start_memory_state, + end_memory_state); + + setup_io_signatures (sample_precision, n_code_inputs, n_code_outputs); +} + +gr_metrics_decode_viterbi_full_block::~gr_metrics_decode_viterbi_full_block +() +{ + delete d_decoder; + delete d_encoder; +} + +void +gr_metrics_decode_viterbi_full_block::setup_io_signatures +(int sample_precision, + int n_code_inputs, + int n_code_outputs) +{ + // create the decoder using: + // + // the "i1" input model: individual input streams; two per metric + // type (0-bit, 1-bit), single metric per input item (char, short, long) + // + // the "ic1" output model: + // individual output streams per decoded code input stream; + // each item is a 'char' type with 1 bit aligned on the LSB. + + d_decoder = new decoder_viterbi_full_block_i1_ic1 (sample_precision, + d_encoder); + + // error checking is done in the encoder and decoder classes + // so just use the parameters as given; will be correct! + + d_n_code_inputs = n_code_inputs; + d_n_code_outputs = n_code_outputs; + + // output signature is always the same: + // sizeof (char) with 1 bit per char as the LSB + + set_output_signature (gr_make_io_signature (d_n_code_inputs, + d_n_code_inputs, + sizeof (char))); + + // determine the input signature element size + size_t l_input_item_size_bytes; + + if (sample_precision == 0) { + // float + l_input_item_size_bytes = sizeof (float); + } else if (sample_precision <= 8) { + // use char + l_input_item_size_bytes = sizeof (char); + } else if (sample_precision <= 16) { + // use short + l_input_item_size_bytes = sizeof (short); + } else { + // use long + l_input_item_size_bytes = sizeof (long); + } + + set_input_signature (gr_make_io_signature (2*d_n_code_outputs, + 2*d_n_code_outputs, + l_input_item_size_bytes)); +} + +void gr_metrics_decode_viterbi_full_block::forecast +(int noutput_items, + gr_vector_int &ninput_items_required) +{ + int ninput_items = d_decoder->compute_n_input_metrics (noutput_items); + size_t ninputs = ninput_items_required.size(); + for (size_t n = 0; n < ninputs; n++) + ninput_items_required[n] = ninput_items; +} + +int +gr_metrics_decode_viterbi_full_block::general_work +(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // FIXME: compute the actual number of output items (1 bit char's) created. + + size_t t_n_input_items = d_decoder->compute_n_input_metrics (noutput_items); + size_t t_n_output_items = d_decoder->compute_n_output_bits (t_n_input_items); + + assert (t_n_output_items == ((size_t)noutput_items)); + + // "work" is handled by the decoder; which returns the actual number + // of input items (metrics) used. + + t_n_input_items = d_decoder->decode ((const char**)(&input_items[0]), + (char**)(&output_items[0]), + noutput_items); + + // consume the number of used input items on all input streams + + consume_each (t_n_input_items); + + // returns number of items written to each output stream + + return (noutput_items); +} diff --git a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h b/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h new file mode 100644 index 00000000..57ca1bab --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h @@ -0,0 +1,163 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H +#define INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H + +#include +#include +#include + +class gr_metrics_decode_viterbi_full_block; + +typedef boost::shared_ptr +gr_metrics_decode_viterbi_full_block_sptr, +gr_metrics_decode_viterbi_full_block_feedback_sptr; + +gr_metrics_decode_viterbi_full_block_sptr +gr_make_metrics_decode_viterbi_full_block +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + std::vector code_generator, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0); + +gr_metrics_decode_viterbi_full_block_feedback_sptr +gr_make_metrics_decode_viterbi_full_block_feedback +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + std::vector code_generator, + std::vector code_feedback, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0); + +/*! + * \brief Decode the incoming streams using a Viterbi-style decoder, + * full trellis block decoding. + * + * input: symbol metrics data. + * + * output: stream(s) of char, single bit stored in the LSB. + */ + +class gr_metrics_decode_viterbi_full_block : public gr_block +{ + friend gr_metrics_decode_viterbi_full_block_sptr + gr_make_metrics_decode_viterbi_full_block + (int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + + friend gr_metrics_decode_viterbi_full_block_feedback_sptr + gr_make_metrics_decode_viterbi_full_block_feedback + (int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); +/* + * frame_size_bits: if == 0, then do streaming decoding (infinite + * trellis); otherwise this is the block size to decode before + * terminating the trellis. + * + * code_generator: vector of integers (32 bit) representing the code + * to be implemented in octal form. E.g. "04" in binary is "100", + * which would be "D^2" for code generation. "06" == 110b == "D^2 + D" + * ==> The vector is listed in order for each input stream, so if there + * are 2 input streams (I1, I2) [specified in "n_code_inputs"] + * and 2 output streams (O1, O2) [specified in "n_code_outputs"], + * then the vector would be the code generator for: + * [I1->O1, I1->O2, I2->O1, I2->O2] + * with each element being the octal representation of the code. + * + * do_termination is valid only if frame_size_bits != 0, and defines + * whether or not to to trellis termination. + * + * do_mux_input: is true, then the one input stream will be + * interpreted as the multiplexing all of the input bits. For + * example for a 3 input decoder, the input stream would be + * [I1[k], I2[k], I3[k], I1[k+1], I2[k+1], ...], where "k" is the + * input sample time, and "I1" through "I3" are the 3 input + * streams. + * + * n_code_inputs: the number of decoder-input (encoder-output) + * streams, no matter if separate or mux'ed + * + * n_code_outputs: the number of decoder-output (encoder-input) streams + */ + + gr_metrics_decode_viterbi_full_block + (int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + + gr_metrics_decode_viterbi_full_block + (int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); + +public: + ~gr_metrics_decode_viterbi_full_block (); + + virtual void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + virtual int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +protected: + void setup_io_signatures (int sample_precision, + int n_code_inputs, + int n_code_outputs); + + int d_n_code_inputs, d_n_code_outputs; + decoder_viterbi_full_block_i1_ic1* d_decoder; + encoder_convolutional_ic1_ic1* d_encoder; +}; + +#endif /* INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H */ diff --git a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i b/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i new file mode 100644 index 00000000..a7cd1ba2 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,metrics_decode_viterbi_full_block); + +// corrected "class NAME" statement, which uses slightly different NAMEs + +typedef boost::shared_ptr +gr_metrics_decode_viterbi_full_block_feedback_sptr; + +LOCAL_GR_SWIG_BLOCK_MAGIC(gr,metrics_decode_viterbi_full_block_feedback); + +gr_metrics_decode_viterbi_full_block_sptr +gr_make_metrics_decode_viterbi_full_block +(int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + +gr_metrics_decode_viterbi_full_block_feedback_sptr +gr_make_metrics_decode_viterbi_full_block_feedback +(int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); + +class gr_metrics_decode_viterbi_full_block : public gr_block +{ + gr_metrics_decode_viterbi_full_block + (int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + + gr_metrics_decode_viterbi_full_block + (int sample_precision, + int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); +}; diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc b/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc new file mode 100644 index 00000000..98e29265 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc @@ -0,0 +1,220 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_streams_encode_convolutional_sptr +gr_make_streams_encode_convolutional +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state) +{ + return gr_streams_encode_convolutional_sptr + (new gr_streams_encode_convolutional (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generator, + do_termination, + start_memory_state, + end_memory_state)); +} + +gr_streams_encode_convolutional_sptr +gr_make_streams_encode_convolutional_feedback +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state) +{ + return gr_streams_encode_convolutional_sptr + (new gr_streams_encode_convolutional (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generator, + code_feedback, + do_termination, + start_memory_state, + end_memory_state)); +} + +gr_streams_encode_convolutional::gr_streams_encode_convolutional +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + bool do_termination, + int start_memory_state, + int end_memory_state) + : gr_block ("streams_encode_convolutional", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)) +{ + // error checking is done by the encoder class itself; + // just pass items on here. + + d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + do_termination, + start_memory_state, + end_memory_state); + + setup_io_signatures (n_code_inputs, n_code_outputs); +} + +gr_streams_encode_convolutional::gr_streams_encode_convolutional +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state) + : gr_block ("streams_encode_convolutional_feedback", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)) +{ + // error checking is done by the encoder class itself; + // just pass items on here. + + d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + code_feedback, + do_termination, + start_memory_state, + end_memory_state); + + setup_io_signatures (n_code_inputs, n_code_outputs); +} + +void +gr_streams_encode_convolutional::setup_io_signatures +(int n_code_inputs, + int n_code_outputs) +{ + fprintf (stderr, "gr_s_e_c: d_encoder == %X\n", (unsigned int)d_encoder); + + // create the correct input signature; 1 bit per input char + + set_input_signature (gr_make_io_signature (n_code_inputs, + n_code_inputs, + sizeof (char))); + + // create the correct output signature; 1 bit per output char + + set_output_signature (gr_make_io_signature (n_code_outputs, + n_code_outputs, + sizeof (char))); + + // no need to set the output multiple (to 1 item), since 1 is the + // default, and the encoder class handles the rest internally + + // no need to set the relative rate (# out / # in) because for each + // input bit per input stream there is 1 output bit per output + // stream ... with a little added for termination, but ignore those. +} + +gr_streams_encode_convolutional::~gr_streams_encode_convolutional +() +{ + delete d_encoder; + d_encoder = 0; +} + +/* + * Compute the number of input items needed to produce 'n_output' + * bits. Handled internally by the encoder. + */ + +void gr_streams_encode_convolutional::forecast +(int noutput_items, + gr_vector_int &ninput_items_required) +{ + fprintf (stderr, "gr_s_e_c::forecast: #out = %d\n", + noutput_items); + + int ninput_items = d_encoder->compute_n_input_bits (noutput_items); + + fprintf (stderr, "s_e_c::forecast: #out = %d, #in = %d\n", + noutput_items, ninput_items); + + size_t ninputs = ninput_items_required.size(); + for (size_t n = 0; n < ninputs; n++) + ninput_items_required[n] = ninput_items; +} + +int +gr_streams_encode_convolutional::general_work +(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + fprintf (stderr, "gr_s_e_c::general_work: Starting #out = %d\n", + noutput_items); + + // FIXME: compute the actual number of output items (1 bit char's) created. + + size_t t_n_input_items = d_encoder->compute_n_input_bits (noutput_items); + +#if 0 + size_t t_n_output_items = d_encoder->compute_n_output_bits (t_n_input_items); + + assert (t_n_output_items == ((size_t)noutput_items)); +#endif + + // "work" is handled by the encoder; which returns the actual number + // of input items (1-bit char's) used. + + t_n_input_items = d_encoder->encode ((const char **)(&input_items[0]), + (char **)(&output_items[0]), + (size_t) noutput_items); + + assert (0); + + // consume the number of used input items on all input streams + + consume_each (t_n_input_items); + + // returns number of items written to each output stream + + return (noutput_items); +} diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h b/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h new file mode 100644 index 00000000..66e91091 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h @@ -0,0 +1,155 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H +#define INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H + +#include +#include + +/*! + * \brief Encode the incoming streams using a convolutional encoder + * + * input: streams of char, one stream per input as defined by the + * instantiated code, using only the right-most justified bit as + * the single input bit per input item. + * + * output: streams of char, one stream per output as defined by the + * instantiated code, using only the right-most justified bit as + * the single output bit per output item. + * + * frame_size_bits: if == 0, then do streaming encoding ("infinite" + * trellis); otherwise this is the frame size in bits to encode + * before terminating the trellis. This value -does not- include + * any termination bits. + * + * n_code_inputs: + * n_code_outputs: + * code_generator: vector of integers (32 bit) representing the code + * to be implemented. E.g. "4" in binary is "100", which would be + * "D^2" for code generation. "6" == 110b == "D^2 + D" + * ==> The vector is listed in order for each output stream, so if there + * are 2 input streams (I1, I2) [specified in "n_code_inputs"] + * and 2 output streams (O1, O2) [specified in "n_code_outputs"], + * then the vector would be the code generator for: + * [I1->O1, I2->O1, I1->O2, I2->O2] + * with each element being an integer representation of the code. + * + * do_termination: valid only if frame_size_bits != 0, and defines + * whether or not to use trellis termination. Default is to use + * termination when doing block coding. + * + * start_memory_state: when starting a new block, the starting memory + * state to begin encoding; there will be a helper function to + * assist in creating this value for a given set of inputs; + * default is the "all zero" state. + * + * end_memory_state: when terminating a block, the ending memory + * state to stop encoding; there will be a helper function to + * assist in creating this value for a given set of inputs; + * default is the "all zero" state. + */ + +class gr_streams_encode_convolutional; +typedef boost::shared_ptr + gr_streams_encode_convolutional_sptr; + +gr_streams_encode_convolutional_sptr +gr_make_streams_encode_convolutional +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0); + +gr_streams_encode_convolutional_sptr +gr_make_streams_encode_convolutional_feedback +(int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0); + +class gr_streams_encode_convolutional : public gr_block +{ + friend gr_streams_encode_convolutional_sptr + gr_make_streams_encode_convolutional + (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + + friend gr_streams_encode_convolutional_sptr + gr_make_streams_encode_convolutional_feedback + (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); + + gr_streams_encode_convolutional (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + + gr_streams_encode_convolutional (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); + + void setup_io_signatures (int n_code_inputs, int n_code_outputs); + + encoder_convolutional_ic1_ic1* d_encoder; + +public: + ~gr_streams_encode_convolutional (); + + inline encoder_convolutional_ic1_ic1* encoder () {return (d_encoder);}; + + virtual void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + virtual int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H */ diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i b/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i new file mode 100644 index 00000000..63d60c6d --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,streams_encode_convolutional); + +// Rename second constructor +%rename(streams_encode_convolutional_feedback) gr_make_streams_encode_convolutional_feedback; + +// support vectors of these ... for use in the convolutional decoder +// as well as Turbo Codes (both encoder and decoder). + +namespace std { + %template(x_vector_gr_streams_encode_convolutional_sptr) vector; +}; + +gr_streams_encode_convolutional_sptr +gr_make_streams_encode_convolutional +(int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0); + +gr_streams_encode_convolutional_sptr +gr_make_streams_encode_convolutional_feedback +(int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0); + +class gr_streams_encode_convolutional : public gr_block +{ +private: + gr_streams_encode_convolutional + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + bool do_termination, + int start_memory_state, + int end_memory_state); + + gr_streams_encode_convolutional + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generator, + const std::vector &code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state); +}; diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc b/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc new file mode 100644 index 00000000..9d7f72fe --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc @@ -0,0 +1,209 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +gr_streams_encode_turbo_sptr +gr_make_streams_encode_turbo +(int n_code_inputs, + int n_code_outputs, + const std::vector &encoders, + const std::vector &interleavers) +{ + return gr_streams_encode_turbo_sptr + (new gr_streams_encode_turbo (n_code_inputs, + n_code_outputs, + encoders, + interleavers)); +} + +gr_streams_encode_turbo::gr_streams_encode_turbo +(int n_code_inputs, + int n_code_outputs, + const std::vector &encoders, + const std::vector &interleavers) + : gr_block ("streams_encode_turbo", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (0, 0, 0)) +{ + // error checking is done by the encoder class itself; + // just pass items on here. + + // check out individual encoders, to make sure the total input / + // output matches those specified by the user. + + d_n_encoders = encoders.size (); + + if (d_n_encoders < 2) { + std::cerr << "gr_streams_encode_turbo: Error: " + "too few (" << d_n_encoders << ") encoders specified; a Turbo " + "code requires at least 2 constituent encoders.\n"; + assert (0); + } + + // make sure that the block size and termination are consistent for + // all encoders; warn the user if not, since it doesn't really + // matter to the encoder (but it might to the decoder; remains to be + // seen). + + encoder_convolutional_ic1_ic1* t_ec = encoders[0]->encoder (); + d_block_size_bits = t_ec->block_size_bits (); + d_do_termination = t_ec->do_termination (); + bool t_diff_block_size, t_diff_termination; + t_diff_block_size = t_diff_termination = false; + + for (size_t m = 1; m < d_n_encoders; m++) { + t_ec = encoders[0]->encoder (); + size_t t_block_size_bits = t_ec->block_size_bits (); + if (t_block_size_bits != d_block_size_bits) + t_diff_block_size = true; + bool t_do_termination = t_ec->do_termination (); + if (t_do_termination != d_do_termination) + t_do_termination = true; + } + + if (t_diff_block_size == true) { + std::cout << "gr_streams_encode_turbo: Warning: " + "Some constituent encoders have different block size (bits).\n"; + } + if (t_diff_termination == true) { + std::cout << "gr_streams_encode_turbo: Warning: " + "Some constituent encoders are differently terminationed.\n"; + } + + std::cout << "gr_streams_encode_turbo: setup:\n" + "d_n_encoders = " << d_n_encoders << "\n" + "n_code_inputs = " << n_code_inputs << "\n" + "n_code_outputs = " << n_code_outputs << "\n\n" + "Individual Encoders:\n"; + + for (size_t m = 0; m < d_n_encoders; m++) { + t_ec = encoders[m]->encoder (); + std::cout << " [" << (m+1) << "]:\n" + "n_code_inputs = " << (t_ec->n_code_inputs()) << "\n" + "n_code_outputs = " << (t_ec->n_code_outputs()) << "\n" + "block_size_bits = " << (t_ec->block_size_bits()) << "\n" + "do_termination = " << + ((t_ec->do_termination()==true)?"true":"false") << "\n"; + } + +#if 1 + assert (0); +#else + if (d_n_encoders != (interleavers.size())) {} + + d_encoder = new encoder_turbo_ic1_ic1 (n_code_inputs, + n_code_outputs, + code_generators, + do_termination, + start_memory_state, + end_memory_state); +#endif + + // create the correct input signature; 1 bit per input char + + set_input_signature (gr_make_io_signature (n_code_inputs, + n_code_inputs, + sizeof (char))); + + // create the correct output signature; 1 bit per output char + + set_output_signature (gr_make_io_signature (n_code_outputs, + n_code_outputs, + sizeof (char))); + +// set the output multiple to 1 item, then let the encoder class +// handle the rest internally + + set_output_multiple (1); +} + +gr_streams_encode_turbo::~gr_streams_encode_turbo +() +{ + if (d_encoder) + delete d_encoder; +} + +/* + * Compute the number of input bits (items in this case, since each + * item has 1 bit in it) needed to produce 'n_output' bits (items in + * this case, since each item has 1 bit in it). + * + * For turbo encoders, there is 1 bit output per bit input per + * stream, with the addition of a some bits for trellis termination if + * selected. Thus the input:output bit ratio will be: + * + * if (streaming | no termination), 1:1 + * + * if (not streaming & termination), roughly 1:(1+X), where "X" is the + * total memory size of the code divided by the block length in bits. + * But this also depends on the state of the FSM ... how many bits are + * left before termination. + */ + +void gr_streams_encode_turbo::forecast +(int noutput_items, + gr_vector_int &ninput_items_required) +{ + int ninput_items = d_encoder->compute_n_input_bits (noutput_items); + size_t ninputs = ninput_items_required.size(); + for (size_t n = 0; n < ninputs; n++) + ninput_items_required[n] = ninput_items; +} + +int +gr_streams_encode_turbo::general_work +(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // FIXME: compute the actual number of output items (1 bit char's) created. + + size_t t_n_input_items = d_encoder->compute_n_input_bits (noutput_items); + size_t t_n_output_items = d_encoder->compute_n_output_bits (t_n_input_items); + + assert (t_n_output_items == ((size_t)noutput_items)); + + // "work" is handled by the encoder; which returns the actual number + // of input items (1-bit char's) used. + + t_n_input_items = d_encoder->encode ((const char **)(&input_items[0]), + (char **)(&output_items[0]), + (size_t) noutput_items); + + // consume the number of used input items on all input streams + + consume_each (t_n_input_items); + + // returns number of items written to each output stream + + return (noutput_items); +} diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h b/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h new file mode 100644 index 00000000..94277248 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h @@ -0,0 +1,104 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_STREAMS_ENCODE_TURBO_H +#define INCLUDED_GR_STREAMS_ENCODE_TURBO_H + +#include +#include + +#if 0 +#include +#else +#include +#endif + +/*! + * \brief Encode the incoming stream(s) using a turbo encoder + * + * input: streams of char, one stream per input as defined by the + * instantiated code, using only the right-most justified bit as + * the single input bit per input item. + * + * output: streams of char, one stream per output as defined by the + * instantiated code, using only the right-most justified bit as + * the single output bit per output item. + * + * n_code_inputs: + * n_code_outputs: the total number of code inputs and outputs for the + * overall turbo encoder (not just the constituent codes). + * + * encoders: the constituent encoders to be used; all -should- be + * configured with the same "block_size" and "termination", though + * from this encoder's perspective it doesn't really matter. + * + * interleavers: the interleavers to use before each encoder, + * respectively, except the first encoder which will not use an + * interleaver. + */ + +class gr_streams_encode_turbo; + +typedef boost::shared_ptr +gr_streams_encode_turbo_sptr; + +gr_streams_encode_turbo_sptr +gr_make_streams_encode_turbo +(int n_code_inputs, + int n_code_outputs, + const std::vector &encoders, + const std::vector &interleavers); + +class gr_streams_encode_turbo : public gr_block +{ + friend gr_streams_encode_turbo_sptr + gr_make_streams_encode_turbo + (int n_code_inputs, + int n_code_outputs, + const std::vector &d_encoders, + const std::vector &d_interleavers); + + gr_streams_encode_turbo + (int n_code_inputs, + int n_code_outputs, + const std::vector &d_encoders, + const std::vector &d_interleavers); + + std::vector d_encoders; + std::vector d_interleavers; + size_t d_n_encoders, d_block_size_bits; + bool d_do_termination; + encoder_turbo* d_encoder; + +public: + ~gr_streams_encode_turbo (); + + virtual void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + virtual int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAMS_ENCODE_TURBO_H */ diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i b/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i new file mode 100644 index 00000000..59ca5c51 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,streams_encode_turbo); + +#include + +gr_streams_encode_turbo_sptr +gr_make_streams_encode_turbo +(int n_code_inputs, + int n_code_outputs, + const std::vector &encoders, + const std::vector &interleavers); + +class gr_streams_encode_turbo : public gr_block +{ + gr_streams_encode_turbo + (int frame_size_bits, + int n_code_inputs, + const std::vector &encoders, + const std::vector &interleavers); +}; diff --git a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc b/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc new file mode 100644 index 00000000..7a123096 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc @@ -0,0 +1,167 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +gr_syms_to_metrics_sptr +gr_make_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision) +{ + return gr_syms_to_metrics_sptr + (new gr_syms_to_metrics (pdf_fcn_0_bit, + pdf_fcn_1_bit, + n_samples, + min_sample, + max_sample, + sample_precision)); +} + +/* + * dummy functions and variables to get the float(*)(float) function + * to work properly with the gr_feval_XX stuff. + */ + +static gr_feval_ff* l_pdf_fcn_0_bit; +static gr_feval_ff* l_pdf_fcn_1_bit; + +static float pdf_fcn_0 (float x) +{ + return (l_pdf_fcn_0_bit->eval (x)); +} + +static float pdf_fcn_1 (float x) +{ + return (l_pdf_fcn_1_bit->eval (x)); +} + +gr_syms_to_metrics::gr_syms_to_metrics +(gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision) + : gr_block ("syms_to_metrics", + gr_make_io_signature (1, -1, sizeof (float)), + gr_make_io_signature (0, 0, 0)) +{ + if ((sample_precision < 0) | (sample_precision > 32)) { + fprintf (stderr, "gr_syms_to_metrics: sample_precision must be " + " between 0 and 32.\n"); + assert (0); + } + + l_pdf_fcn_0_bit = pdf_fcn_0_bit; + l_pdf_fcn_1_bit = pdf_fcn_1_bit; + + if (sample_precision == 0) { + // float + d_out_item_size_bytes = sizeof (float); + d_code_metrics = new code_metric_ff (&pdf_fcn_0, + &pdf_fcn_1, + n_samples, + min_sample, + max_sample); + } else if (sample_precision <= 8) { + // use char + d_out_item_size_bytes = sizeof (char); + d_code_metrics = new code_metric_fb (&pdf_fcn_0, + &pdf_fcn_1, + n_samples, + min_sample, + max_sample, + sample_precision); + } else if (sample_precision <= 16) { + // use short + d_out_item_size_bytes = sizeof (short); + d_code_metrics = new code_metric_fs (&pdf_fcn_0, + &pdf_fcn_1, + n_samples, + min_sample, + max_sample, + sample_precision); + } else { + // use long + d_out_item_size_bytes = sizeof (long); + d_code_metrics = new code_metric_fl (&pdf_fcn_0, + &pdf_fcn_1, + n_samples, + min_sample, + max_sample, + sample_precision); + } + + set_output_signature (gr_make_io_signature (1, -1, d_out_item_size_bytes)); +} + +bool gr_syms_to_metrics::check_topology (int ninputs, int noutputs) +{ + return ((noutputs == (2*ninputs)) ? true : false); +} + +void +gr_syms_to_metrics::forecast +(int noutput_items, + gr_vector_int &ninput_items_required) +{ + // always 1:1, for all streams + for (size_t n = 0; n < ninput_items_required.size(); n++) { + ninput_items_required[n] = noutput_items; + } +} + +int +gr_syms_to_metrics::general_work +(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t l_n_output_items = noutput_items; + + for (size_t n = 0; n < input_items.size(); n++) { + float* t_in_buf = (float*)(&input_items[n]); + void* t_out_buf_0_bit = (void*)(&(output_items[2*n])); + void* t_out_buf_1_bit = (void*)(&(output_items[(2*n)+1])); + + d_code_metrics->convert (l_n_output_items, t_in_buf, + t_out_buf_0_bit, t_out_buf_1_bit); + } + + // consume the number of used input items on all input streams + + consume_each (noutput_items); + + // returns number of items written to each output stream + + return (noutput_items); +} diff --git a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h b/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h new file mode 100644 index 00000000..d084fde8 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h @@ -0,0 +1,121 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_SYMS_TO_METRICS_H +#define INCLUDED_SYMS_TO_METRICS_H + +#include +#include +#include +#include + +class gr_syms_to_metrics; +typedef boost::shared_ptr gr_syms_to_metrics_sptr; + +gr_syms_to_metrics_sptr gr_make_syms_to_metrics +(gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision); + +/*! + * \brief Convert the input stream(s) of soft (float) symbols to + * log-probability metrics of user-specified precision; output is 2 + * streams per input stream, each stream consisting of the metric for + * receiving a 0-bit and 1-bit, respectively, with the lower-numbered + * stream being the 0-bit. + * + * input: stream(s) of float; output: stream(s) of metrics + */ + +class gr_syms_to_metrics : public gr_block +{ + friend gr_syms_to_metrics_sptr + gr_make_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision); + +/* + * gr_syms_to_metrics: Convert the input soft (float) symbols into + * log-probabilities (metrics) for use in the convolutional + * decoder. Samples the provided PDF function in 'n_samples' + * places from 'min_sample' to 'max_sample', takes the log of that + * value, then converts the result into a given precision and + * stores all results in a "handy dandy" lookup table for much + * faster processing. + * + * pdf_fcn_0_bit: point to a probability distribution function which + * takes a float and returns a float, for the 0-bit probabilities. + * + * pdf_fcn_1_bit: point to a probability distribution function which + * takes a float and returns a float, for the 1-bit probabilities. + * + * n_samples: the number of samples between min_sample and max_sample + * to store in the lookup table. Must be at least 2, but + * otherwise is limited only by the amount of available memory; + * generally, 65536 (1 << 16) is plenty of samples. + * + * min_sample: the minimum value below which any incoming value is + * "rounded" up. + * + * max_sample: the maximum value above which any incoming value is + * "rounded" down. + * + * sample_precision: the precision with which to sample the returned + * value of the PDF function. + * + Cannot be < 0 or > 32. + * + "soft float" == 0 + * + otherwise, convert to an integer of the given value + * + * in "work", finds the (linearly) closest sample value for the given + * input and outputs the metric for a 0-bit input on the first + * stream and a 1-bit input on the second stream. + * + */ + + gr_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision); + + size_t d_out_item_size_bytes; + code_metrics* d_code_metrics; + +public: + bool check_topology (int ninputs, int noutputs); + + 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_SYMS_TO_METRICS_H */ diff --git a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i b/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i new file mode 100644 index 00000000..6a76a714 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,syms_to_metrics); + +gr_syms_to_metrics_sptr gr_make_syms_to_metrics +(gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision); + +class gr_syms_to_metrics : public gr_block +{ + gr_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit, + gr_feval_ff* pdf_fcn_1_bit, + int n_samples, + float min_sample, + float max_sample, + int sample_precision); +}; diff --git a/gr-error-correcting-codes/src/lib/libecc/Makefile.am b/gr-error-correcting-codes/src/lib/libecc/Makefile.am new file mode 100644 index 00000000..e2fa9eca --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/Makefile.am @@ -0,0 +1,60 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = mld . tests + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I.. + +noinst_LTLIBRARIES = libecc.la + +libecc_la_SOURCES = \ + code_convolutional_trellis.cc \ + code_metrics.cc \ + encoder.cc \ + encoder_convolutional.cc \ + encoder_convolutional_ic1_ic1.cc \ + encoder_turbo.cc \ + decoder.cc \ + decoder_viterbi.cc \ + decoder_viterbi_full_block.cc \ + decoder_viterbi_full_block_i1_ic1.cc + +noinst_HEADERS = \ + code_types.h code_metrics.h \ + code_convolutional_trellis.h \ + encoder.h encoder_turbo.h \ + encoder_convolutional.h \ + encoder_convolutional_ic1_ic1.h \ + decoder.h decoder_viterbi.h \ + decoder_viterbi_full_block.h \ + decoder_viterbi_full_block_i1_ic1.h + +# link the library against the c++ standard library +libecc_la_LIBADD = \ + mld/libmld.la \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +MOSTLYCLEANFILES = *.loT *~ + +CONFIG_CLEAN_FILES = *.in diff --git a/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc new file mode 100644 index 00000000..72b8adbf --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc @@ -0,0 +1,1028 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "code_convolutional_trellis.h" +#include +#include + +#define DO_TIME_THOUGHPUT 0 +#define DO_PRINT_DEBUG 1 +#define DO_PRINT_DEBUG_ENCODE 1 + +#include +#include + +static const int g_max_block_size_bits = 10000000; +static const int g_max_num_streams = 10; +static const int g_num_bits_per_byte = 8; + +/* + * sum_bits_mod2: + * sum the number of set bits, mod 2, for the output bit + */ + +char +code_convolutional_trellis::sum_bits_mod2 +(memory_t in_mem, + size_t max_memory) +{ + // there are faster ways to do this, but this works for now; could + // certainly do a single inline asm, which most processors provide + // to deal with summing the bits in an integer. + // this routine can be overridden by another method if desired. + + char t_out_bit = (char)(in_mem & 1); + for (size_t r = max_memory; r > 0; r--) { + in_mem >>= 1; + t_out_bit ^= ((char)(in_mem & 1)); + } + return (t_out_bit); +} + +void +code_convolutional_trellis::code_convolutional_trellis_init +(int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector& code_generators, + const std::vector* code_feedback, + bool do_termination, + int end_memory_state) +{ + // do error checking on the input arguments + + // make sure the block length makes sense + + if ((block_size_bits < 0) | (block_size_bits > g_max_block_size_bits)) { + std::cerr << "code_convolutional_trellis: " << + "Requested block length (" << block_size_bits << + " bits) must be between 0 and " << g_max_block_size_bits << + " bits, with 0 being a streaming encoder.\n"; + assert (0); + } + + // check to make sure the number of input streams makes sense + + if ((n_code_inputs <= 0) | (n_code_inputs > g_max_num_streams)) { + std::cerr << "code_convolutional_trellis: " << + "Requested number of input streams (" << + n_code_inputs << ") must be between 1 and " << + g_max_num_streams << ".\n"; + assert (0); + } + + // check to make sure the number of output streams makes sense + + if ((n_code_outputs <= 0) | (n_code_outputs > g_max_num_streams)) { + std::cerr << "code_convolutional_trellis: " << + "Requested number of output streams (" << + n_code_outputs << ") must be between 1 and " << + g_max_num_streams << ".\n"; + assert (0); + } + + // make sure the code_generator is the correct length + + if (code_generators.size () != + ((size_t)(n_code_inputs * n_code_outputs))) { + std::cerr << "code_convolutional_trellis: " << + "Number of code generator entries (" << code_generators.size () << + ") is not equal to the product of the number of input and output" << + " streams (" << (n_code_inputs * n_code_outputs) << ").\n"; + assert (0); + } + + // check for feedback (== NULL or not) + + d_do_feedback = (code_feedback != NULL); + + // create the class block variables + + d_block_size_bits = block_size_bits; + d_n_code_inputs = n_code_inputs; + d_n_code_outputs = n_code_outputs; + d_do_streaming = (block_size_bits == 0); + d_do_termination = (d_do_streaming == true) ? false : do_termination; + + if (DO_PRINT_DEBUG) { + std::cout << + "d_block_size_bits = " << d_block_size_bits << "\n" + "d_n_code_inputs = " << d_n_code_inputs << "\n" + "d_n_code_outputs = " << d_n_code_outputs << "\n" + "d_do_streaming = " << + ((d_do_streaming == true) ? "true" : "false") << "\n" + "d_do_termination = " << + ((d_do_termination == true) ? "true" : "false") << "\n" + "d_do_feedback = " << + ((d_do_feedback == true) ? "true" : "false") << "\n"; + } + + // allocate the vectors for doing the encoding. use memory_t (an + // interger type, at least 32 bits) bits to represent memory and the + // code, as it makes the operations quite simple the state vectors. + + // d_states is a "matrix" [#input by #outputs] containing indices + // to memory_t's; this is done to make feedback function properly, + // and doesn't effect the computation time for feedforward. The + // issue is that any code with the same feedback can use the same + // memory - thus reducing the actual number of memories required. + // These overlapping encoders will use the same actual memory, but + // given that there is no way to know a-priori where they are, use + // pointers over the full I/O matrix-space to make sure each I/O + // encoder uses the correct memory. + // reference the matrix using "maoi(i,o)" ... see .h file. + + // code generators (feedforward part) are [#inputs x #outputs], + // always - one for each I/O combination. + // reference the matrix using "maoi(i,o)" ... see .h file + + d_code_generators.assign (d_n_code_inputs * d_n_code_outputs, 0); + + // check the feedback for correctness, before anything else, since + // any feedback impacts the total # of delays in the encoder: + // without feedback, this is the sum of the individual delays max'ed + // over each input (if siao) or output (if soai). + + if (d_do_feedback == true) { + memory_t t_OR_all_feedback = 0; + for (size_t n = 0; n < d_n_code_outputs; n++) { + for (size_t m = 0; m < d_n_code_inputs; m++) { + memory_t t_in_code = (*code_feedback)[maoi(m,n)]; + + // OR this feedback with the overall, + // to check for any delays used at all + + t_OR_all_feedback |= t_in_code; + } + } + + // check to see if all the feedback entries were either "0" or "1", + // which implies no feedback; warn the user in that case and reset + // the do_feedback parameter to false. + + if ((t_OR_all_feedback | 1) == 1) { + std::cout << "code_convolutional_trellis: Warning: " << + "No feedback is required, ignoring feedback.\n"; + d_do_feedback = false; + } + } + + // copy over the FF code generators + + for (size_t n = 0; n < d_n_code_outputs; n++) + for (size_t m = 0; m < d_n_code_inputs; m++) + d_code_generators[maio(m,n)] = code_generators[maio(m,n)]; + + // check the input FF (and FB) code generators for correctness, and + // find the minimum memory configuration: combining via a single + // input / all outputs (SIAO), or a single output / all inputs (SOAI). + // + // for FF only, look over both the SOAI and SIAO realizations to + // find the minimum total # of delays, and use that realization + // (SOAI is preferred if total # of delays is equal, since it's much + // simpler to implement). + // + // for FB: + // for SIAO, check each input row (all outputs for a given input) + // for unique feedback; duplicate feedback entries can be + // combined into a single computation to reduce total # of delays. + // for SOAI: check each output column (all inputs for a given + // output) for unique feedback; duplicate feedback entries can + // be combined into a simgle computation (ditto). + + // check for SOAI all '0' output + + for (size_t n = 0; n < d_n_code_outputs; n++) { + memory_t t_all_inputs_zero = 0; + for (size_t m = 0; m < d_n_code_inputs; m++) + t_all_inputs_zero |= d_code_generators[maio(m,n)]; + + // check this input to see if all encoders were '0'; this might be + // OK for some codes, but warn the user just in case + + if (t_all_inputs_zero == 0) { + std::cout << "code_convolutional_trellis: Warning:" + "Output " << n+1 << " (of " << d_n_code_outputs << + ") will always be 0.\n"; + } + } + + // check for SIAO all '0' input + + for (size_t m = 0; m < d_n_code_inputs; m++) { + memory_t t_all_outputs_zero = 0; + for (size_t n = 0; n < d_n_code_outputs; n++) + t_all_outputs_zero |= d_code_generators[maio(m,n)]; + + // check this input to see if all encoders were '0'; this might be + // OK for some codes, but warn the user just in case + + if (t_all_outputs_zero == 0) { + std::cout << "code_convolutional_trellis: Warning:" + "Input " << m+1 << " (of " << d_n_code_inputs << + ") will not be used; all encoders are '0'.\n"; + } + } + + // check and compute memory requirements in order to determine which + // realization uses the least memory; create and save findings to + // not have to re-do these computations later. + + // single output, all inputs (SOAI) realization: + // reset the global parameters + + d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_n_delays.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_io_num.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_states_ndx.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_max_delay = d_total_n_delays = d_n_memories = 0; + d_do_encode_soai = true; + + for (size_t n = 0; n < d_n_code_outputs; n++) { + size_t t_max_mem = 0; + size_t t_n_unique_fb_prev_start = d_n_memories; + + for (size_t m = 0; m < d_n_code_inputs; m++) { + get_memory_requirements (m, n, t_max_mem, + t_n_unique_fb_prev_start, code_feedback); + if (d_do_feedback == false) { + d_states_ndx[maio(m,n)] = n; + } + } + if (d_do_feedback == false) { + // not feedback; just store memory requirements for this output + d_total_n_delays += t_max_mem; + d_n_delays[n] = t_max_mem; + d_io_num[n] = n; + } + } + if (d_do_feedback == false) { + d_n_memories = d_n_code_outputs; + } + + // store the parameters for SOAI + + std::vector t_fb_generators_soai, t_n_delays_soai, t_io_num_soai; + std::vector t_states_ndx_soai; + size_t t_max_delay_soai, t_total_n_delays_soai, t_n_memories_soai; + + t_fb_generators_soai.assign (d_code_feedback.size (), 0); + t_fb_generators_soai = d_code_feedback; + t_n_delays_soai.assign (d_n_delays.size (), 0); + t_n_delays_soai = d_n_delays; + t_io_num_soai.assign (d_io_num.size (), 0); + t_io_num_soai = d_io_num; + t_states_ndx_soai.assign (d_states_ndx.size (), 0); + t_states_ndx_soai = d_states_ndx; + + t_n_memories_soai = d_n_memories; + t_total_n_delays_soai = d_total_n_delays; + t_max_delay_soai = d_max_delay; + + // single input, all outputs (SIAO) realization + // reset the global parameters + + d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_n_delays.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_io_num.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_states_ndx.assign (d_n_code_inputs * d_n_code_outputs, 0); + d_max_delay = d_total_n_delays = d_n_memories = 0; + d_do_encode_soai = false; + + for (size_t m = 0; m < d_n_code_inputs; m++) { + size_t t_max_mem = 0; + size_t t_n_unique_fb_prev_start = d_n_memories; + + for (size_t n = 0; n < d_n_code_outputs; n++) { + get_memory_requirements (m, n, t_max_mem, + t_n_unique_fb_prev_start, code_feedback); + if (d_do_feedback == false) { + d_states_ndx[maio(m,n)] = m; + } + } + if (d_do_feedback == false) { + // not feedback; just store memory requirements for this output + d_total_n_delays += t_max_mem; + d_n_delays[m] = t_max_mem; + d_io_num[m] = m; + } + } + if (d_do_feedback == false) { + d_n_memories = d_n_code_inputs; + } + + if (DO_PRINT_DEBUG) { + std::cout << + " t_total_n_delays_siao = " << d_total_n_delays << "\n" + " t_total_n_delays_soai = " << t_total_n_delays_soai << "\n"; + } + + // pick which realization to use; soai is preferred since it's faster + // ... but unfortunately it's also less likely + + if (d_total_n_delays < t_total_n_delays_soai) { + // use siao + // nothing else to do, since the global variables already hold + // the correct values. + } else { + // use soai + d_do_encode_soai = true; + d_code_feedback = t_fb_generators_soai; + d_n_delays = t_n_delays_soai; + d_io_num = t_io_num_soai; + d_states_ndx = t_states_ndx_soai; + d_n_memories = t_n_memories_soai; + d_total_n_delays = t_total_n_delays_soai; + d_max_delay = t_max_delay_soai; + } + + // make sure the block length makes sense, #2 + + if ((d_do_streaming == false) & (d_block_size_bits < d_max_delay)) { + std::cerr << "code_convolutional_trellis: " << + "Requested block length (" << d_block_size_bits << + " bit" << (d_block_size_bits > 1 ? "s" : "") << + ") must be at least 1 memory length (" << d_max_delay << + " bit" << (d_max_delay > 1 ? "s" : "") << + " for this code) when doing block coding.\n"; + assert (0); + } + + // check & mask off the init states + + d_n_states = (1 << d_total_n_delays); + d_n_input_combinations = (1 << d_n_code_inputs); + + memory_t t_mask = (memory_t)((2 << d_total_n_delays) - 1); + + if (end_memory_state & t_mask) { + std::cout << "code_convolutional_trellis: Warning: " << + "provided end memory state out (" << end_memory_state << + ") is out of the state range [0, " << + (d_n_states-1) << "]; masking off the unused bits.\n"; + + end_memory_state &= t_mask; + } + + // create the max_mem_mask to be used in encoding + + d_max_mem_masks.assign (d_n_memories, 0); + + for (size_t m = 0; m < d_n_memories; m++) { + if (d_n_delays[m] == sizeof (memory_t) * g_num_bits_per_byte) + d_max_mem_masks[m] = ((memory_t) -1); + else + d_max_mem_masks[m] = (memory_t)((2 << (d_n_delays[m])) - 1); + } + + if (DO_PRINT_DEBUG) { + std::cout << + " d_n_memories = " << d_n_memories << "\n" + " d_total_n_delays = " << d_total_n_delays << "\n" + " d_max_delay = " << d_max_delay << "\n" + " d_do_encode_soai = " << + ((d_do_encode_soai == true) ? "true" : "false") << "\n"; + } + + // zero the memories + + d_memory.assign (d_n_memories, 0); + + // create the inputs and outputs buffers + + d_current_inputs.assign (d_n_code_inputs, 0); + d_current_outputs.assign (d_n_code_outputs, 0); + + // create the trellis for this code: + + create_trellis (); + + if (d_do_termination == true) { + + // create the termination lookup table + + create_termination_table (end_memory_state); + } +} + +void +code_convolutional_trellis::get_memory_requirements +(size_t m, // input number + size_t n, // output number + size_t& t_max_mem, + size_t& t_n_unique_fb_prev_start, + const std::vector* code_feedback) +{ + size_t t_in_code = d_code_generators[maio(m,n)]; + + // find the memory requirement for this code generator + + size_t t_code_mem_ff = max_bit_position (t_in_code); + + // check to see if this is bigger than any others in this row/column + + if (t_code_mem_ff > t_max_mem) + t_max_mem = t_code_mem_ff; + + if (DO_PRINT_DEBUG) { + std::cout << "c_g[" << m << "][" << n << "]{" << + maio(m,n) << "} = " << n2bs(t_in_code, 8) << + ", code_mem = " << t_code_mem_ff; + } + + // check the feedback portion, if it exists; + // for soai, check all the inputs which generate this output for + // uniqueness; duplicate entries can be combined to reduce total + // # of memories as well as required computations. + + if (d_do_feedback == true) { + if (DO_PRINT_DEBUG) { + std::cout << "\n"; + } + + // get the FB code; AND off the LSB for correct functionality + // during internal computations. + + t_in_code = ((memory_t)((*code_feedback)[maio(m,n)])); + t_in_code &= ((memory_t)(-2)); + + // find the memory requirement + + size_t t_code_mem_fb = max_bit_position (t_in_code); + + if (DO_PRINT_DEBUG) { + std::cout << "c_f[" << m << "][" << n << "]{" << + maio(m,n) << "} = " << n2bs(t_in_code, 8) << + ", code_mem = " << t_code_mem_fb; + } + + // check to see if this feedback is unique + + size_t l_n_unique_fb = t_n_unique_fb_prev_start; + while (l_n_unique_fb < d_n_memories) { + if (d_code_feedback[l_n_unique_fb] == t_in_code) + break; + l_n_unique_fb++; + } + if (l_n_unique_fb == d_n_memories) { + + // this is a unique feedback; + + d_code_feedback[l_n_unique_fb] = t_in_code; + d_n_delays[l_n_unique_fb] = t_code_mem_fb; + + // increase the number of unique feedback codes + + d_n_memories++; + + // store memory requirements for this output + + if (t_max_mem < t_code_mem_fb) + t_max_mem = t_code_mem_fb; + d_total_n_delays += t_max_mem; + + if (DO_PRINT_DEBUG) { + std::cout << ", uq # " << l_n_unique_fb << + ", tot_mem = " << d_total_n_delays; + } + } else { + // not a unique feedback, but the FF might require more memory + + if (DO_PRINT_DEBUG) { + std::cout << ", !uq # " << l_n_unique_fb << + " = " << d_n_delays[l_n_unique_fb]; + } + + if (d_n_delays[l_n_unique_fb] < t_code_mem_ff) { + d_total_n_delays += (t_code_mem_ff - d_n_delays[l_n_unique_fb]); + d_n_delays[l_n_unique_fb] = t_code_mem_ff; + + if (DO_PRINT_DEBUG) { + std::cout << " => " << d_n_delays[l_n_unique_fb] << + ", tot_mem = " << d_total_n_delays; + } + } + } + d_io_num[l_n_unique_fb] = ((d_do_encode_soai == true) ? n : m); + d_states_ndx[maio(m,n)] = l_n_unique_fb; + } + if (DO_PRINT_DEBUG) { + std::cout << "\n"; + } + if (d_max_delay < t_max_mem) + d_max_delay = t_max_mem; +} + +void +code_convolutional_trellis::create_trellis +() +{ + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << "c_t: # states = " << d_n_states << + ", d_n_input_combinations = " << d_n_input_combinations << "\n"; + } + + // first dimension is the number of states + + d_trellis.resize (d_n_states); + + // second dimension (one per first dimension) is the number of input + // combinations + + for (size_t m = 0; m < d_n_states; m++) { + d_trellis[m].resize (d_n_input_combinations); + for (size_t n = 0; n < d_n_input_combinations; n++) { + connection_t_ptr t_connection = &(d_trellis[m][n]); + t_connection->d_output_bits.resize (d_n_code_outputs); + } + } + + // fill in the trellis + + for (size_t m = 0; m < d_n_states; m++) { + for (size_t n = 0; n < d_n_input_combinations; n++) { + connection_t_ptr t_connection = &(d_trellis[m][n]); + encode_single (m, n, t_connection->d_to_state, + t_connection->d_output_bits); + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << "set d_t[" << n2bs(m,d_total_n_delays) << "][" << + n2bs(n,d_n_code_inputs) << "] : to_st = " << + n2bs(t_connection->d_to_state,d_total_n_delays) << "\n"; + } + } + } +} + +void +code_convolutional_trellis::demux_state +(memory_t in_state, + std::vector& memories) +{ + // de-mux bits for the given memory state; + // copy them into the provided vector; + // assumes state bits start after the LSB (not at &1) + + memories.resize (d_n_memories); + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << "in_st = " << n2bs(in_state,d_total_n_delays) << " ->\n"; + } + for (size_t m = 0; m < d_n_memories; m++) { + memories[m] = (in_state << 1) & d_max_mem_masks[m]; + in_state >>= d_n_delays[m]; + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << " #d = " << d_n_delays[m] << ", mem[" << m << "] = " << + n2bs(memories[m], d_n_delays[m]+1) << "\n"; + } + } +} + +memory_t +code_convolutional_trellis::mux_state +(const std::vector& memories) +{ + // mux bits for the given memory states in d_memory + // assumes state bits start after the LSB (not at &1) + memory_t t_state = 0; + size_t shift = 0; + for (size_t m = 0; m < d_n_memories; m++) { + t_state |= (memories[m] >> 1) << shift; + shift += d_n_delays[m]; + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << " #d = " << d_n_delays[m] << ", mem[" << m << "] = " << + n2bs(memories[m], d_n_delays[m]+1) << " -> st = " << + n2bs(t_state, d_total_n_delays) << "\n"; + } + } + return (t_state); +} + +void +code_convolutional_trellis::demux_inputs +(memory_t inputs, + std::vector& in_vec) +{ + for (size_t m = 0; m < d_n_code_inputs; m++, inputs >>= 1) { + in_vec[m] = (char)(inputs & 1); + } +} + +memory_t +code_convolutional_trellis::mux_inputs +(const std::vector& in_vec) +{ + size_t bit_shift = 0; + memory_t inputs = 0; + for (size_t m = 0; m < in_vec.size(); m++, bit_shift++) { + inputs |= (((memory_t)(in_vec[m]&1)) << bit_shift); + } + return (inputs); +} + +void +code_convolutional_trellis::encode_single +(memory_t in_state, + size_t inputs, + memory_t& out_state, + std::vector& out_bits) +{ + // set input parameters + + demux_state (in_state, d_memory); + demux_inputs (inputs, d_current_inputs); + + // call the correct function to do the work + + if (d_do_encode_soai == true) { + if (d_do_feedback == true) { + encode_single_soai_fb (); + } else { + encode_single_soai (); + } + } else { + if (d_do_feedback == true) { + encode_single_siao_fb (); + } else { + encode_single_siao (); + } + } + + // retrieve the output parameters + + out_state = mux_state (d_memory); + out_bits = d_current_outputs; +} + +void +code_convolutional_trellis::encode_lookup +(memory_t& state, + const std::vector& inputs, + std::vector& out_bits) +{ + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << "using d_t[" << state << "][" << mux_inputs(inputs) << + "] = "; + std::cout.flush (); + } + + connection_t_ptr t_connection = &(d_trellis[state][mux_inputs(inputs)]); + + if (DO_PRINT_DEBUG_ENCODE) { + std::cout << t_connection << ": to_state = " + << t_connection->d_to_state << "\n"; + } + + state = t_connection->d_to_state; + out_bits = t_connection->d_output_bits; +} + +void +code_convolutional_trellis::get_termination_inputs +(memory_t term_start_state, + size_t bit_num, + std::vector& inputs) +{ + inputs.resize (d_n_code_inputs); + for (size_t m = 0; m < d_n_code_inputs; m++) { + inputs[m] = ((d_term_inputs[term_start_state][m]) >> bit_num) & 1; + } +} + +void +code_convolutional_trellis::create_termination_table +(memory_t end_memory_state) +{ + // somewhat involved, but basically start with the terminating state + // and work backwards d_total_n_delays, then create a + // std::vector of length n_states, once per path required + // to get from the given state to the desired termination state. + // + // each entry represents the bits required to terminate that + // particular state, listed in order from LSB for the first input + // bit to the MSB for the last input bit. + +#if 0 + // create a reverse trellis + // it's temporary, just for doing the termination, so just do it locally + + trellis_t t_trellis; + + // first dimension is the number of states + + t_trellis.resize (d_n_states); + + // second dimension (one per first dimension) is the number of input + // combinations + + for (size_t m = 0; m < d_n_states; m++) { + t_trellis[m].resize (d_n_input_combinations); + } + + std::vector outputs (d_n_code_outputs); + memory_t to_state; + + // fill in the trellis + + for (memory_t m = 0; m < d_n_states; m++) { + for (memory_t n = 0; n < d_n_input_combinations; n++) { + encode_single (m, n, to_state, outputs); + + connection_t_ptr t_connection = &(t_trellis[to_state][n]); + t_connection->d_to_state = m; +#if 0 + t_connection->d_output_bits.resize (d_n_code_outputs); + t_connection->d_output_bits = outputs; +#endif + } + } + + // create the output vectors + + term_input_t t_term_inputs; + t_term_inputs.resize (d_n_states); + for (size_t m = 0; m < d_n_states; m++) { + t_term_inputs[m].assign (d_n_code_inputs, 0); + } + + + std::vector t_used_states; + t_used_states.assign (d_n_states, 0); + + // setup the first state + + t_states[0] = end_memory_state; + size_t n_states = 1; + + for (size_t m = 0; m < d_total_n_delays; m++) { + for (size_t n = 0; n < n_states; n++) { + memory_t t_end_state = t_states[n]; + for (size_t p = 0; p < d_n_code_inputs; p++) { + connection_t_ptr t_connection = &(t_trellis[t_end_state][p]); + memory_t_ptr t_mem = &(t_term_inputs[t_end_state][p]); + + + + + } + } + + t_inputs[0] = t_trellis +#endif +} + +void +code_convolutional_trellis::encode_single_soai +() +{ + // single-output, all inputs; no feedback + + if (DO_PRINT_DEBUG) { + std::cout << "Starting encode_single_soai.\n"; + } + + // shift memories down by 1 bit to make room for feedback; no + // masking required. + + for (size_t p = 0; p < d_n_memories; p++) { + if (DO_PRINT_DEBUG) { + std::cout << "m_i[" << p << "] = " << + n2bs(d_memory[p], 1+d_n_delays[p]); + } + + d_memory[p] >>= 1; + + if (DO_PRINT_DEBUG) { + std::cout << " >>= 1 -> " << + n2bs(d_memory[p], 1+d_n_delays[p]) << "\n"; + } + } + + // for each input bit, if that bit's a '1', then XOR the code + // generators into the correct state's memory. + + for (size_t m = 0; m < d_n_code_inputs; m++) { + if (DO_PRINT_DEBUG) { + std::cout << "c_i[" << m << "] = " << + n2bs(d_current_inputs[m],1); + } + if (d_current_inputs[m] == 1) { + if (DO_PRINT_DEBUG) { + std::cout << "\n"; + } + for (size_t n = 0; n < d_n_code_outputs; n++) { + if (DO_PRINT_DEBUG) { + std::cout << "m_i[s_ndx[" << m << "][" << n << "] == " << + d_states_ndx[maio(m,n)] << "] = " << + n2bs(d_memory[d_states_ndx[maio(m,n)]], + 1+d_n_delays[d_states_ndx[maio(m,n)]]); + } + + d_memory[d_states_ndx[maio(m,n)]] ^= d_code_generators[maio(m,n)]; + + if (DO_PRINT_DEBUG) { + std::cout << " ^= c_g[][] == " << + n2bs(d_code_generators[maio(m,n)], + 1+d_n_delays[d_states_ndx[maio(m,n)]]) << + " -> " << n2bs(d_memory[d_states_ndx[maio(m,n)]], + 1+d_n_delays[d_states_ndx[maio(m,n)]]) << "\n"; + } + } + } else if (DO_PRINT_DEBUG) { + std::cout << " ... nothing to do\n"; + } + } + + for (size_t p = 0; p < d_n_code_outputs; p++) { + d_current_outputs[p] = 0; + } + + // create the output bits, by XOR'ing the individual unique + // memory(ies) into the correct output bit + + for (size_t p = 0; p < d_n_memories; p++) { + d_current_outputs[d_io_num[p]] ^= ((char)(d_memory[p] & 1)); + } + + if (DO_PRINT_DEBUG) { + std::cout << "ending encode_single_soai.\n"; + } +} + +void +code_convolutional_trellis::encode_single_soai_fb +() +{ + // single-output, all inputs; with feedback + + if (DO_PRINT_DEBUG) { + std::cout << "Starting encode_single_soai_fb.\n"; + } + + // shift memories down by 1 bit to make room for feedback; no + // masking required. + + for (size_t p = 0; p < d_n_memories; p++) { + if (DO_PRINT_DEBUG) { + std::cout << "m_i[" << p << "] = " << d_memory[p]; + } + + d_memory[p] >>= 1; + + if (DO_PRINT_DEBUG) { + std::cout << " -> " << d_memory[p] << "\n"; + } + } + + // for each input bit, if that bit's a '1', then XOR the code + // generators into the correct state's memory. + + for (size_t m = 0; m < d_n_code_inputs; m++) { + if (d_current_inputs[m] == 1) { + for (size_t n = 0; n < d_n_code_outputs; n++) { + d_memory[d_states_ndx[maio(m,n)]] ^= d_code_generators[maio(m,n)]; + } + } + } + + for (size_t p = 0; p < d_n_code_outputs; p++) { + d_current_outputs[p] = 0; + } + + // create the output bits, by XOR'ing the individual unique + // memory(ies) into the correct output bit + + for (size_t p = 0; p < d_n_memories; p++) { + d_current_outputs[d_io_num[p]] ^= ((char)(d_memory[p] & 1)); + } + + // now that the output bits are fully created, XOR the FB back + // into the memories; the feedback bits have the LSB (&1) masked + // off already so that it doesn't contribute. + + for (size_t p = 0; p < d_n_memories; p++) { + if (d_current_outputs[d_io_num[p]] == 1) { + d_memory[p] ^= d_code_feedback[p]; + } + } + + if (DO_PRINT_DEBUG) { + std::cout << "ending encode_single_soai.\n"; + } +} + +void +code_convolutional_trellis::encode_single_siao +() +{ + // single input, all outputs; no feedback + + if (DO_PRINT_DEBUG) { + std::cout << "starting encode_single_siao.\n"; + } + + // update the memories with the current input bits; + + // for each unique memory (1 per input), shift the delays and mask + // off the extra high bits; then XOR in the input bit. + + for (size_t p = 0; p < d_n_memories; p++) { + d_memory[p] |= ((memory_t)(d_current_inputs[d_io_num[p]])); + } + + // create the output bits: for each output, loop over all inputs, + // find the output bits for each encoder, and XOR each together + // then sum (would usually be sum then XOR, but they're mutable in + // base-2 and it's faster this way). + + for (size_t n = 0; n < d_n_code_outputs; n++) { + memory_t t_mem = 0; + for (size_t m = 0; m < d_n_code_inputs; m++) { + t_mem ^= ((d_memory[d_states_ndx[maio(m,n)]]) & + d_code_generators[maio(m,n)]); + } + d_current_outputs[n] = sum_bits_mod2 (t_mem, d_max_delay); + } + + // post-shift & mask the memory to guarantee that output + // state is in the correct bit positions (1 up, not the LSB) + + for (size_t p = 0; p < d_n_memories; p++) { + d_memory[p] = (d_memory[p] << 1) & d_max_mem_masks[p]; + } + + if (DO_PRINT_DEBUG) { + std::cout << "ending encode_single_siao.\n"; + } +} + +void +code_convolutional_trellis::encode_single_siao_fb +() +{ + // single input, all outputs; with feedback + + if (DO_PRINT_DEBUG) { + std::cout << "starting encode_single_siao_fb.\n"; + } + + // update the memories with the current input bits; + + // for each unique memory (1 per input), shift the delays and mask + // off the extra high bits; then XOR in the input bit. + // with FB: find the feedback bit, and OR it into the input bit's slot; + + for (size_t p = 0; p < d_n_memories; p++) { + memory_t t_mem = d_memory[p]; + memory_t t_fb = t_mem & d_code_feedback[p]; + char t_fb_bit = sum_bits_mod2 (t_fb, d_max_delay); + t_mem |= ((memory_t) t_fb_bit); + d_memory[p] = t_mem ^ ((memory_t)(d_current_inputs[d_io_num[p]])); + } + + // create the output bits: for each output, loop over all inputs, + // find the output bits for each encoder, and XOR each together + // then sum (would usually be sum then XOR, but they're mutable in + // base-2 and it's faster this way). + + for (size_t n = 0; n < d_n_code_outputs; n++) { + memory_t t_mem = 0; + for (size_t m = 0; m < d_n_code_inputs; m++) { + t_mem ^= ((d_memory[d_states_ndx[maio(m,n)]]) & + d_code_generators[maio(m,n)]); + } + d_current_outputs[n] = sum_bits_mod2 (t_mem, d_max_delay); + } + + // post-shift & mask the memory to guarantee that output + // state is in the correct bit positions (1 up, not the LSB) + + for (size_t p = 0; p < d_n_memories; p++) { + d_memory[p] = (d_memory[p] << 1) & d_max_mem_masks[p]; + } + + if (DO_PRINT_DEBUG) { + std::cout << "ending encode_loop_siao_fb.\n"; + } +} diff --git a/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h new file mode 100644 index 00000000..205ccc03 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h @@ -0,0 +1,372 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_CODE_CONVOLUTIONAL_TRELLIS_H +#define INCLUDED_CODE_CONVOLUTIONAL_TRELLIS_H + +#include "code_types.h" +#include + +/* + * connection_t: describes an output connection from the current + * time-bit memory state to the next time-bit memory state + * + * d_to_state: memory configuration of the "to" state + * + * d_output_bits: the output bits for this connection + */ + +typedef struct connection_t { + memory_t d_to_state; + std::vector d_output_bits; +} connection_t, *connection_t_ptr; + +/* + * trellis_t: describes a single set of trellis connections, from a + * time-bit to the next, forward transitions only + * + * This is a 2d "matrix", where the first dimention is the starting + * memory state, and the second is the (combined) input as an + * integer: e.g. for a 2 input code, if I1 = 0 and I2 = 1, then + * the combined input is the "number" found by appending I2 and I1 + * together, in this case 10b = 3. + * + * The trellis is used to lookup information: given a starting state + * and inputs, return the output bits and next state. + */ + +typedef std::vector > trellis_t, *trellis_t_ptr; + +class code_convolutional_trellis +{ +/*! + * class code_convolutional_trellis + * + * Create a convolutional code trellis structure, but encoding, + * decoding, determining termination transitions, and anything else + * which might be useful. + * + * block_size_bits: if == 0, then do streaming encoding ("infinite" + * trellis); otherwise this is the block size in bits to encode + * before terminating the trellis. This value -does not- include + * any termination bits. + * + * n_code_inputs: + * n_code_outputs: + * code_generator: vector of integers (32 bit) representing the code + * to be implemented. E.g. "4" in binary is "100", which would be + * "D^2" for code generation. "6" == 110b == "D^2 + D" + * ==> The vector is listed in order for each output stream, so if there + * are 2 input streams (I1, I2) [specified in "n_code_inputs"] + * and 2 output streams (O1, O2) [specified in "n_code_outputs"], + * then the vector would be the code generator for: + * [I1->O1, I2->O1, I1->O2, I2->O2] + * with each element being an integer representation of the code. + * The "octal" representation is used frequently in the literature + * (e.g. [015, 06] == [1101, 0110] in binary) due to its close + * relationship with binary (each number is 3 binary digits) + * ... but any integer representation will suffice. + * + * do_termination: valid only if block_size_bits != 0, and defines + * whether or not to use trellis termination. Default is to use + * termination when doing block coding. + * + * start_memory_state: when starting a new block, the starting memory + * state to begin encoding; there will be a helper function to + * assist in creating this value for a given set of inputs; + * default is the "all zero" state. + * + * end_memory_state: when terminating a block, the ending memory + * state to stop encoding; there will be a helper function to + * assist in creating this value for a given set of inputs; + * default is the "all zero" state. + */ + +public: + inline code_convolutional_trellis + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + bool do_termination = true, + int end_memory_state = 0) + {code_convolutional_trellis_init (block_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + NULL, + do_termination, + end_memory_state);}; + +/*! + * Encoder with feedback. + * + * code_feedback: vector of integers (32 bit) representing the code + * feedback to be implemented (same as for the code_generator). + * For this feedback type, the LSB ("& 1") is ignored (set to "1" + * internally, since it's always 1) ... this (effectively) + * represents the input bit for the given encoder, without which + * there would be no encoding! Each successive higher-order bit + * represents the output of that delay block; for example "6" == + * 110b == "D^2 + D" means use the current input bit + the output + * of the second delay block. Listing order is the same as for + * the code_generator. + */ + + inline code_convolutional_trellis + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + const std::vector &code_feedback, + bool do_termination = true, + int end_memory_state = 0) + {code_convolutional_trellis_init (block_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + &code_feedback, + do_termination, + end_memory_state);}; + + virtual ~code_convolutional_trellis () {}; + +/* for remote access to internal info */ + + inline size_t block_size_bits () {return (d_block_size_bits);}; + inline size_t n_code_inputs () {return (d_n_code_inputs);}; + inline size_t n_code_outputs () {return (d_n_code_outputs);}; + inline const bool do_termination () {return (d_do_termination);}; + inline const bool do_feedback () {return (d_do_feedback);}; + inline const bool do_streaming () {return (d_do_streaming);}; + inline const size_t total_n_delays () {return (d_total_n_delays);}; + + virtual char sum_bits_mod2 (memory_t in_mem, size_t max_memory); + void get_termination_inputs (memory_t term_start_state, + size_t bit_num, + std::vector& inputs); + + void encode_lookup (memory_t& state, + const std::vector& inputs, + std::vector& out_bits); + + void demux_state (memory_t in_state, std::vector& memories); + memory_t mux_state (const std::vector& memories); + void demux_inputs (memory_t inputs, std::vector& in_vec); + memory_t mux_inputs (const std::vector& in_vec); + +protected: +#if 0 +/* + * state_get_from(v,i,k): use to retrieve a given bit-memory state, + * from the inputs: + * + * memory_t v: the value from which to retrieve the given state + * size_t i: for which input stream (0 to #I-1) + * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2) + */ + + inline memory_t state_get_from (memory_t v, + size_t i, + size_t k) + {return (((v)>>((i)*(k)))&((1<<(k))-1));}; + +/* + * state_add_to(s,v,i,k): use to create a given bit-memory state, + * from the inputs: + * + * memory_t s: the state value to modify + * memory_t v: value to set the state to for this input + * size_t i: for which input stream (0 to #I-1) + * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2) + */ + + inline void state_add_to (memory_t s, + memory_t v, + size_t i, + size_t k) + {(s)|=(((v)&((1<<(k))-1))<<((i)*(k)));}; +#endif + +/* + * maio(i,o): matrix access into a vector, knowing the # of code + * outputs (from inside the class). References into a vector with + * code inputs ordered by code output. + * + * 'i' is the 1st dimension - faster memory - the code input + * 'o' is the 2nd dimension - slower memory - the code output + * + * returns ((o*n_code_inputs) + i) + */ + + inline size_t maio(size_t i, size_t o) {return ((o*d_n_code_inputs) + i);}; + +/* + * maoi(i,o): matrix access into a vector, knowing the # of code + * inputs (from inside the class). References into a vector with + * code outputs ordered by code input. + * + * 'o' is the 1st dimension - faster memory - the code output + * 'i' is the 2nd dimension - slower memory - the code input + * + * returns ((i*n_code_outputs) + o) + */ + + inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_outputs) + o);}; + +/* + * max_bit_position (x): returns the bit-number of the highest "1" bit + * in the provided value, such that the LSB would return 0 and the MSB + * of a long would return 31. + */ + + inline size_t max_bit_position (memory_t x) + { + size_t t_code_mem = 0; + memory_t t_in_code = x >> 1; + while (t_in_code != 0) { + t_in_code >>= 1; + t_code_mem++; + } + + return (t_code_mem); + } + + // methods defined in this class + + void code_convolutional_trellis_init + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector& code_generators, + const std::vector* code_generators, + bool do_termination, + int end_memory_state); + + void create_trellis (); + void create_termination_table (memory_t end_memory_state); + void encode_single (memory_t in_state, + memory_t inputs, + memory_t& out_state, + std::vector& out_bits); + virtual void encode_single_soai (); + virtual void encode_single_siao (); + virtual void encode_single_soai_fb (); + virtual void encode_single_siao_fb (); + + void get_memory_requirements (size_t m, + size_t n, + size_t& t_max_mem, + size_t& t_n_unique_fb_prev_start, + const std::vector* code_feedback); + + // variables + + size_t d_block_size_bits, d_n_code_outputs; + size_t d_n_code_inputs, d_n_input_combinations; + bool d_do_streaming, d_do_termination, d_do_feedback, d_do_encode_soai; + + // "max_delay" is the max # of delays for all unique generators (ff and fb), + // needed to determine (e.g.) termination + + size_t d_max_delay; + + // "n_memories" is the number of unique memories as determined by + // either the feedforward or feedback generators (not both). For + // FF, this number equals either the number of code inputs (for + // SIAO) or outputs (for SOAI). + + size_t d_n_memories; + + // "total_n_delays" is the total # of delays, needed to determine the + // # of states in the decoder + // "n_states" = (2^n_delays) - 1 .. the number of memory states + + size_t d_total_n_delays, d_n_states; + + // "code generators" are stored internally in "maXY(i,o)" order this + // allows for looping over all a single output and computing all + // input parts sequentially. + + std::vector d_code_generators; + + // "feedback" are found as "d_n_memories" unique entries, and stored + // in at most 1 entry per I/O combination. Listed in the same order + // as "d_io_num" entries show. + + std::vector d_code_feedback; + + // "n_delays" is a vector, the number of delays for the FB generator + // in the same [] location; also relates directly to the + // "max_mem_masks" in the same [] location. + + std::vector d_n_delays; + + // "io_num" is a vector, mapping which FB in SIAO goes with which + // input, or which FB in SOAI goes with which output + + std::vector d_io_num; + + // "max_mem_masks" are the memory masks, one per unique FB for SIAO; + // otherwise not used. + + std::vector d_states_ndx; + + // "memory" are the actual stored delay bits, one memory for each + // unique FF or FB code generator; + // interpreted w/r.t. the actual FF and FB code generators and + // SOAI / SIAO realization; + + std::vector d_max_mem_masks; + + // "states_ndx" is a "matrix" whose contents are the indices into + // the "io_num" vector, telling which input goes with which + // state; uses the same "maXY(i,o)" as the code generators. + + std::vector d_memory; + + // "term_inputs" are the inputs required to terminate the trellis - + // interpreted w/r.t. the actual FF and FB code generators and + // SOAI / SIAO realization; + // first dimension is the memory state #; + // second dimension is the input stream #; + // bits are packed, with the first input being the LSB and the last + // input being closest to the MSB. + + typedef std::vector > term_input_t; + term_input_t d_term_inputs; + + // "inputs" are the current input bits, in the LSB (&1) of each "char" + + std::vector d_current_inputs; + + // "outputs" are the current output bits, in the LSB (&1) of each "char" + + std::vector d_current_outputs; + + // "trellis" is the single-stage memory state transition ("trellis") + // representation for this code; forward paths only + + trellis_t d_trellis; +}; + +#endif /* INCLUDED_CODE_CONVOLUTIONAL_TRELLIS_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc b/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc new file mode 100644 index 00000000..39245086 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc @@ -0,0 +1,445 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +code_metric_ff::code_metric_ff +(pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample) +{ + if (n_samples < 2) { + fprintf (stderr, "code_metric_f32:: n_samples " + "must be at least 2.\n"); + assert (0); + } + if (min_sample >= max_sample) { + fprintf (stderr, "code_metric_f32:: min_sample must be " + "less than max_sample.\n"); + assert (0); + } + if (! pdf_fcn_0_bit) { + fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (! pdf_fcn_1_bit) { + fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + + d_n_samples = n_samples; + d_max_sample = max_sample; + d_min_sample = min_sample; + d_delta = (max_sample - min_sample) / (n_samples - 1); + d_pdf_fcn_0_bit = pdf_fcn_0_bit; + d_pdf_fcn_1_bit = pdf_fcn_1_bit; + d_metric_table_0_bit.assign (n_samples, 0); + d_metric_table_1_bit.assign (n_samples, 0); + + pdf_fcn_io_t l_val = min_sample; + for (size_t m = 0; m < n_samples; m++) { + d_metric_table_0_bit[m] = logf ((*pdf_fcn_0_bit)(l_val)); + d_metric_table_1_bit[m] = logf ((*pdf_fcn_1_bit)(l_val)); + l_val += d_delta; + } +} + +void code_metric_ff::lookup +(pdf_fcn_io_t sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + if (sym <= d_min_sample) { + *l_bit_0 = d_metric_table_0_bit[0]; + *l_bit_1 = d_metric_table_1_bit[0]; + return; + } + if (sym >= d_max_sample) { + *l_bit_0 = d_metric_table_0_bit.back (); + *l_bit_1 = d_metric_table_1_bit.back (); + return; + } + + size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta); + *l_bit_0 = d_metric_table_0_bit[l_ndx]; + *l_bit_1 = d_metric_table_1_bit[l_ndx]; +} + +void code_metric_ff::convert +(size_t n_syms, + pdf_fcn_io_t* sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + for (size_t m = n_syms; m > 0; m--) + lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++); +} + +code_metric_fl::code_metric_fl +(pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample, + int sample_precision) +{ + if (n_samples < 2) { + fprintf (stderr, "code_metric_fl:: n_samples " + "must be at least 2.\n"); + assert (0); + } + if (min_sample >= max_sample) { + fprintf (stderr, "code_metric_fl:: min_sample must be " + "less than max_sample.\n"); + assert (0); + } + if (! pdf_fcn_0_bit) { + fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (! pdf_fcn_1_bit) { + fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (sample_precision < 16 || sample_precision > 32) { + fprintf (stderr, "code_metric_fl:: sample_precision must be " + "between 16 and 32 for this class.\n"); + assert (0); + } + + d_sample_precision = sample_precision; + d_n_samples = n_samples; + d_max_sample = max_sample; + d_min_sample = min_sample; + d_delta = (max_sample - min_sample) / (n_samples - 1); + d_pdf_fcn_0_bit = pdf_fcn_0_bit; + d_pdf_fcn_1_bit = pdf_fcn_1_bit; + d_metric_table_0_bit.assign (n_samples, 0); + d_metric_table_1_bit.assign (n_samples, 0); + + // get the scale factor for converting from float to sample_precision + // maps: + // logf (pdf_fcn_0_bit->eval (d_min_sample)) -> l_min_map + // logf (pdf_fcn_0_bit->eval (d_max_sample)) -> l_max_map + + metric_t l_min_map = - (1 << (sample_precision - 1)); + + pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample)); + pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample)); + pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) / + (l_max_log_val_0 - l_min_log_val_0)); + pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample)); + pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample)); + pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) / + (l_max_log_val_1 - l_min_log_val_1)); + + pdf_fcn_io_t l_val = d_min_sample; + for (size_t m = 0; m < d_n_samples; m++) { + d_metric_table_0_bit[m] = + (metric_t) roundf (((pdf_fcn_io_t) l_min_map) + + (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) - + l_min_log_val_0))); + d_metric_table_1_bit[m] = + (metric_t) roundf (((pdf_fcn_io_t) l_min_map) + + (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) - + l_min_log_val_1))); + l_val += d_delta; + } +} + +void code_metric_fl::lookup +(pdf_fcn_io_t sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + if (sym <= d_min_sample) { + *l_bit_0 = d_metric_table_0_bit[0]; + *l_bit_1 = d_metric_table_1_bit[0]; + return; + } + if (sym >= d_max_sample) { + *l_bit_0 = d_metric_table_0_bit.back (); + *l_bit_1 = d_metric_table_1_bit.back (); + return; + } + + size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta); + *l_bit_0 = d_metric_table_0_bit[l_ndx]; + *l_bit_1 = d_metric_table_1_bit[l_ndx]; +} + +void code_metric_fl::convert +(size_t n_syms, + pdf_fcn_io_t* sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + for (size_t m = n_syms; m > 0; m--) + lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++); +} + +code_metric_fs::code_metric_fs +(pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample, + int sample_precision) +{ + if (n_samples < 2) { + fprintf (stderr, "code_metric_fs:: n_samples " + "must be at least 2.\n"); + assert (0); + } + if (min_sample >= max_sample) { + fprintf (stderr, "code_metric_fs:: min_sample must be " + "less than max_sample.\n"); + assert (0); + } + if (! pdf_fcn_0_bit) { + fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (! pdf_fcn_1_bit) { + fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (sample_precision < 9 || sample_precision > 16) { + fprintf (stderr, "code_metric_fs:: sample_precision must be " + "between 9 and 16 for this class.\n"); + assert (0); + } + + d_sample_precision = sample_precision; + d_n_samples = n_samples; + d_max_sample = max_sample; + d_min_sample = min_sample; + d_delta = (max_sample - min_sample) / (n_samples - 1); + d_pdf_fcn_0_bit = pdf_fcn_0_bit; + d_pdf_fcn_1_bit = pdf_fcn_1_bit; + d_metric_table_0_bit.assign (n_samples, 0); + d_metric_table_1_bit.assign (n_samples, 0); + + // get the scale factor for converting from float to sample_precision + // maps: + // logf (pdf_fcn_0_bit->eval (d_min_sample)) -> l_min_map + // logf (pdf_fcn_0_bit->eval (d_max_sample)) -> l_max_map + + metric_t l_min_map = - (1 << (sample_precision - 1)); + + pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample)); + pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample)); + pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) / + (l_max_log_val_0 - l_min_log_val_0)); + pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample)); + pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample)); + pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) / + (l_max_log_val_1 - l_min_log_val_1)); + + pdf_fcn_io_t l_val = d_min_sample; + for (size_t m = 0; m < d_n_samples; m++) { + d_metric_table_0_bit[m] = + (metric_t) roundf (((pdf_fcn_io_t) l_min_map) + + (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) - + l_min_log_val_0))); + d_metric_table_1_bit[m] = + (metric_t) roundf (((pdf_fcn_io_t) l_min_map) + + (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) - + l_min_log_val_1))); + l_val += d_delta; + } +} + +void code_metric_fs::lookup +(pdf_fcn_io_t sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + if (sym <= d_min_sample) { + *l_bit_0 = d_metric_table_0_bit[0]; + *l_bit_1 = d_metric_table_1_bit[0]; + return; + } + if (sym >= d_max_sample) { + *l_bit_0 = d_metric_table_0_bit.back (); + *l_bit_1 = d_metric_table_1_bit.back (); + return; + } + + size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta); + *l_bit_0 = d_metric_table_0_bit[l_ndx]; + *l_bit_1 = d_metric_table_1_bit[l_ndx]; +} + +void code_metric_fs::convert +(size_t n_syms, + pdf_fcn_io_t* sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + for (size_t m = n_syms; m > 0; m--) + lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++); +} + +code_metric_fb::code_metric_fb +(pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample, + int sample_precision) +{ + if (n_samples < 2) { + fprintf (stderr, "code_metric_fb:: n_samples " + "must be at least 2.\n"); + assert (0); + } + if (min_sample >= max_sample) { + fprintf (stderr, "code_metric_fb:: min_sample must be " + "less than max_sample.\n"); + assert (0); + } + if (! pdf_fcn_0_bit) { + fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (! pdf_fcn_1_bit) { + fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be " + "a non-null pointer to function.\n"); + assert (0); + } + if (sample_precision < 1 || sample_precision > 8) { + fprintf (stderr, "code_metric_fb:: sample_precision must be " + "between 1 and 8 for this class.\n"); + assert (0); + } + + d_sample_precision = sample_precision; + d_n_samples = n_samples; + d_max_sample = max_sample; + d_min_sample = min_sample; + d_delta = (max_sample - min_sample) / (n_samples - 1); + d_pdf_fcn_0_bit = pdf_fcn_0_bit; + d_pdf_fcn_1_bit = pdf_fcn_1_bit; + d_metric_table_0_bit.assign (n_samples, 0); + d_metric_table_1_bit.assign (n_samples, 0); + + // get the scale factor for converting from float to sample_precision + // maps: + // logf (pdf_fcn_0_bit->eval (d_min_sample)) -> l_min_map + // logf (pdf_fcn_0_bit->eval (d_max_sample)) -> l_max_map + + metric_t l_min_map = - (1 << (sample_precision - 1)); + + pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample)); + pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample)); + pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) / + (l_max_log_val_0 - l_min_log_val_0)); + pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample)); + pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample)); + pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) / + (l_max_log_val_1 - l_min_log_val_1)); + + pdf_fcn_io_t l_val = d_min_sample; + for (size_t m = 0; m < d_n_samples; m++) { + d_metric_table_0_bit[m] = + (metric_t) roundf (((pdf_fcn_io_t) l_min_map) + + (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) - + l_min_log_val_0))); + d_metric_table_1_bit[m] = + (metric_t) roundf (((pdf_fcn_io_t) l_min_map) + + (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) - + l_min_log_val_1))); + l_val += d_delta; + } +} + +void code_metric_fb::lookup +(pdf_fcn_io_t sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + if (sym <= d_min_sample) { + *l_bit_0 = d_metric_table_0_bit[0]; + *l_bit_1 = d_metric_table_1_bit[0]; + return; + } + if (sym >= d_max_sample) { + *l_bit_0 = d_metric_table_0_bit.back (); + *l_bit_1 = d_metric_table_1_bit.back (); + return; + } + + size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta); + *l_bit_0 = d_metric_table_0_bit[l_ndx]; + *l_bit_1 = d_metric_table_1_bit[l_ndx]; +} + +void code_metric_fb::convert +(size_t n_syms, + pdf_fcn_io_t* sym, + void* bit_0, + void* bit_1) +{ + metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0; + metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1; + + for (size_t m = n_syms; m > 0; m--) + lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/code_metrics.h b/gr-error-correcting-codes/src/lib/libecc/code_metrics.h new file mode 100644 index 00000000..9530dd64 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/code_metrics.h @@ -0,0 +1,155 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_CODE_METRIC_H +#define INCLUDED_CODE_METRIC_H + +#include +#include + +class code_metrics +{ +public: + typedef float pdf_fcn_io_t; + + code_metrics () {}; + virtual ~code_metrics () {}; + +// lookup() returns either a float, or a sign-extended +// 'sample_precision'-bit integer value. + + virtual void lookup (pdf_fcn_io_t sym, + void* bit_0, + void* bit_1) = 0; + + virtual void convert (size_t n_syms, + pdf_fcn_io_t* syms, + void* bit_0, + void* bit_1) = 0; +}; + +class code_metric_ff : public code_metrics +{ + typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t); + typedef float metric_t, *metric_ptr_t; + +private: + size_t d_n_samples; + pdf_fcn_io_t d_max_sample, d_min_sample, d_delta; + pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit; + std::vector d_metric_table_0_bit; + std::vector d_metric_table_1_bit; + +public: + code_metric_ff (pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample); + ~code_metric_ff () {}; + + void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1); + void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1); +}; + +class code_metric_fl : public code_metrics +{ + typedef float pdf_fcn_io_t; + typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t); + typedef long metric_t, *metric_ptr_t; + +private: + char d_sample_precision; + size_t d_n_samples, d_sample_mask; + pdf_fcn_io_t d_max_sample, d_min_sample, d_delta; + pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit; + std::vector d_metric_table_0_bit; + std::vector d_metric_table_1_bit; + +public: + code_metric_fl (pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample, + int sample_precision = 32); + ~code_metric_fl () {}; + + void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1); + void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1); +}; + +class code_metric_fs : public code_metrics +{ + typedef float pdf_fcn_io_t; + typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t); + typedef short metric_t, *metric_ptr_t; + +private: + char d_sample_precision; + size_t d_n_samples, d_sample_mask; + pdf_fcn_io_t d_max_sample, d_min_sample, d_delta; + pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit; + std::vector d_metric_table_0_bit; + std::vector d_metric_table_1_bit; + +public: + code_metric_fs (pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample, + int sample_precision = 16); + ~code_metric_fs () {}; + + void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1); + void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1); +}; + +class code_metric_fb : public code_metrics +{ + typedef float pdf_fcn_io_t; + typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t); + typedef char metric_t, *metric_ptr_t; + +private: + char d_sample_precision; + size_t d_n_samples, d_sample_mask; + pdf_fcn_io_t d_max_sample, d_min_sample, d_delta; + pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit; + std::vector d_metric_table_0_bit; + std::vector d_metric_table_1_bit; + +public: + code_metric_fb (pdf_fcn_t pdf_fcn_0_bit, + pdf_fcn_t pdf_fcn_1_bit, + size_t n_samples, + pdf_fcn_io_t min_sample, + pdf_fcn_io_t max_sample, + int sample_precision = 8); + ~code_metric_fb () {}; + + void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1); + void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1); +}; + +#endif /* INCLUDED_CODE_METRIC_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/code_types.h b/gr-error-correcting-codes/src/lib/libecc/code_types.h new file mode 100644 index 00000000..cc771435 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/code_types.h @@ -0,0 +1,31 @@ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_CODE_TYPES_H +#define INCLUDED_CODE_TYPES_H + +#include + +// the following is the type used for encoder memory + +typedef unsigned long memory_t, *memory_ptr_t; + +#endif /* INCLUDED_CODE_TYPES_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder.cc b/gr-error-correcting-codes/src/lib/libecc/decoder.cc new file mode 100644 index 00000000..0b77f779 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define DO_PRINT_DEBUG 1 + +#if DO_PRINT_DEBUG +#include +#endif + +/* + * decode a certain number of output bits + * + * the 'in_buf' and 'out_buf' must have enough memory to handle the + * number of input metrics and output bits; no error checking is done! + * + * n_bits_to_output: the number of bits per output stream to output. + * + * returns the actual number of metrics used per input stream. + */ + +size_t +decoder::decode +(const char** in_buf, + char** out_buf, + size_t n_bits_to_output) +{ + // set the class-internal number of input metrics + // and output bits left to decode + + size_t saved_n_input_metrics; + saved_n_input_metrics = d_n_input_metrics_left = + compute_n_input_metrics (n_bits_to_output); + d_n_output_bits_left = n_bits_to_output; + + // call the private decode function + + decode_private (in_buf, out_buf); + + if (DO_PRINT_DEBUG) { + std::cout << "n_input_metrics_used = " << + (saved_n_input_metrics - d_n_input_metrics_left) << "\n" + "n_output_bits_used = " << + (n_bits_to_output - d_n_output_bits_left) << '\n'; + } + + // return the actual number of input metrics used + + return (saved_n_input_metrics - d_n_input_metrics_left); +} + +/* + * decode a certain number of input metrics + * + * the 'in_buf' and 'out_buf' must have enough memory to handle the + * number of input metrics and output bits; no error checking is done! + * + * n_metrics_to_input: the number of metrics per input stream to decode + * + * returns the actual number of bits written per output stream + */ + +size_t +decoder::decode +(const char** in_buf, + size_t n_metrics_to_input, + char** out_buf) +{ + // set the class-internal number of input metrics and + // output bits left to decode + + size_t saved_n_output_bits; + saved_n_output_bits = d_n_output_bits_left = + compute_n_output_bits (n_metrics_to_input); + d_n_input_metrics_left = n_metrics_to_input; + + // call the private decode function + + decode_private (in_buf, out_buf); + + if (DO_PRINT_DEBUG) { + std::cout << "n_input_metrics_used = " << + (n_metrics_to_input - d_n_input_metrics_left) << '\n'; + std::cout << "n_output_bits_used = " << + (saved_n_output_bits - d_n_output_bits_left) << '\n'; + } + + // return the actual number of output bits written + + return (saved_n_output_bits - d_n_output_bits_left); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder.h b/gr-error-correcting-codes/src/lib/libecc/decoder.h new file mode 100644 index 00000000..76a24b20 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_DECODER_H +#define INCLUDED_DECODER_H + +#include "code_types.h" + +// the 'decoder' class is a virtual class upon which all decoder types +// can be built. + +class decoder +{ +public: + decoder () {}; + virtual ~decoder () {}; + + virtual size_t compute_n_input_metrics (size_t n_output_bits) = 0; + virtual size_t compute_n_output_bits (size_t n_input_metrics) = 0; + virtual size_t decode (const char** in_buf, + char** out_buf, + size_t n_bits_to_output); + virtual size_t decode (const char** in_buf, + size_t n_metrics_to_input, + char** out_buf); + +protected: + virtual void decode_private (const char** in_buf, char** out_buf) = 0; + virtual char get_next_input (const char** in_buf, size_t code_input_n) = 0; + virtual void output_bit (char t_out_bit, char** out_buf, + size_t t_output_stream) = 0; + + size_t d_block_size_bits, d_n_code_inputs, d_n_code_outputs; + size_t d_n_dec_bits; + size_t d_in_buf_ndx, d_out_buf_ndx; + size_t d_in_bit_shift, d_out_bit_shift; + size_t d_n_input_metrics_left, d_n_output_bits_left; +}; + +#endif /* INCLUDED_DECODER_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc new file mode 100644 index 00000000..bce2cacb --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc @@ -0,0 +1,1060 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +const int g_max_block_size_bits = 10000000; +const int g_max_num_streams = 10; +const int g_num_bits_per_byte = 8; + +#define DO_TIME_THOUGHPUT 0 +#define DO_PRINT_DEBUG_INST 0 +#define DO_PRINT_DEBUG_INST_0 0 +#define DO_PRINT_DEBUG_INST_1 0 +#define DO_PRINT_DEBUG_INST_2 0 +#define DO_PRINT_DEBUG_FSM 0 +#define DO_PRINT_DEBUG_INIT 0 +#define DO_PRINT_DEBUG_UP 0 +#define DO_PRINT_DEBUG_UP_0 0 +#define DO_PRINT_DEBUG_UP_1 0 +#define DO_PRINT_DEBUG_MIDDLE 0 +#define DO_PRINT_DEBUG_MIDDLE_0 0 +#define DO_PRINT_DEBUG_MIDDLE_1 0 +#define DO_PRINT_DEBUG_TERM 0 +#define DO_PRINT_DEBUG_TERM_1 0 +#define DO_PRINT_DEBUG_OUTPUT 0 +#define DO_PRINT_DEBUG_OUTPUT_0 0 +#define DO_PRINT_DEBUG_EXIT 0 +#define DO_PRINT_DEBUG 0 + +#if DO_TIME_THOUGHPUT +#include +#endif +#if DO_PRINT_DEBUG +#include +#endif + +decoder_viterbi::decoder_viterbi +(int sample_precision, + encoder_convolutional* l_encoder) +{ + // make sure the sample precitions makes sense + + if ((sample_precision < 0) | (sample_precision > 32)) { + std::cerr << "decoder_viterbi: " + "Requested sample_precision (" << sample_precision << + "must be between 0 and 32.\n"; + assert (0); + } + + // make sure that the encoder is "valid" + + if (! l_encoder) { + std::cerr << "decoder_viterbi: Error: Encoder is a NULL pointer.\n"; + assert (0); + } + + // keep around a pointer to the encoder + + d_encoder = l_encoder; + + // fill the class variables + + d_block_size_bits = d_encoder->block_size_bits (); + d_do_streaming = (d_block_size_bits == 0); + d_n_code_inputs = d_encoder->n_code_inputs (); + d_n_code_outputs = d_encoder->n_code_outputs (); + d_do_termination = d_encoder->do_termination (); +#if 0 + d_total_memory = d_encoder->total_memory (); +#endif + + // NOTE: d_n_states is a 'long', and thus is quite limited in terms + // of max memory and # of input streams to 2^32 states This is OK, + // since that many states would be impossibly slow to decode! might + // make this a "long long" (64 bits) in the future + + d_n_states = 1 << d_total_memory; + d_n_input_combinations = 1 << d_n_code_inputs; + + // really nothing else to do here, since this class doesn't "know" + // how to process streaming versus block decoding, or partial + // trellis versus full-trellis. Those will be handled by + // sub-classes which inherit from this one. + + if (DO_PRINT_DEBUG_INST_0) { + std::cout << "Init:\n" << + "d_block_size_bits = " << d_block_size_bits << "\n" << + "d_n_code_inputs = " << d_n_code_inputs << "\n" << + "d_n_code_outputs = " << d_n_code_outputs << "\n" << + "d_do_streaming = " << + ((d_do_streaming == true) ? "true" : "false") << "\n" << + "d_do_termination = " << + ((d_do_termination == true) ? "true" : "false") << "\n" << + "d_total_memory = " << d_total_memory << "\n" << + "d_n_states = " << d_n_states << "\n" << + "d_n_input_combinations = " << d_n_input_combinations << "\n"; + } + + // always start the fsm in the "init" state + + d_fsm_state = fsm_dec_viterbi_init; + + // create a vector of indexes to states when doing "up" or "termination"; + + d_up_term_states_ndx[0] = new size_t [d_n_states]; + d_up_term_states_ndx[1] = new size_t [d_n_states]; + + // get the total number of out bits per stream + + d_n_total_inputs_per_stream = d_block_size_bits; + if (d_do_termination == true) + d_n_total_inputs_per_stream += d_max_memory; + + + +} + +decoder_viterbi::~decoder_viterbi +() +{ + // reverse over from allocation + + delete [] d_up_term_states_ndx[0]; + delete [] d_up_term_states_ndx[1]; + + // delete the state's structures + + state_t_ptr t_state = d_states[0]; + for (size_t n = d_n_states; n > 0; n--, t_state++) { + connection_t_ptr t_connection = t_state->d_connections; + for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) { + delete [] t_connection->d_output_bits; + } + delete [] t_state->d_connections; + } + delete [] d_states[0]; + + t_state = d_states[1]; + for (size_t n = d_n_states; n > 0; n--, t_state++) { + connection_t_ptr t_connection = t_state->d_connections; + for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) { + delete [] t_connection->d_output_bits; + } + delete [] t_state->d_connections; + } + delete [] d_states[1]; + + // delete the save buffer + + char** t_save_buffer = d_save_buffer; + for (size_t n = 0; n < d_n_code_inputs; n++) { + delete [] (*t_save_buffer++); + } + delete [] d_save_buffer; +} + +void +decoder_viterbi::reset_metrics +(u_char which) +{ + state_t_ptr t_state = d_states[which&1]; + for (size_t n = d_n_states; n > 0; n--, t_state++) { + t_state->d_max_metric = -1e10; +#if 0 +// probably don't need to do these, try removing them later + t_state->d_max_state_ndx = 0; + t_state->d_max_input = -1; +#endif + } +} + +void +decoder_viterbi::zero_metrics +(u_char which) +{ + state_t_ptr t_state = d_states[which&1]; + for (size_t n = d_n_states; n > 0; n--, t_state++) { + t_state->d_max_metric = 0; +#if 0 +// probably don't need to do these, try removing them later + t_state->d_max_state_ndx = -1; + t_state->d_max_input = -1; +#endif + } +} + +//FIXME + +char +decoder_viterbi::get_next_input +(const char** in_buf, +size_t code_input_n) +{ + return (0); +} + +void +decoder_viterbi::decode_private +(const char** in_buf, + char** out_buf) +{ +#if 0 + +#if DO_TIME_THOUGHPUT + struct timeval t_tp; + start_timer (&t_tp); +#endif +#if DO_PRINT_DEBUG + size_t t_state_print_bits = d_total_memory + 1; + size_t t_mem_print_bits = d_max_memory + 2; +#endif +// setup variables for quicker access + const char **in_buf = (const char **) &input_items[0]; + char **out_buf = (char **) &output_items[0]; + int t_in_buf_ndx = 0, t_out_buf_ndx = 0; + int t_out_bit_shift = 0; + int t_ninput_items = compute_n_input_metrics (noutput_items); + int t_noutput_bits = noutput_items; + +#if DO_PRINT_DEBUG_INST + std::cout << "# output items = " << noutput_items << " (" << + t_noutput_bytes << " Bytes, " << (t_noutput_bytes * g_num_bits_per_byte) << + " bits), # input items = " << t_ninput_items << " Symbols\n"; + for (size_t n = 0; n < ninput_items.size(); n++) { + std::cout << "# input items [" << n << "] = " << ninput_items[n] << "\n"; + } +#endif + +// put any leftover bits into the output + if (d_n_saved_bits != 0) { +// copy the leftover from the save buffer +// check to make sure it will all fit + size_t t_noutput_bits = t_noutput_bytes * g_num_bits_per_byte; + size_t t_n_copy; + if (t_noutput_bits < d_n_saved_bits) { +// asking for fewer bits than available; set to copy +// just what's being asked for + t_n_copy = t_noutput_bytes; + } else { +// asking for at least as many bits as available; set to copy all + t_out_buf_ndx = d_n_saved_bits / g_num_bits_per_byte; + t_out_bit_shift = d_n_saved_bits % g_num_bits_per_byte; + t_n_copy = t_out_buf_ndx + (t_out_bit_shift != 0 ? 1 : 0); + } +// do the copy for all output streams (code inputs) +// copy starting at save buffer index "start" + for (size_t n = 0; n < d_n_code_inputs; n++) + bcopy (&(d_save_buffer[n][d_n_saved_bits_start_ndx]), + out_buf[n], t_n_copy); +#if DO_PRINT_DEBUG_INST + std::cout << "Copied " << t_n_copy << " Byte" << + (t_n_copy != 1 ? "s" : "") << ": s_b[][" << + d_n_saved_bits_start_ndx << "] => o_b[][0]\n" << + "# saved bits = " << d_n_saved_bits << + ", o_b_ndx = " << t_out_buf_ndx << + ", bit shift = " << t_out_bit_shift << "\n"; +#endif +// update the number of saved bits and start + if (t_noutput_bits < d_n_saved_bits) { +// asking for fewer bit than available: update +// the number of saved bits and their starting index + d_n_saved_bits_start_ndx += t_noutput_bytes; + d_n_saved_bits -= (t_noutput_bytes * g_num_bits_per_byte); +#if DO_PRINT_DEBUG_INST + std::cout << "Updated # saved bits = " << d_n_saved_bits << + ", index = " << d_n_saved_bits_start_ndx << "\n"; +#endif +// nothing to consume; return the desired number of output items + return (noutput_items); + } else { + d_n_saved_bits_start_ndx = d_n_saved_bits = 0; + } + } +#if DO_PRINT_DEBUG_INST + std::cout << "Starting FSM in state: " << + (d_fsm_state == fsm_dec_viterbi_init ? "init" : + (d_fsm_state == fsm_dec_viterbi_doing_up ? "up" : + (d_fsm_state == fsm_dec_viterbi_doing_middle ? "middle" : + (d_fsm_state == fsm_dec_viterbi_doing_term ? "term" : + (d_fsm_state == fsm_dec_viterbi_output ? "output" : "unknown"))))) << "\n"; +#endif + +// while there are input items to create + while (t_out_buf_ndx < t_noutput_bytes) { +#if DO_PRINT_DEBUG_FMS + std::cout << "Starting 'while': processing " << t_in_buf_ndx << " of " << + t_ninput_items << " items.\nJumping to state '" << + (d_fsm_state == fsm_dec_viterbi_init ? "init" : + (d_fsm_state == fsm_dec_viterbi_doing_up ? "up" : + (d_fsm_state == fsm_dec_viterbi_doing_middle ? "middle" : + (d_fsm_state == fsm_dec_viterbi_doing_term ? "term" : + (d_fsm_state == fsm_dec_viterbi_output ? "output" : "unknown"))))) << "'\n"; +#endif +// jump to the correct state in the fsm + switch (d_fsm_state) { + case fsm_dec_viterbi_doing_up: +#if DO_PRINT_DEBUG_FSM + std::cout << "Starting fsm_dec_viterbi_doing_up\n"; +#endif +// set the number of up_down indices + size_t t_n_up_down_ndx = 1 << (d_n_code_inputs * + d_time_count); +// stay in this state until the correct number of input symbols are +// reached; exit also if we run out of input symbols to process + while ((d_time_count < d_max_memory) & + (t_in_buf_ndx < t_ninput_items)) { +#if DO_PRINT_DEBUG_UP_0 + std::cout << "Doing 'while' loop:\n" << + "t_n_up_down_ndx = " << t_n_up_down_ndx << "\n" << + "d_time_count = " << d_time_count << "\n" << + "d_max_memory = " << d_max_memory << "\n" << + "t_in_buf_ndx = " << t_in_buf_ndx << "\n" << + "t_ninput_items = " << t_ninput_items << "\n"; +#endif +// use the "from" states, loop over all inputs and compute the metric for +// each & store it in the "to" state at the end of the connection. +// no need to compare metrics yet, since none join into any given state + +#if 0 +// reset the "to" state's metrics +// probably don't need to do this; try removing later + reset_metrics (d_states_ndx ^ 1); +#if DO_PRINT_DEBUG_UP + std::cout << "Reset Metrics\n"; +#endif +#endif + +// reset the state's index for each set of new inputs + size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx]; + size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1]; +// loop over all current stored "up" states + for (size_t n = 0; n < t_n_up_down_ndx; n++) { + size_t t_state_ndx = *t_state_ndx_ptr++; +// get a pointer to this state's structure + state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]); +// get the connections for all inputs + connection_t_ptr t_connection = t_state->d_connections; +#if DO_PRINT_DEBUG_UP_0 + std::cout << "Looping over all 'up' states:\n" << + "n = " << n << "\n" << + "t_n_up_down_ndx = " << t_n_up_down_ndx << "\n" << + "d_states_ndx = " << d_states_ndx << "\n" << + "t_state_ndx = " << t_state_ndx << "\n" << + "d_n_input_combs = " << d_n_input_combinations << "\n" << + "t_state = " << t_state << "\n" << + "t_connection = " << t_connection << "\n"; +#endif +// loop over all possible input values, 1 bit per input stream + for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) { +// find the "to" state for this connection + state_t_ptr t_to_state = t_connection->d_to; +// get the output bits for this connection + float* t_output_bit = t_connection->d_output_bits; +// start with this state's metric + float t_metric = t_state->d_max_metric; +#if DO_PRINT_DEBUG_UP_0 + std::cout << + "to state index = " << t_connection->d_to_ndx << "\n" << + "current metric = " << t_metric << "\n"; +#endif + if (d_do_mux_inputs == true) { +// if using mux'ed input streams, handle differently + const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]); +// loop over all encoder-output values + for (size_t r = d_n_code_outputs; r > 0; r--) { +#if DO_PRINT_DEBUG_UP + std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " << + *t_output_bit << " ==> metric -> "; +#endif + t_metric += ((*t_in_buf++) * (*t_output_bit++)); +#if DO_PRINT_DEBUG_UP + std::cout << t_metric << "\n"; +#endif + } + } else { +// loop over all encoder-output values + for (size_t r = 0; r < d_n_code_outputs; r++) { +#if DO_PRINT_DEBUG_UP + std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] << + ", code_out_bit = " << *t_output_bit << " ==> metric -> "; +#endif + t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++)); +#if DO_PRINT_DEBUG_UP + std::cout << t_metric << "\n"; +#endif + } + } +// get the "to" state index + size_t t_to_ndx = t_connection->d_to_ndx; +// store the metric in the "to" state; should not have been used before + t_to_state->d_max_metric = t_metric; +// add the "to" state index to the "up" state list + *t_next_state_ndx_ptr++ = t_to_ndx; +// update the traceback structure, depending on which variety it is +// doing full trellis before decoding; use d_out_buf +// simple: get the current state & output state + traceback_t_ptr t_out_buf = &(d_out_buf[d_time_count] + [t_state_ndx]); + traceback_t_ptr t_next_out_buf = &(d_out_buf[d_time_count+1] + [t_to_ndx]); +#if DO_PRINT_DEBUG_UP_1 + std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n" << + "ndx[" << n << "] == " << t_state_ndx << + ", s[" << n2bs(t_state_ndx,t_state_print_bits) << + "]: max_ndx = " << + n2bs(t_state->d_max_state_ndx,t_state_print_bits) << + ", input = " << n2bs(q, d_n_code_inputs+1) << + ": " << t_next_out_buf << " => " << t_out_buf << "\n"; +#endif +// and connect output to the current, set inputs on output + t_next_out_buf->d_prev = t_out_buf; + t_next_out_buf->d_inputs = q; +// finished (for) this input value + } +// finished (for) this "up_term" state + } +// increment the in_buf index, depending on mux'ing or not + t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs; +// increment the time counter + d_time_count++; +// update the number of "up_term" states + d_up_term_ndx ^= 1; +// increase the number of using states + t_n_up_down_ndx <<= d_n_code_inputs; +// change which d_states' index to use as starting + d_states_ndx ^= 1; +// finished (while) staying in this fsm state or not + } +// if reached the end of doing the "up" part of the trellis, +// switch states into the middle + if (d_time_count == d_max_memory) { +#if DO_PRINT_DEBUG_FSM + std::cout << "Setting FSM to fsm_dec_viterbi_doing_middle\n"; +#endif + d_fsm_state = fsm_dec_viterbi_doing_middle; + } +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_viterbi_doing_up\n"; +#endif + break; + case (fsm_dec_viterbi_doing_middle): +#if DO_PRINT_DEBUG_FSM + std::cout << "Entered fsm_dec_viterbi_doing_middle\n"; +#endif +// stay in this state until the correct number of input symbols is +// reached (if doing block coding), or until there are no more input +// symbols to parse + while (((d_block_size_bits != 0) & + (d_time_count < d_block_size_bits) & + (t_in_buf_ndx < t_ninput_items)) | + ((d_block_size_bits == 0) & + (t_in_buf_ndx < t_ninput_items))) { +// use all states, loop over all inputs, compute the metric for +// each; compare the current metric with all previous stored metric in the +// endpoint of the connection to find the highest one. + +// reset the "to" state's metrics + reset_metrics (d_states_ndx ^ 1); +// get the state's index for each set of new inputs + state_t_ptr t_state = d_states[d_states_ndx]; +#if DO_PRINT_DEBUG_MIDDLE + std::cout << "Time Count " << (d_time_count+1) << " of " << + d_block_size_bits << "\n" << + "d_states_ndx = " << d_states_ndx << "\n";; +#endif +// loop over all current states + for (size_t n = 0; n < d_n_states; n++, t_state++) { +// loop over all possible input values, 1 bit per input stream + connection_t_ptr t_connection = t_state->d_connections; +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "Looping over all 'middle' states: " << + n << " of " << d_n_states << "\n"; +#endif + for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) { +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "Input = " << n2bs(q, d_n_code_inputs+1) << "\n"; +#endif +// start with this state's metric + float t_metric = t_state->d_max_metric; +// get the "to" state + state_t_ptr t_to_state = t_connection->d_to; +// get that state's metric + float t_to_metric = t_to_state->d_max_metric; +// see if the computation is even needed; +// maximum change is d_n_code_outputs if all bits match exactly + if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) { +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "!not computing metric!\n"; +#endif + continue; + } +// metrics are close enough; do the computation and the compare +// get the output bits for this connection + float* t_output_bit = t_connection->d_output_bits; + if (d_do_mux_inputs == true) { +// if using mux'ed input streams, handle differently + const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]); +// loop over all encoder-output values + for (size_t r = d_n_code_outputs; r > 0; r--) { +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " << + *t_output_bit << " ==> metric -> "; +#endif + t_metric += ((*t_in_buf++) * (*t_output_bit++)); +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << t_metric << "\n"; +#endif + } + } else { +// loop over all encoder-output values + for (size_t r = 0; r < d_n_code_outputs; r++) { +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] << + ", code_out_bit = " << *t_output_bit << " ==> metric -> "; +#endif + t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++)); +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << t_metric << "\n"; +#endif + } + } +// done with this input value; compare old and new metrics + if (t_metric > t_to_metric) { +#if DO_PRINT_DEBUG_MIDDLE + std::cout << "New Metric to s[" << + n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: "; + if (t_to_state->d_max_metric == -1e10) { + std::cout << "setting to "; + } else { + std::cout << "was s[" << + n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) << + "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) << + "]@ " << t_to_state->d_max_metric << " now "; + } + std::cout << "s[" << n2bs(n,t_state_print_bits) << "] i[" << + n2bs (q, d_n_code_inputs+1) << "]@ " << t_metric << "\n"; +#endif +// new metric is better; copy that info into the "to" state + t_to_state->d_max_metric = t_metric; + t_to_state->d_max_state_ndx = n; + t_to_state->d_max_input = q; + } +// finished (for) this input value + } +// finished (for) this state + } +// done with all states and all inputs; now update the traceback structure +// change which d_states' index to use as starting + d_states_ndx ^= 1; +// get the state's index for the "to" set of new inputs to get the +// "max" stuff from + t_state = d_states[d_states_ndx]; +// update the traceback structure +// loop over all current states + traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count]; + traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1]; +#if DO_PRINT_DEBUG_MIDDLE_1 + std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n"; +#endif + for (size_t n = d_n_states; n > 0; n--, t_state++) { +// simple: get the current state & output state +// and connect output to the current, set inputs on output + traceback_t_ptr t_out_buf = t_out_bufs++; + traceback_t_ptr t_prev_out_buf = + &(t_prev_out_bufs[t_state->d_max_state_ndx]); +#if DO_PRINT_DEBUG_MIDDLE_1 + std::cout << "s[" << n2bs(d_n_states-n,t_state_print_bits) << + "]: max_ndx = " << + n2bs(t_state->d_max_state_ndx,t_state_print_bits) << + ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) << + ": " << t_out_buf << " => " << t_prev_out_buf << "\n"; +#endif + t_out_buf->d_prev = t_prev_out_buf; + t_out_buf->d_inputs = t_state->d_max_input; +// finished doing this state + } +// increment the in_buf index, depending on mux'ing or not + t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs; +// increment the time counter + d_time_count++; +// finished (while) staying in this fsm state or not + } + if ((d_block_size_bits != 0) & + (d_time_count == d_block_size_bits)) { +#if DO_PRINT_DEBUG_FSM + std::cout << "Setting FSM to fsm_dec_viterbi_doing_term\n"; +#endif + d_fsm_state = fsm_dec_viterbi_doing_term; + } + break; +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_viterbi_doing_middle\n"; +#endif + case (fsm_dec_viterbi_doing_term): +#if DO_PRINT_DEBUG_FSM + std::cout << "Entered fsm_dec_viterbi_doing_term\n"; +#endif +// set the "next" up_down index to the end of their states + size_t t_time_count = d_max_memory - (d_time_count - d_block_size_bits); + t_n_up_down_ndx = 1 << (d_n_code_inputs * t_time_count); +// stay in this state until the correct number of input symbols are +// reached; exit also if we run out of input symbols to process + while ((t_time_count > 0) & + (t_in_buf_ndx < t_ninput_items)) { +#if DO_PRINT_DEBUG_TERM + std::cout << "Doing time " << (d_max_memory - t_time_count + 1) << + " of " << d_max_memory << "; starting buf[" << t_in_buf_ndx << + "] of [" << t_ninput_items << "]\n"; +#endif +// use the "to" states, +// FIXME: loop over just the "0" inputs +// and compute the metric for +// each, compare & store it in the "to" state at the end of the connection. + +// reset the "to" state's metrics + reset_metrics (d_states_ndx ^ 1); +// reset the state's index for each set of new inputs + size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx]; + size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1]; +// loop over all current stored "term" state indeces + for (size_t n = 0; n < t_n_up_down_ndx; n++) { + size_t t_state_ndx = *t_state_ndx_ptr++; + state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]); +// loop over just the all 0 input value (d_connections[0]) + connection_t_ptr t_connection = t_state->d_connections; +// get the "to" state + state_t_ptr t_to_state = t_connection->d_to; +// start with this state's metric + float t_metric = t_state->d_max_metric; +// get that state's metric + float t_to_metric = t_to_state->d_max_metric; +#if DO_PRINT_DEBUG_TERM + std::cout << "Term state " << (n+1) << " of " << t_n_up_down_ndx << + "; using d_s[" << d_states_ndx << "][" << + n2bs(t_state_ndx,t_state_print_bits) << "]\n"; +#endif +// see if the computation is even needed; +// maximum change is d_n_code_outputs if all bits match exactly + if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) { +#if DO_PRINT_DEBUG_TERM + std::cout << "!not computing metric!\n"; +#endif + continue; + } +// metrics are close enough; do the computation and the compare +// get the output bits for this connection + float* t_output_bit = t_connection->d_output_bits; + if (d_do_mux_inputs == true) { +// if using mux'ed input streams, handle differently + const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]); +// loop over all encoder-output values + for (size_t r = d_n_code_outputs; r > 0; r--) { + t_metric += ((*t_in_buf++) * (*t_output_bit++)); + } + } else { +// loop over all encoder-output values + for (size_t r = 0; r < d_n_code_outputs; r++) { + t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++)); + } + } +// done with this input value; compare old and new metrics +// see if it's the best metric + if (t_metric > t_to_metric) { +#if DO_PRINT_DEBUG_TERM + std::cout << "New Metric to s[" << + n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: "; + if (t_to_state->d_max_metric == -1e10) { + std::cout << "setting to "; + } else { + std::cout << "was s[" << + n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) << + "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) << + "]@ " << t_to_state->d_max_metric << " now "; + } + std::cout << "s[" << n2bs(t_state_ndx,t_state_print_bits) << + "] i[" << n2bs (0, d_n_code_inputs+1) << "]@ " << t_metric << "\n"; +#endif + t_to_state->d_max_metric = t_metric; + t_to_state->d_max_state_ndx = t_state_ndx; + t_to_state->d_max_input = 0; + } +// add the "to" state's index to the "next" set of state's indices list + *t_next_state_ndx_ptr++ = t_connection->d_to_ndx; +// finished (for) this state + } +// done with all states and all inputs; now update the traceback structure +// change which d_states' index to use as starting + d_states_ndx ^= 1; +// update the number of "up_term" states + d_up_term_ndx ^= 1; +// reduce the number of using states + t_n_up_down_ndx >>= d_n_code_inputs; +// reset the state's index for each set of new inputs + t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx]; +// update the traceback structure +// loop over all current states + traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count]; + traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1]; +#if DO_PRINT_DEBUG_TERM_1 + std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n"; +#endif +// loop over all current stored "term" state indices + for (size_t n = 0; n < t_n_up_down_ndx; n++) { +// get the start index and then pointer to each of the "to" states, +// which hold the newest "max" stuff + size_t t_state_ndx = *t_state_ndx_ptr++; + state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]); +// simple: get the current state & output state +// and connect output to the current, set inputs on output + traceback_t_ptr t_out_buf = &(t_out_bufs[t_state_ndx]); + traceback_t_ptr t_prev_out_buf = + &(t_prev_out_bufs[t_state->d_max_state_ndx]); +#if DO_PRINT_DEBUG_TERM_1 + std::cout << "ndx[" << n << "] == " << t_state_ndx << + ", s[" << n2bs(t_state_ndx,t_state_print_bits) << + "]: max_ndx = " << + n2bs(t_state->d_max_state_ndx,t_state_print_bits) << + ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) << + ": " << t_out_buf << " => " << t_prev_out_buf << "\n"; +#endif + t_out_buf->d_prev = t_prev_out_buf; + t_out_buf->d_inputs = t_state->d_max_input; +// finished (for) this state + } +// increment the in_buf index, depending on mux'ing or not + t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs; +// increment the time counters + t_time_count--; + d_time_count++; +// finished (while) staying in this fsm state or not + } + if (t_time_count == 0) { +// finished this trellis, now move as much of the decoded input to the +// output buffer as possible +#if DO_PRINT_DEBUG_FSM + std::cout << "Setting FSM to fsm_dec_viterbi_output\n"; +#endif + d_fsm_state = fsm_dec_viterbi_output; + } +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_viterbi_doing_term\n"; +#endif + break; + case (fsm_dec_viterbi_output): +#if DO_PRINT_DEBUG_FSM + std::cout << "Entered fsm_dec_viterbi_output.\n"; +#endif +// this is done in reverse bit order (last time to first time) +// using the traceback structure in d_out_buf, starting with +// the maximum valued one in the last time slot, then using +// the traceback's "d_prev" link to trace the trellis back + +// see where the output data will terminate + int t_next_out_buf_ndx = (t_out_buf_ndx + + (d_block_size_bits / g_num_bits_per_byte)); + int t_next_out_bit_shift = (t_out_bit_shift + + (d_block_size_bits % g_num_bits_per_byte)); + if (t_next_out_bit_shift >= g_num_bits_per_byte) { + t_next_out_bit_shift -= g_num_bits_per_byte; + t_next_out_buf_ndx++; + } +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "First bit in at out[][" << t_out_buf_ndx << "].[" << + t_out_bit_shift << "] -> " << d_block_size_bits << " bits == " << + (d_block_size_bits / g_num_bits_per_byte) << " Byte" << + ((d_block_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") << + " + " << (d_block_size_bits % g_num_bits_per_byte) << " bit" << + ((d_block_size_bits % g_num_bits_per_byte) != 1 ? "s" : "") << + "\nNext set of bits start at out[][" << t_next_out_buf_ndx << + "].[" << t_next_out_bit_shift << "]\n"; +#endif +// find the starting traceback structure + traceback_t_ptr t_out_buf; + if (d_do_termination == true) { +// FIXME: assume termination state == 0 +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Using termination; going through trellis for " << + d_max_memory << " bit" << + ((d_max_memory != 1) ? "s" : "") << "\n"; +#endif + t_out_buf = &(d_out_buf[d_time_count][0]); +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Starting traceback ptr " << t_out_buf << "\n"; +#endif +// skip over the termination bits + for (size_t n = d_max_memory; n > 0; n--) { + t_out_buf = t_out_buf->d_prev; +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Next traceback ptr " << t_out_buf << "\n"; +#endif + } + } else { +// no termination but doing block coding; +// FIXME: use the state with the bext metric +// get the state's index for each set of new inputs + state_t_ptr t_state = d_states[d_states_ndx]; + float t_max_metric = t_state->d_max_metric; + size_t t_max_state_ndx = 0; + t_state++; +// loop over all current states + for (size_t n = 1; n < d_n_states; n++, t_state++) { +// start with this state's metric + float t_metric = t_state->d_max_metric; +// compare with current max + if (t_metric > t_max_metric) { + t_max_metric = t_metric; + t_max_state_ndx = n; + } + } +// get the correct out_buf reference to start with + t_out_buf = &(d_out_buf[d_time_count][t_max_state_ndx]); + } +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "Found starting traceback ptr " << t_out_buf << + "; getting all " << d_block_size_bits << " bits per stream.\n"; +#endif +// now we've got the starting traceback structure address; +// check to make sure there is enough space in each output buffer + size_t t_block_bit_ndx = d_block_size_bits; + if ((t_next_out_buf_ndx > t_noutput_bytes) | + ((t_next_out_buf_ndx == t_noutput_bytes) & + (t_next_out_bit_shift != 0))) { +// not enough space for all output bits; +// find the number of extra bits to save + size_t t_save_buf_ndx = t_next_out_buf_ndx - t_noutput_bytes; + size_t t_n_extra_bits = ((t_save_buf_ndx * g_num_bits_per_byte) + + t_next_out_bit_shift); +// set the number of saved bits + d_n_saved_bits = t_n_extra_bits; +// remove the extra bits from the number to copy to the output buffer + t_block_bit_ndx -= t_n_extra_bits; +// find the actual output buf index, once we get there + t_next_out_buf_ndx -= t_save_buf_ndx; +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "Not enough output buffer space:\n" << + "len (o_b) = " << t_noutput_bytes << " ==> " << + t_n_extra_bits << " extra bit" << + (t_n_extra_bits != 1 ? "s" : "") << " == " << + t_save_buf_ndx << " Byte" << + (t_save_buf_ndx != 1 ? "s" : "") << ", " << + t_next_out_bit_shift << " bit" << + (t_next_out_bit_shift != 1 ? "s" : "") << "\n"; +#endif +// zero each output buffers' bytes + size_t t_n_zero = t_save_buf_ndx + (t_next_out_bit_shift ? 1 : 0); +#if DO_PRINT_DEBUG_OUTPUT + size_t t_n_out_bytes = ((d_block_size_bits / g_num_bits_per_byte) + + ((d_block_size_bits % g_num_bits_per_byte) ? 1 : 0)); + std::cout << "Zeroing save buffer from for " << t_n_zero << + " Byte" << (t_n_zero != 1 ? "s" : "") << " (of " << + d_block_size_bits << " bit" << + (d_block_size_bits != 1 ? "s" : "") << " == " << t_n_out_bytes << + " Byte" << (t_n_out_bytes != 1 ? "s" : "") << ")\n"; +#endif + for (size_t m = 0; m < d_n_code_inputs; m++) + bzero (d_save_buffer[m], t_n_zero); +// loop over all extra bits + for (size_t n = t_n_extra_bits; n > 0; n--) { +// first decrement the output bit & byte as necessary + if (--t_next_out_bit_shift < 0) { + t_next_out_bit_shift += g_num_bits_per_byte; + t_save_buf_ndx--; + } +// get the encoder inputs to output + size_t t_inputs = t_out_buf->d_inputs; +// loop over all code inputs (decoder-outputs), 1 bit per stream + for (size_t m = 0; m < d_n_code_inputs; m++) { + d_save_buffer[m][t_save_buf_ndx] |= + ((t_inputs & 1) << t_next_out_bit_shift); + t_inputs >>= 1; + } + t_out_buf = t_out_buf->d_prev; +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Next traceback ptr " << t_out_buf << "\n"; +#endif + } +// at exit, "t_out_buf_ndx" should be == t_noutput_bytes, and +// "t_out_bit_shift" should be 0; check these! +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "n_o_b_ndx (" << t_next_out_buf_ndx << ") ?=? " << + "#o_B (" << t_noutput_bytes << ") & t_o_b_sh (" << + t_next_out_bit_shift << ") ?=? 0\n"; + assert (t_next_out_buf_ndx == t_noutput_bytes); + assert (t_next_out_bit_shift == 0); +#endif + } +// set the correct output buffer index and bit shift + t_out_bit_shift = t_next_out_bit_shift; + t_out_buf_ndx = t_next_out_buf_ndx; +// copy any remaining bits looping backwards in bit-time +// through the traceback trellis + for (size_t n = t_block_bit_ndx; n > 0; n--) { +// first decrement the output bit & byte as necessary + if (--t_out_bit_shift < 0) { + t_out_bit_shift += g_num_bits_per_byte; + t_out_buf_ndx--; + } +// get the encoder inputs to output + size_t t_inputs = t_out_buf->d_inputs; +// loop over all code inputs (decoder-outputs), 1 bit per stream + for (size_t m = 0; m < d_n_code_inputs; m++) { + out_buf[m][t_out_buf_ndx] |= ((t_inputs & 1) << t_out_bit_shift); + t_inputs >>= 1; + } + t_out_buf = t_out_buf->d_prev; +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Next traceback ptr " << t_out_buf << "\n"; +#endif + } +// set the next output byte and bit-shift + t_out_bit_shift = t_next_out_bit_shift; + t_out_buf_ndx = t_next_out_buf_ndx; +#if DO_PRINT_DEBUG_FSM + std::cout << "Set FSM to fsm_dec_viterbi_init\n"; +#endif + d_fsm_state = fsm_dec_viterbi_init; +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_viterbi_output\n"; +#endif + break; + case (fsm_dec_viterbi_init): +#if DO_PRINT_DEBUG_FSM + std::cout << "Entered fsm_dec_viterbi_init\n"; +#endif +// this is called immediately (first input bit upon startup), +// or after termination of a trellis. + +// reset states to the 0'th one + d_up_term_ndx = d_states_ndx = 0; +// zero the metrics for those states + zero_metrics (0); +#if 0 +// might not need to do this; check and see after it works +// reset up_term states and number so that there is 1 item, the "0" state. + bzero (d_up_term_states_ndx[0], sizeof (size_t) * d_n_states); + bzero (d_up_term_states_ndx[1], sizeof (size_t) * d_n_states); +#else + d_up_term_states_ndx[0][0] = 0; +#endif +// reset time count back to the start + d_time_count = 0; +#if 0 +// reset the traceback structures +// might not need to do this; check and see after it works + traceback_t_hdl t_out_bufs = d_out_buf; + for (size_t n = d_n_traceback_els; n > 0; n--) { + traceback_t_ptr t_out_buf = (*t_out_bufs++); + for (size_t m = d_n_states; m > 0; m--, t_out_buf++) { + t_out_buf->d_prev = NULL; + t_out_buf->d_inputs = -1; + } + } +#endif +// set the fsm to "doing up" +#if DO_PRINT_DEBUG_FSM + std::cout << "Set FSM to fsm_dec_viterbi_doing_up\n"; +#endif + d_fsm_state = fsm_dec_viterbi_doing_up; +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_viterbi_init\n"; +#endif + break; +// should never get here! + default: + assert (0); +// done (switch) with FSM + } +// done (while) there are inputs + } + +// consume all of the input items on all input streams +// "ninput_items[]" doesn't seem to be reliable, +// so compute this from the actual number of blocks processed +#if DO_PRINT_DEBUG_EXIT + std::cout << "Exiting FSM in state: " << + (d_fsm_state == fsm_dec_viterbi_init ? "init" : + (d_fsm_state == fsm_dec_viterbi_doing_up ? "up" : + (d_fsm_state == fsm_dec_viterbi_doing_middle ? "middle" : + (d_fsm_state == fsm_dec_viterbi_doing_term ? "term" : + (d_fsm_state == fsm_dec_viterbi_output ? "output" : "unknown"))))) << "\n" << + "Consuming " << t_in_buf_ndx << + " input items on each input stream (of " << t_ninput_items << ").\n"; +#endif + consume_each (t_in_buf_ndx); + +// make sure the number of output items makes sense +// t_out_buf_ndx always points to the current index +// t_out_bit_shift always points to the next bit position to be written + int t_leftover_bytes = t_out_buf_ndx % d_out_stream_el_size_bytes; + int t_leftover_bits = ((t_leftover_bytes * g_num_bits_per_byte) + + t_out_bit_shift); + int t_noutput_items = noutput_items; +#if DO_PRINT_DEBUG_EXIT + std::cout << "Final o_b[" << t_out_buf_ndx << "][" << + t_out_bit_shift << "] of " << t_noutput_bytes << + ", el_size = " << d_out_stream_el_size_bytes << + ", lo_Bytes = " << t_leftover_bytes << + ", t_lo_bits = " << t_leftover_bits << "\n" << + "Desired # output items = " << noutput_items << "\n"; +#endif + if (t_leftover_bits != 0) { + // should never get here! +#if 1 + assert (0); +#else + int t_ndx = t_out_buf_ndx - t_leftover_bytes; + size_t t_n_copy = t_leftover_bytes + ((t_out_bit_shift != 0) ? 1 : 0); + assert (t_n_copy <= d_out_stream_el_size_bytes); +// copy the leftover into the save buffer + for (size_t n = 0; n < d_n_code_inputs; n++) { + bcopy (&(out_buf[n][t_ndx]), d_save_buffer[n], t_n_copy); + } + t_noutput_items = t_ndx / d_out_stream_el_size_bytes; + d_n_saved_bits = t_leftover_bits; +#if DO_PRINT_DEBUG_EXIT + std::cout << "Copied " << t_n_copy << " Byte" << + (t_n_copy != 1 ? "s" : "") << " from o_b[][" << t_ndx << + "] into each save buffer.\n" << + "Actual #output items = " << t_noutput_items << + ", # saved bit(s) = " << d_n_saved_bits << "\n"; +#endif +#endif + } + +#endif + +#if DO_TIME_THOUGHPUT + u_long d_t = end_timer (&t_tp); + + std::cout << "dec_blk_conv_soft_full: Completed " << t_ninput_items << + " bits in " << d_t << " usec => " << + 1e6*(((double)(t_ninput_items))/((double) d_t)) << + " b/s\n"; +#endif +} diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h new file mode 100644 index 00000000..66a6ba40 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h @@ -0,0 +1,189 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_DECODER_VITERBI_H +#define INCLUDED_DECODER_VITERBI_H + +#include "decoder.h" +#include "encoder_convolutional.h" + +class decoder_viterbi : public decoder +{ +public: +/*! + * \brief Decode the incoming metrics streams using the Viterbi algorithm. + * + * input: streams of metrics, 2 streams per n_code_outputs - one each for + * a 0- and 1-bit metric. + * + * output: streams of char, one stream per n_code_inputs, using only + * the right-most justified bit as the single bit per output item. + * + * sample_precision: precision of the incoming metrics + * if == 0, then use soft precision (32 bit float); + * otherwise, use an integer up to 32 bits, already sign-extended + * to the nearest power-of-2-sized type (char, short, long). + * + * l_encoder: pointer to an encoder class from which to determine the + * trellis transitions (states and i/o bits). + */ + + decoder_viterbi (int sample_precision, + encoder_convolutional* l_encoder); + + virtual ~decoder_viterbi (); + +protected: + struct state_t; + +/* + * connection_t: describes an output connection from the current + * time-bit memory state to the next time-bit memory state + * + * d_to: state pointer to which this connection going + * + * d_to_ndx: index of the "to" state + * + * d_output_bits: what are the output bits, coverted into + * 1->+1.0, 0->-1.0, for this connection + */ + + typedef struct connection_t { + struct state_t *d_to; + int d_to_ndx; + float* d_output_bits; + } connection_t, *connection_t_ptr; + +/* + * state_t: describes a given memory state + * + * d_connections: a pointer to an array of these structures + * will be used to describes a given time-bit's memory state; + * an entry will be referenced via "state_add_to", to find the + * connections to the next time-bit memory states. There is + * one entry per each input bit combination -> 2^#I connections in all. + * e.g. [0] means the all 0 input; + * [1] means that input #1 was 1 while all the others were 0; + * [2] means that input #2 was 1, while all the others were 0; + * [3] means that inputs #1 and #2 were 1, while the others were 0. + * + * d_max_metric: the maximum metric thus far for this state + * + * d_max_state: the state from which the maximum metric was attained + * + * d_max_input: the input bits from which the maximum metric was attained + */ + + typedef struct state_t { + connection_t_ptr d_connections; + float d_max_metric; + int d_max_state_ndx; + int d_max_input; + } state_t, *state_t_ptr; + +/* + * state_get_from(v,i,k): use to retrieve a given bit-memory state, + * from the inputs: + * + * memory_t v: the value from which to retrieve the given state + * size_t i: for which input stream (0 to #I-1) + * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2) + */ + + inline memory_t state_get_from (memory_t v, + size_t i, + size_t k) + {return (((v)>>((i)*(k)))&((1<<(k))-1));}; + +/* + * state_add_to(s,v,i,k): use to create a given bit-memory state, + * from the inputs: + * + * memory_t s: the state value to modify + * memory_t v: value to set the state to for this input + * size_t i: for which input stream (0 to #I-1) + * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2) + */ + + inline void state_add_to (memory_t s, + memory_t v, + size_t i, + size_t k) + {(s)|=(((v)&((1<<(k))-1))<<((i)*(k)));}; + +/* + * fsm_dec_viterbi_t: finite state machine for the Viterbi decoder + * + * fsm_dec_viterbi_init: initialize for a new block / block; this is + * already done at instantiation, so do it only at the end of a + * block. + * + * fsm_dec_viterbi_doing_up: encoding at the start of a block + * + * fsm_dec_viterbi_doing_middle: doing encoding inside the trellis + * + * fsm_dec_viterbi_doing_term: termination trellis, if requested + */ + + enum fsm_dec_viterbi_t { + fsm_dec_viterbi_init, fsm_dec_viterbi_doing_up, + fsm_dec_viterbi_doing_middle, fsm_dec_viterbi_doing_term + }; + + virtual void decode_private (const char** in_buf, char** out_buf); + virtual char get_next_input (const char** in_buf, size_t code_input_n); +#if 0 + virtual void decode_loop (const char** in_buf, char** out_buf, + size_t* which_counter, size_t how_many); + + virtual char get_next_input__up (const char** in_buf, + size_t code_input_n) = 0; + virtual char get_next_input__middle (const char** in_buf, + size_t code_input_n) = 0; + virtual char get_next_input__term (size_t code_input_n) = 0; +#endif + virtual void increment_input_indices (bool while_decoding) = 0; + virtual void increment_output_indices (bool while_decoding) = 0; + virtual void update_traceback__up (size_t from_state_ndx, + size_t to_state_ndx, + size_t l_input) = 0; + virtual void update_traceback__middle () = 0; + virtual void update_traceback__term () = 0; + + void reset_metrics (u_char which); + void zero_metrics (u_char which); + + encoder_convolutional* d_encoder; + fsm_dec_viterbi_t d_fsm_state; + size_t d_max_memory, d_total_memory; + size_t d_time_count, d_n_total_inputs_per_stream; + size_t d_n_saved_bits, d_n_saved_bits_start_ndx, d_n_traceback_els; + size_t d_n_states, d_n_input_combinations; + size_t d_states_ndx, d_up_term_ndx; + bool d_do_streaming, d_do_termination; + std::vector d_init_states, d_term_states; + char **d_save_buffer; + state_t_ptr d_states[2]; + size_t* d_up_term_states_ndx[2]; +}; + +#endif /* INCLUDED_DECODER_VITERBI_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc new file mode 100644 index 00000000..308d2775 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc @@ -0,0 +1,1120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "decoder_viterbi_full_block.h" +#include +#include +#include + +const int g_max_block_size_bits = 10000000; +const int g_max_num_streams = 10; +const int g_num_bits_per_byte = 8; + +#define DO_TIME_THOUGHPUT 0 + +#define DO_PRINT_DEBUG_INST 0 +#define DO_PRINT_DEBUG_FSM 0 +#define DO_PRINT_DEBUG_INIT 0 +#define DO_PRINT_DEBUG_UP 0 +#define DO_PRINT_DEBUG_UP_0 0 +#define DO_PRINT_DEBUG_UP_1 0 +#define DO_PRINT_DEBUG_MIDDLE 0 +#define DO_PRINT_DEBUG_MIDDLE_0 0 +#define DO_PRINT_DEBUG_MIDDLE_1 0 +#define DO_PRINT_DEBUG_TERM 0 +#define DO_PRINT_DEBUG_TERM_1 0 +#define DO_PRINT_DEBUG_OUTPUT 0 +#define DO_PRINT_DEBUG_OUTPUT_0 0 +#define DO_PRINT_DEBUG_EXIT 0 +#define DO_PRINT_DEBUG 1 + +#if DO_TIME_THOUGHPUT +#include +#endif +#if DO_PRINT_DEBUG +#include +#endif + +decoder_viterbi_full_block::decoder_viterbi_full_block +(int sample_precision, + encoder_convolutional* l_encoder) + : decoder_viterbi (sample_precision, l_encoder) +{ + // verify that the block size is non-zero + + if (d_block_size_bits == 0) { + std::cerr << "decoder_viterbi_full_block: Error: " + "Block size is 0, and must be positive for block decoding.\n"; + assert (0); + } + + // the traceback buffers are specific to the type of decoding + // (full/block, partial/block, partial/stream) + + // create the traceback buffers; for full/block, use the total # of + // bits to decode + 1: each bit is represented by a transition + // between traceback elements. + + d_n_traceback_els = d_n_total_inputs_per_stream + 1; + + // create the output buffers: + // this is a 2d matrix structure, where the first dimension + // is the number of output bits; the second dimension is + // the number of states. + // When doing full blocks, each bit-time's state's traceback + // contains just the pointer to the previous bit-time's state's traceback + // as well as the inputs for that connection. + // No further work is required because each reverse-path is unique + // once a given end-bit-time's state is determined to be "the one". + + traceback_t_hdl t_out_buf = + d_out_buf = new traceback_t_ptr [d_n_traceback_els]; + for (size_t n = d_n_traceback_els; n > 0; n--) { + (*t_out_buf++) = new traceback_t [d_n_states]; + } + + if (DO_PRINT_DEBUG_INST) { + std::cout << + "total # in bits / stream = " << d_n_total_inputs_per_stream << "\n" << + "d_n_traceback_els = " << d_n_traceback_els << "\n"; + } + + if (DO_PRINT_DEBUG_INST) { + traceback_t_hdl t_out_bufs = d_out_buf; + for (size_t n = 0; n < d_n_traceback_els; n++, *t_out_bufs++) { + traceback_t_ptr t_out_buf = *t_out_bufs; + for (size_t m = 0; m < d_n_states; m++, t_out_buf++) { + std::cout << "tb[" << n << "] = " << t_out_bufs << + ", &tb[" << n << "][" << m << "] = " << (&d_out_buf[n][m]) << + ", tb[" << n << "," << m << "] = " << t_out_buf << "\n"; + } + } + } +} + +decoder_viterbi_full_block::~decoder_viterbi_full_block +() +{ + // delete the traceback buffers + + traceback_t_hdl t_out_buf = d_out_buf; + for (size_t n = d_n_traceback_els; n > 0; n--) { + delete [] (*t_out_buf++); + } + delete [] d_out_buf; +} + +void +decoder_viterbi_full_block::update_traceback__up +(size_t from_state_ndx, + size_t to_state_ndx, + size_t l_input) +{ +#if 0 +#if DO_PRINT_DEBUG + size_t t_state_print_bits = d_total_memory + 1; + size_t t_mem_print_bits = d_max_memory + 2; +#endif + // update the traceback structure, depending on which variety it is + // doing full trellis before decoding; use d_out_buf + + // get the current state & output state + + traceback_t_ptr t_out_buf = &(d_out_buf[d_time_count] + [from_state_ndx]); + traceback_t_ptr t_next_out_buf = &(d_out_buf[d_time_count+1] + [to_state_ndx]); + if (DO_PRINT_DEBUG_UP_1) { + std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n" << + "ndx[" << n << "] == " << from_state_ndx << + ", s[" << n2bs(from_state_ndx,t_state_print_bits) << + "]: max_ndx = " << + n2bs(t_state->d_max_state_ndx,t_state_print_bits) << + ", input = " << n2bs(l_input, d_n_code_inputs+1) << + ": " << t_next_out_buf << " => " << t_out_buf << "\n"; + } + + // and connect output to the current, set inputs on output + + t_next_out_buf->d_prev = t_out_buf; + t_next_out_buf->d_inputs = l_input; +#endif +} + +void +decoder_viterbi_full_block::update_traceback__middle +() +{ +#if 0 + +#if DO_PRINT_DEBUG + size_t t_state_print_bits = d_total_memory + 1; + size_t t_mem_print_bits = d_max_memory + 2; +#endif + // change which d_states' index to use as starting + + d_states_ndx ^= 1; + + // get the state's index for the "to" set of new inputs to get the + // "max" stuff from + + state_t_ptr t_state = d_states[d_states_ndx]; + + // update the traceback structure + // loop over all current states + + traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count]; + traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1]; + + if (DO_PRINT_DEBUG_MIDDLE_1) { + std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n"; + } + + for (size_t n = d_n_states; n > 0; n--, t_state++) { + + // simple: get the current state & output state + // and connect output to the current, set inputs on output + + traceback_t_ptr t_out_buf = t_out_bufs++; + traceback_t_ptr t_prev_out_buf = + &(t_prev_out_bufs[t_state->d_max_state_ndx]); + + if (DO_PRINT_DEBUG_MIDDLE_1) { + std::cout << "s[" << n2bs(d_n_states-n,t_state_print_bits) << + "]: max_ndx = " << + n2bs(t_state->d_max_state_ndx,t_state_print_bits) << + ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) << + ": " << t_out_buf << " => " << t_prev_out_buf << "\n"; + } + + t_out_buf->d_prev = t_prev_out_buf; + t_out_buf->d_inputs = t_state->d_max_input; + } + +#endif +} + +void +decoder_viterbi_full_block::update_traceback__term +() +{ +#if 0 + +#if DO_PRINT_DEBUG + size_t t_state_print_bits = d_total_memory + 1; + size_t t_mem_print_bits = d_max_memory + 2; +#endif +// done with all states and all inputs; now update the traceback structure +// change which d_states' index to use as starting + d_states_ndx ^= 1; +// update the number of "up_term" states + d_up_term_ndx ^= 1; +// reduce the number of using states + t_n_up_down_ndx >>= d_n_code_inputs; +// reset the state's index for each set of new inputs + t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx]; +// update the traceback structure +// loop over all current states + traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count]; + traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1]; +#if DO_PRINT_DEBUG_TERM_1 + std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n"; +#endif +// loop over all current stored "term" state indices + for (size_t n = 0; n < t_n_up_down_ndx; n++) { +// get the start index and then pointer to each of the "to" states, +// which hold the newest "max" stuff + size_t t_state_ndx = *t_state_ndx_ptr++; + state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]); +// simple: get the current state & output state +// and connect output to the current, set inputs on output + traceback_t_ptr t_out_buf = &(t_out_bufs[t_state_ndx]); + traceback_t_ptr t_prev_out_buf = + &(t_prev_out_bufs[t_state->d_max_state_ndx]); +#if DO_PRINT_DEBUG_TERM_1 + std::cout << "ndx[" << n << "] == " << t_state_ndx << + ", s[" << n2bs(t_state_ndx,t_state_print_bits) << + "]: max_ndx = " << + n2bs(t_state->d_max_state_ndx,t_state_print_bits) << + ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) << + ": " << t_out_buf << " => " << t_prev_out_buf << "\n"; +#endif + t_out_buf->d_prev = t_prev_out_buf; + t_out_buf->d_inputs = t_state->d_max_input; +// finished (for) this state + } + +#endif +} + +void +decoder_viterbi_full_block::decode_private +(const char** in_buf, + char** out_buf) +{ +#if 0 + +#if DO_TIME_THOUGHPUT + struct timeval t_tp; + start_timer (&t_tp); +#endif +#if DO_PRINT_DEBUG + size_t t_state_print_bits = d_total_memory + 1; + size_t t_mem_print_bits = d_max_memory + 2; +#endif +// setup variables for quicker access + int t_in_buf_ndx = 0, t_out_buf_ndx = 0; + int t_out_bit_shift = 0; + int t_ninput_items = fixed_rate_noutput_to_ninput (noutput_items); + int t_noutput_bytes = noutput_items * d_out_stream_el_size_bytes; + +#if DO_PRINT_DEBUG_INST + std::cout << "# output items = " << noutput_items << " (" << + t_noutput_bytes << " Bytes, " << (t_noutput_bytes * g_num_bits_per_byte) << + " bits), # input items = " << t_ninput_items << " Symbols\n"; + for (size_t n = 0; n < ninput_items.size(); n++) { + std::cout << "# input items [" << n << "] = " << ninput_items[n] << "\n"; + } +#endif + +// put any leftover bits into the output + if (d_n_saved_bits != 0) { +// copy the leftover from the save buffer +// check to make sure it will all fit + size_t t_noutput_bits = t_noutput_bytes * g_num_bits_per_byte; + size_t t_n_copy; + if (t_noutput_bits < d_n_saved_bits) { +// asking for fewer bits than available; set to copy +// just what's being asked for + t_n_copy = t_noutput_bytes; + } else { +// asking for at least as many bits as available; set to copy all + t_out_buf_ndx = d_n_saved_bits / g_num_bits_per_byte; + t_out_bit_shift = d_n_saved_bits % g_num_bits_per_byte; + t_n_copy = t_out_buf_ndx + (t_out_bit_shift != 0 ? 1 : 0); + } +// do the copy for all output streams (code inputs) +// copy starting at save buffer index "start" + for (size_t n = 0; n < d_n_code_inputs; n++) + bcopy (&(d_save_buffer[n][d_n_saved_bits_start_ndx]), + out_buf[n], t_n_copy); +#if DO_PRINT_DEBUG_INST + std::cout << "Copied " << t_n_copy << " Byte" << + (t_n_copy != 1 ? "s" : "") << ": s_b[][" << + d_n_saved_bits_start_ndx << "] => o_b[][0]\n" << + "# saved bits = " << d_n_saved_bits << + ", o_b_ndx = " << t_out_buf_ndx << + ", bit shift = " << t_out_bit_shift << "\n"; +#endif +// update the number of saved bits and start + if (t_noutput_bits < d_n_saved_bits) { +// asking for fewer bit than available: update +// the number of saved bits and their starting index + d_n_saved_bits_start_ndx += t_noutput_bytes; + d_n_saved_bits -= (t_noutput_bytes * g_num_bits_per_byte); +#if DO_PRINT_DEBUG_INST + std::cout << "Updated # saved bits = " << d_n_saved_bits << + ", index = " << d_n_saved_bits_start_ndx << "\n"; +#endif +// nothing to consume; return the desired number of output items + return (noutput_items); + } else { + d_n_saved_bits_start_ndx = d_n_saved_bits = 0; + } + } +#if DO_PRINT_DEBUG_INST + std::cout << "Starting FSM in state: " << + (d_fsm == fsm_dec_init ? "init" : + (d_fsm == fsm_dec_doing_up ? "up" : + (d_fsm == fsm_dec_doing_middle ? "middle" : + (d_fsm == fsm_dec_doing_term ? "term" : + (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n"; +#endif + +// while there are input items to create + while (t_out_buf_ndx < t_noutput_bytes) { +#if DO_PRINT_DEBUG_FMS + std::cout << "Starting 'while': processing " << t_in_buf_ndx << " of " << + t_ninput_items << " items.\nJumping to state '" << + (d_fsm == fsm_dec_init ? "init" : + (d_fsm == fsm_dec_doing_up ? "up" : + (d_fsm == fsm_dec_doing_middle ? "middle" : + (d_fsm == fsm_dec_doing_term ? "term" : + (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "'\n"; +#endif +// jump to the correct state in the fsm + switch (d_fsm) { + case fsm_dec_doing_up: +#if DO_PRINT_DEBUG_FSM + std::cout << "Starting fsm_dec_doing_up\n"; +#endif +// set the number of up_down indices + size_t t_n_up_down_ndx = 1 << (d_n_code_inputs * + d_time_count); +// stay in this state until the correct number of input symbols are +// reached; exit also if we run out of input symbols to process + while ((d_time_count < d_max_memory) & + (t_in_buf_ndx < t_ninput_items)) { +#if DO_PRINT_DEBUG_UP_0 + std::cout << "Doing 'while' loop:\n" << + "t_n_up_down_ndx = " << t_n_up_down_ndx << "\n" << + "d_time_count = " << d_time_count << "\n" << + "d_max_memory = " << d_max_memory << "\n" << + "t_in_buf_ndx = " << t_in_buf_ndx << "\n" << + "t_ninput_items = " << t_ninput_items << "\n"; +#endif +// use the "from" states, loop over all inputs and compute the metric for +// each & store it in the "to" state at the end of the connection. +// no need to compare metrics yet, since none join into any given state + +#if 0 +// reset the "to" state's metrics +// probably don't need to do this; try removing later + reset_metrics (d_states_ndx ^ 1); +#if DO_PRINT_DEBUG_UP + std::cout << "Reset Metrics\n"; +#endif +#endif + +// reset the state's index for each set of new inputs + size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx]; + size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1]; +// loop over all current stored "up" states + for (size_t n = 0; n < t_n_up_down_ndx; n++) { + size_t t_state_ndx = *t_state_ndx_ptr++; +// get a pointer to this state's structure + state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]); +// get the connections for all inputs + connection_t_ptr t_connection = t_state->d_connections; +#if DO_PRINT_DEBUG_UP_0 + std::cout << "Looping over all 'up' states:\n" << + "n = " << n << "\n" << + "t_n_up_down_ndx = " << t_n_up_down_ndx << "\n" << + "d_states_ndx = " << d_states_ndx << "\n" << + "t_state_ndx = " << t_state_ndx << "\n" << + "d_n_input_combs = " << d_n_input_combinations << "\n" << + "t_state = " << t_state << "\n" << + "t_connection = " << t_connection << "\n"; +#endif +// loop over all possible input values, 1 bit per input stream + for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) { +// find the "to" state for this connection + state_t_ptr t_to_state = t_connection->d_to; +// get the output bits for this connection + float* t_output_bit = t_connection->d_output_bits; +// start with this state's metric + float t_metric = t_state->d_max_metric; +#if DO_PRINT_DEBUG_UP_0 + std::cout << + "to state index = " << t_connection->d_to_ndx << "\n" << + "current metric = " << t_metric << "\n"; +#endif + if (d_do_mux_inputs == true) { +// if using mux'ed input streams, handle differently + const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]); +// loop over all encoder-output values + for (size_t r = d_n_code_outputs; r > 0; r--) { +#if DO_PRINT_DEBUG_UP + std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " << + *t_output_bit << " ==> metric -> "; +#endif + t_metric += ((*t_in_buf++) * (*t_output_bit++)); +#if DO_PRINT_DEBUG_UP + std::cout << t_metric << "\n"; +#endif + } + } else { +// loop over all encoder-output values + for (size_t r = 0; r < d_n_code_outputs; r++) { +#if DO_PRINT_DEBUG_UP + std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] << + ", code_out_bit = " << *t_output_bit << " ==> metric -> "; +#endif + t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++)); +#if DO_PRINT_DEBUG_UP + std::cout << t_metric << "\n"; +#endif + } + } + // get the "to" state index + + size_t t_to_ndx = t_connection->d_to_ndx; + + // store the metric in the "to" state; should not have + // been used before + + t_to_state->d_max_metric = t_metric; + + // add the "to" state index to the "up" state list + + *t_next_state_ndx_ptr++ = t_to_ndx; + + // update the traceback structure + + update_traceback__up (t_state, t_to_state, q); + + // next (for) input value + } + + // next (for) "up_term" state + } + + // increment the input buffer indices + + increment_input_indices (false); + + // increment the time counter + + d_time_count++; + + // change which up-term index to use + + d_up_term_ndx ^= 1; + + // increase the number of states to be used + + t_n_up_down_ndx <<= d_n_code_inputs; + + // change which d_states' index to use as starting + + d_states_ndx ^= 1; + + // next (while) input + } + + // if reached the end of doing the "up" part of the trellis, + // switch states into the middle + + if (d_time_count == d_max_memory) { + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Setting FSM to fsm_dec_doing_middle\n"; + } + d_fsm = fsm_dec_doing_middle; + } + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Exited fsm_dec_doing_up\n"; + } + break; + + case (fsm_dec_doing_middle): + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Entered fsm_dec_doing_middle\n"; + } + + // stay in this state until a full block (+ optional + // termination) of input metrics is reached, or until there are + // no more input metrics to parse + + while ((d_time_count < d_block_size_bits) & + (t_in_buf_ndx < t_ninput_items)) { + + // use all states, loop over all inputs, compute the metric + // for each; compare the current metric with all previous + // stored metric in the endpoint of the connection to find the + // highest one. + + // reset the "to" state's metrics + + reset_metrics (d_states_ndx ^ 1); + + // get the state's index for each set of new inputs + + state_t_ptr t_state = d_states[d_states_ndx]; + + if (DO_PRINT_DEBUG_MIDDLE) { + std::cout << "Time Count " << (d_time_count+1) << " of " << + d_block_size_bits << "\nd_states_ndx = " << d_states_ndx << "\n"; + } + + // loop over all current states + + for (size_t n = 0; n < d_n_states; n++, t_state++) { + + // loop over all possible input values, 1 bit per input stream + + connection_t_ptr t_connection = t_state->d_connections; + + if (DO_PRINT_DEBUG_MIDDLE_0) { + std::cout << "Looping over all 'middle' states: " << + n << " of " << d_n_states << "\n"; + } + + for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) { + + if (DO_PRINT_DEBUG_MIDDLE_0) { + std::cout << "Input = " << n2bs(q, d_n_code_inputs+1) << "\n"; + } + + // start with this state's metric + + float t_metric = t_state->d_max_metric; + + // get the "to" state + + state_t_ptr t_to_state = t_connection->d_to; + + // get that state's metric + + float t_to_metric = t_to_state->d_max_metric; + + // see if the computation is even needed; + // maximum change is d_n_code_outputs if all bits match exactly + + if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) { + if (DO_PRINT_DEBUG_MIDDLE_0) { + std::cout << "!not computing metric!\n"; + } + continue; + } + + // metrics are close enough; do the computation and the + // compare get the output bits for this connection + + float* t_output_bit = t_connection->d_output_bits; + if (d_do_mux_inputs == true) { + + // if using mux'ed input streams, handle differently + + const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]); + + // loop over all encoder-output values + + for (size_t r = d_n_code_outputs; r > 0; r--) { +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " << + *t_output_bit << " ==> metric -> "; +#endif + t_metric += ((*t_in_buf++) * (*t_output_bit++)); +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << t_metric << "\n"; +#endif + } + } else { +// loop over all encoder-output values + for (size_t r = 0; r < d_n_code_outputs; r++) { +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] << + ", code_out_bit = " << *t_output_bit << " ==> metric -> "; +#endif + t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++)); +#if DO_PRINT_DEBUG_MIDDLE_0 + std::cout << t_metric << "\n"; +#endif + } + } +// done with this input value; compare old and new metrics + if (t_metric > t_to_metric) { +#if DO_PRINT_DEBUG_MIDDLE + std::cout << "New Metric to s[" << + n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: "; + if (t_to_state->d_max_metric == -1e10) { + std::cout << "setting to "; + } else { + std::cout << "was s[" << + n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) << + "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) << + "]@ " << t_to_state->d_max_metric << " now "; + } + std::cout << "s[" << n2bs(n,t_state_print_bits) << "] i[" << + n2bs (q, d_n_code_inputs+1) << "]@ " << t_metric << "\n"; +#endif +// new metric is better; copy that info into the "to" state + t_to_state->d_max_metric = t_metric; + t_to_state->d_max_state_ndx = n; + t_to_state->d_max_input = q; + } + // next (for) input value + } + // next (for) state + } + + // done with all states and all inputs; + // update the traceback buffers + + update_traceback__middle (); + + // increment the input buffer indices + + increment_input_indices (); + + // increment the time counter + + d_time_count++; + + // check (while) staying in this fsm state or not + } + + if ((d_block_size_bits != 0) & + (d_time_count == d_block_size_bits)) { + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Setting FSM to fsm_dec_doing_term\n"; + } + d_fsm = fsm_dec_doing_term; + } + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Exited fsm_dec_doing_middle\n"; + } + break; + + case (fsm_dec_doing_term): + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Entered fsm_dec_doing_term\n"; + } + + // set the "next" up_down index to the end of their states + + size_t t_time_count = d_max_memory - (d_time_count - d_block_size_bits); + t_n_up_down_ndx = 1 << (d_n_code_inputs * t_time_count); + + // stay in this state until the correct number of input metrics + // are reached; exit if we run out of input metrics to process + + while ((t_time_count > 0) & + (t_in_buf_ndx < t_ninput_items)) { + + if (DO_PRINT_DEBUG_TERM) { + std::cout << "Doing time " << (d_max_memory - t_time_count + 1) << + " of " << d_max_memory << "; starting buf[" << t_in_buf_ndx << + "] of [" << t_ninput_items << "]\n"; + } + + // FIXME: loop over just the "0" inputs + + // use the "to" states, and compute the metric for each, + // compare & store it in the "to" state at the end of the + // connection. + + // reset the "to" state's metrics + + reset_metrics (d_states_ndx ^ 1); + + // reset the state's index for each set of new inputs + + size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx]; + size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1]; + + // loop over all current stored "term" state indeces + + for (size_t n = 0; n < t_n_up_down_ndx; n++) { + size_t t_state_ndx = *t_state_ndx_ptr++; + state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]); + + // loop over just the all 0 input value (d_connections[0]) + + connection_t_ptr t_connection = t_state->d_connections; + + // get the "to" state + + state_t_ptr t_to_state = t_connection->d_to; + + // start with this state's metric + + float t_metric = t_state->d_max_metric; + + // get that state's metric + + float t_to_metric = t_to_state->d_max_metric; + + if (DO_PRINT_DEBUG_TERM) { + std::cout << "Term state " << (n+1) << " of " << + t_n_up_down_ndx << "; using d_s[" << d_states_ndx << "][" << + n2bs(t_state_ndx,t_state_print_bits) << "]\n"; + } + + // see if the computation is even needed; + // maximum change is d_n_code_outputs if all bits match exactly + + if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) { + if (DO_PRINT_DEBUG_TERM) { + std::cout << "!not computing metric!\n"; + } + continue; + } + + // metrics are close enough; do the computation and the + // compare get the output bits for this connection + + float* t_output_bit = t_connection->d_output_bits; + if (d_do_mux_inputs == true) { +// if using mux'ed input streams, handle differently + const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]); +// loop over all encoder-output values + for (size_t r = d_n_code_outputs; r > 0; r--) { + t_metric += ((*t_in_buf++) * (*t_output_bit++)); + } + } else { +// loop over all encoder-output values + for (size_t r = 0; r < d_n_code_outputs; r++) { + t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++)); + } + } +// done with this input value; compare old and new metrics +// see if it's the best metric + if (t_metric > t_to_metric) { +#if DO_PRINT_DEBUG_TERM + std::cout << "New Metric to s[" << + n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: "; + if (t_to_state->d_max_metric == -1e10) { + std::cout << "setting to "; + } else { + std::cout << "was s[" << + n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) << + "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) << + "]@ " << t_to_state->d_max_metric << " now "; + } + std::cout << "s[" << n2bs(t_state_ndx,t_state_print_bits) << + "] i[" << n2bs (0, d_n_code_inputs+1) << "]@ " << t_metric << "\n"; +#endif + t_to_state->d_max_metric = t_metric; + t_to_state->d_max_state_ndx = t_state_ndx; + t_to_state->d_max_input = 0; + } +// add the "to" state's index to the "next" set of state's indices list + *t_next_state_ndx_ptr++ = t_connection->d_to_ndx; +// finished (for) this state + } + + // update the traceback buffers + + update_traceback__term (); + increment_input_indices (false); + + // increment the time counters + + t_time_count--; + d_time_count++; + + // finished (while) staying in this fsm state or not + + } + + if (t_time_count == 0) { + // finished this trellis, now move as much of the decoded + // input to the output buffer as possible + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Setting FSM to fsm_dec_output\n"; + } + d_fsm = fsm_dec_output; + } + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Exited fsm_dec_doing_term\n"; + } + break; + + case (fsm_dec_output): + if (DO_PRINT_DEBUG_FSM) { + std::cout << "Entered fsm_dec_output.\n"; + } + + // this is done in reverse bit order (last time to first time) + // using the traceback structure in d_out_buf, starting with the + // maximum valued one in the last time slot, then using the + // traceback's "d_prev" link to trace the trellis back + + // see where the output data will terminate + + int t_next_out_buf_ndx = (t_out_buf_ndx + + (d_block_size_bits / g_num_bits_per_byte)); + int t_next_out_bit_shift = (t_out_bit_shift + + (d_block_size_bits % g_num_bits_per_byte)); + if (t_next_out_bit_shift >= g_num_bits_per_byte) { + t_next_out_bit_shift -= g_num_bits_per_byte; + t_next_out_buf_ndx++; + } +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "First bit in at out[][" << t_out_buf_ndx << "].[" << + t_out_bit_shift << "] -> " << d_block_size_bits << " bits == " << + (d_block_size_bits / g_num_bits_per_byte) << " Byte" << + ((d_block_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") << + " + " << (d_block_size_bits % g_num_bits_per_byte) << " bit" << + ((d_block_size_bits % g_num_bits_per_byte) != 1 ? "s" : "") << + "\nNext set of bits start at out[][" << t_next_out_buf_ndx << + "].[" << t_next_out_bit_shift << "]\n"; +#endif +// find the starting traceback structure + traceback_t_ptr t_out_buf; + if (d_do_termination == true) { +// FIXME: assume termination state == 0 +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Using termination; going through trellis for " << + d_max_memory << " bit" << + ((d_max_memory != 1) ? "s" : "") << "\n"; +#endif + t_out_buf = &(d_out_buf[d_time_count][0]); +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Starting traceback ptr " << t_out_buf << "\n"; +#endif +// skip over the termination bits + for (size_t n = d_max_memory; n > 0; n--) { + t_out_buf = t_out_buf->d_prev; +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Next traceback ptr " << t_out_buf << "\n"; +#endif + } + } else { +// no termination but doing block coding; +// FIXME: use the state with the bext metric +// get the state's index for each set of new inputs + state_t_ptr t_state = d_states[d_states_ndx]; + float t_max_metric = t_state->d_max_metric; + size_t t_max_state_ndx = 0; + t_state++; +// loop over all current states + for (size_t n = 1; n < d_n_states; n++, t_state++) { +// start with this state's metric + float t_metric = t_state->d_max_metric; +// compare with current max + if (t_metric > t_max_metric) { + t_max_metric = t_metric; + t_max_state_ndx = n; + } + } +// get the correct out_buf reference to start with + t_out_buf = &(d_out_buf[d_time_count][t_max_state_ndx]); + } +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "Found starting traceback ptr " << t_out_buf << + "; getting all " << d_block_size_bits << " bits per stream.\n"; +#endif +// now we've got the starting traceback structure address; +// check to make sure there is enough space in each output buffer + size_t t_block_bit_ndx = d_block_size_bits; + if ((t_next_out_buf_ndx > t_noutput_bytes) | + ((t_next_out_buf_ndx == t_noutput_bytes) & + (t_next_out_bit_shift != 0))) { +// not enough space for all output bits; +// find the number of extra bits to save + size_t t_save_buf_ndx = t_next_out_buf_ndx - t_noutput_bytes; + size_t t_n_extra_bits = ((t_save_buf_ndx * g_num_bits_per_byte) + + t_next_out_bit_shift); +// set the number of saved bits + d_n_saved_bits = t_n_extra_bits; +// remove the extra bits from the number to copy to the output buffer + t_block_bit_ndx -= t_n_extra_bits; +// find the actual output buf index, once we get there + t_next_out_buf_ndx -= t_save_buf_ndx; +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "Not enough output buffer space:\n" << + "len (o_b) = " << t_noutput_bytes << " ==> " << + t_n_extra_bits << " extra bit" << + (t_n_extra_bits != 1 ? "s" : "") << " == " << + t_save_buf_ndx << " Byte" << + (t_save_buf_ndx != 1 ? "s" : "") << ", " << + t_next_out_bit_shift << " bit" << + (t_next_out_bit_shift != 1 ? "s" : "") << "\n"; +#endif +// zero each output buffers' bytes + size_t t_n_zero = t_save_buf_ndx + (t_next_out_bit_shift ? 1 : 0); +#if DO_PRINT_DEBUG_OUTPUT + size_t t_n_out_bytes = ((d_block_size_bits / g_num_bits_per_byte) + + ((d_block_size_bits % g_num_bits_per_byte) ? 1 : 0)); + std::cout << "Zeroing save buffer from for " << t_n_zero << + " Byte" << (t_n_zero != 1 ? "s" : "") << " (of " << + d_block_size_bits << " bit" << + (d_block_size_bits != 1 ? "s" : "") << " == " << t_n_out_bytes << + " Byte" << (t_n_out_bytes != 1 ? "s" : "") << ")\n"; +#endif + for (size_t m = 0; m < d_n_code_inputs; m++) + bzero (d_save_buffer[m], t_n_zero); +// loop over all extra bits + for (size_t n = t_n_extra_bits; n > 0; n--) { +// first decrement the output bit & byte as necessary + if (--t_next_out_bit_shift < 0) { + t_next_out_bit_shift += g_num_bits_per_byte; + t_save_buf_ndx--; + } +// get the encoder inputs to output + size_t t_inputs = t_out_buf->d_inputs; +// loop over all code inputs (decoder-outputs), 1 bit per stream + for (size_t m = 0; m < d_n_code_inputs; m++) { + d_save_buffer[m][t_save_buf_ndx] |= + ((t_inputs & 1) << t_next_out_bit_shift); + t_inputs >>= 1; + } + t_out_buf = t_out_buf->d_prev; +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Next traceback ptr " << t_out_buf << "\n"; +#endif + } +// at exit, "t_out_buf_ndx" should be == t_noutput_bytes, and +// "t_out_bit_shift" should be 0; check these! +#if DO_PRINT_DEBUG_OUTPUT + std::cout << "n_o_b_ndx (" << t_next_out_buf_ndx << ") ?=? " << + "#o_B (" << t_noutput_bytes << ") & t_o_b_sh (" << + t_next_out_bit_shift << ") ?=? 0\n"; + assert (t_next_out_buf_ndx == t_noutput_bytes); + assert (t_next_out_bit_shift == 0); +#endif + } +// set the correct output buffer index and bit shift + t_out_bit_shift = t_next_out_bit_shift; + t_out_buf_ndx = t_next_out_buf_ndx; +// copy any remaining bits looping backwards in bit-time +// through the traceback trellis + for (size_t n = t_block_bit_ndx; n > 0; n--) { +// first decrement the output bit & byte as necessary + if (--t_out_bit_shift < 0) { + t_out_bit_shift += g_num_bits_per_byte; + t_out_buf_ndx--; + } +// get the encoder inputs to output + size_t t_inputs = t_out_buf->d_inputs; +// loop over all code inputs (decoder-outputs), 1 bit per stream + for (size_t m = 0; m < d_n_code_inputs; m++) { + out_buf[m][t_out_buf_ndx] |= ((t_inputs & 1) << t_out_bit_shift); + t_inputs >>= 1; + } + t_out_buf = t_out_buf->d_prev; +#if DO_PRINT_DEBUG_OUTPUT_0 + std::cout << "Next traceback ptr " << t_out_buf << "\n"; +#endif + } +// set the next output byte and bit-shift + t_out_bit_shift = t_next_out_bit_shift; + t_out_buf_ndx = t_next_out_buf_ndx; +#if DO_PRINT_DEBUG_FSM + std::cout << "Set FSM to fsm_dec_init\n"; +#endif + d_fsm = fsm_dec_init; +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_output\n"; +#endif + break; + case (fsm_dec_init): +#if DO_PRINT_DEBUG_FSM + std::cout << "Entered fsm_dec_init\n"; +#endif +// this is called immediately (first input bit upon startup), +// or after termination of a trellis. + +// reset states to the 0'th one + d_up_term_ndx = d_states_ndx = 0; +// zero the metrics for those states + zero_metrics (0); +#if 0 +// might not need to do this; check and see after it works +// reset up_term states and number so that there is 1 item, the "0" state. + bzero (d_up_term_states_ndx[0], sizeof (size_t) * d_n_states); + bzero (d_up_term_states_ndx[1], sizeof (size_t) * d_n_states); +#else + d_up_term_states_ndx[0][0] = 0; +#endif +// reset time count back to the start + d_time_count = 0; +#if 0 +// reset the traceback structures +// might not need to do this; check and see after it works + traceback_t_hdl t_out_bufs = d_out_buf; + for (size_t n = d_n_traceback_els; n > 0; n--) { + traceback_t_ptr t_out_buf = (*t_out_bufs++); + for (size_t m = d_n_states; m > 0; m--, t_out_buf++) { + t_out_buf->d_prev = NULL; + t_out_buf->d_inputs = -1; + } + } +#endif +// set the fsm to "doing up" +#if DO_PRINT_DEBUG_FSM + std::cout << "Set FSM to fsm_dec_doing_up\n"; +#endif + d_fsm = fsm_dec_doing_up; +#if DO_PRINT_DEBUG_FSM + std::cout << "Exited fsm_dec_init\n"; +#endif + break; +// should never get here! + default: + assert (0); +// done (switch) with FSM + } +// done (while) there are inputs + } + +// consume all of the input items on all input streams +// "ninput_items[]" doesn't seem to be reliable, +// so compute this from the actual number of blocks processed +#if DO_PRINT_DEBUG_EXIT + std::cout << "Exiting FSM in state: " << + (d_fsm == fsm_dec_init ? "init" : + (d_fsm == fsm_dec_doing_up ? "up" : + (d_fsm == fsm_dec_doing_middle ? "middle" : + (d_fsm == fsm_dec_doing_term ? "term" : + (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n" << + "Consuming " << t_in_buf_ndx << + " input items on each input stream (of " << t_ninput_items << ").\n"; +#endif + consume_each (t_in_buf_ndx); + +// make sure the number of output items makes sense +// t_out_buf_ndx always points to the current index +// t_out_bit_shift always points to the next bit position to be written + int t_leftover_bytes = t_out_buf_ndx % d_out_stream_el_size_bytes; + int t_leftover_bits = ((t_leftover_bytes * g_num_bits_per_byte) + + t_out_bit_shift); + int t_noutput_items = noutput_items; +#if DO_PRINT_DEBUG_EXIT + std::cout << "Final o_b[" << t_out_buf_ndx << "][" << + t_out_bit_shift << "] of " << t_noutput_bytes << + ", el_size = " << d_out_stream_el_size_bytes << + ", lo_Bytes = " << t_leftover_bytes << + ", t_lo_bits = " << t_leftover_bits << "\n" << + "Desired # output items = " << noutput_items << "\n"; +#endif + if (t_leftover_bits != 0) { + // should never get here! +#if 1 + assert (0); +#else + int t_ndx = t_out_buf_ndx - t_leftover_bytes; + size_t t_n_copy = t_leftover_bytes + ((t_out_bit_shift != 0) ? 1 : 0); + assert (t_n_copy <= d_out_stream_el_size_bytes); +// copy the leftover into the save buffer + for (size_t n = 0; n < d_n_code_inputs; n++) { + bcopy (&(out_buf[n][t_ndx]), d_save_buffer[n], t_n_copy); + } + t_noutput_items = t_ndx / d_out_stream_el_size_bytes; + d_n_saved_bits = t_leftover_bits; +#if DO_PRINT_DEBUG_EXIT + std::cout << "Copied " << t_n_copy << " Byte" << + (t_n_copy != 1 ? "s" : "") << " from o_b[][" << t_ndx << + "] into each save buffer.\n" << + "Actual #output items = " << t_noutput_items << + ", # saved bit(s) = " << d_n_saved_bits << "\n"; +#endif +#endif + } + +#endif + +#if DO_TIME_THOUGHPUT + u_long d_t = end_timer (&t_tp); + + std::cout << "decoder_viterbi_full_block: Completed " << t_ninput_items << + " bits in " << d_t << " usec => " << + 1e6*(((double)(t_ninput_items))/((double) d_t)) << + " b/s\n"; +#endif +} diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h new file mode 100644 index 00000000..531b7a6c --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_DECODER_VITERBI_FULL_BLOCK_H +#define INCLUDED_DECODER_VITERBI_FULL_BLOCK_H + +#include "decoder_viterbi.h" + +class decoder_viterbi_full_block : public decoder_viterbi +{ +/*! + * \brief Decode the incoming streams using a Viterbi-style decoder, + * doing full trellis block decoding before putting out + * any bits + * + * input: streams of metrics, two per code output: one for the 0-bit + * metrics and the other for the 1-bit metric. + * + * output: stream(s) of output bits + */ + +public: + decoder_viterbi_full_block (int sample_precision, + encoder_convolutional* l_encoder); + + virtual ~decoder_viterbi_full_block (); + +protected: + virtual void decode_private (const char** in_buf, char** out_buf); + virtual void update_traceback__up (size_t from_state_ndx, + size_t to_state_ndx, + size_t l_input); + virtual void update_traceback__middle (); + virtual void update_traceback__term (); + +/* + * traceback_t: used to store all encode-input bits for + * all possible paths, when computing all trellis bits before + * determining the ML decode-output sequence. + * + * d_prev: the connection to the previous bit's traceback structure + * + * d_inputs: the inputs (one per bit) for this connection + */ + + typedef struct traceback_t { + struct traceback_t *d_prev; + int d_inputs; + } traceback_t, *traceback_t_ptr, **traceback_t_hdl; + +/* + * d_n_total_inputs_per_stream: how many bits to store for each + * state to determine the best decoder-output (encoder-input) bits + */ + size_t d_n_inputs_per_stream; + traceback_t_hdl d_out_buf; +}; + +#endif /* INCLUDED_DECODER_VITERBI_FULL_BLOCK_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc new file mode 100644 index 00000000..b0fc4f36 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc @@ -0,0 +1,162 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "decoder_viterbi_full_block_i1_ic1.h" +#include +#include +#include + +const int g_max_block_size_bits = 10000000; +const int g_max_num_streams = 10; +const int g_num_bits_per_byte = 8; + +#define DO_TIME_THOUGHPUT 0 + +#define DO_PRINT_DEBUG_INST 0 +#define DO_PRINT_DEBUG_FSM 0 +#define DO_PRINT_DEBUG_INIT 0 +#define DO_PRINT_DEBUG_UP 0 +#define DO_PRINT_DEBUG_UP_0 0 +#define DO_PRINT_DEBUG_UP_1 0 +#define DO_PRINT_DEBUG_MIDDLE 0 +#define DO_PRINT_DEBUG_MIDDLE_0 0 +#define DO_PRINT_DEBUG_MIDDLE_1 0 +#define DO_PRINT_DEBUG_TERM 0 +#define DO_PRINT_DEBUG_TERM_1 0 +#define DO_PRINT_DEBUG_OUTPUT 0 +#define DO_PRINT_DEBUG_OUTPUT_0 0 +#define DO_PRINT_DEBUG_EXIT 0 +#define DO_PRINT_DEBUG 1 + +#if DO_TIME_THOUGHPUT +#include +#endif +#if DO_PRINT_DEBUG +#include +#endif + +// FIXME + +size_t +decoder_viterbi_full_block_i1_ic1::compute_n_output_bits +(size_t n_input_items) +{ + assert (0); + return (0); +} + +/* + * Compute the number of input items (metrics) needed to produce + * 'noutput' bits. For convolutional decoders, there is 1 + * bit output per metric input per stream, with the addition of a some + * metrics for trellis termination if selected. Without termination, + * there is exactly 1:1 input to output (1 metric in to 1 bit out), + * no matter the encoding type. + * + * if (not terminating), then get the number of output bits. + * + * otherwise, find the number of blocks (not necessarily an integer), + * and then compute the number of input metrics (including termination) + * required to produce those blocks. Subtract the number of bits + * leftover from the previous computation, then find the number of input + * metrics, ceil'd to make sure there are enough. + */ + +size_t +decoder_viterbi_full_block_i1_ic1::compute_n_input_metrics +(size_t n_output_bits) +{ + int t_ninput_items = 0; + int t_noutput_bits = ((int) n_output_bits) - ((int) d_n_saved_bits); + + // if there are enough saved bits, just use those, no inputs required + + if (t_noutput_bits <= 0) + return (0); + + // remove any bits already in the decoding trellis + + if (d_time_count != 0) { + int t_time_bits = ((d_time_count > d_block_size_bits) ? 0 : + d_block_size_bits - d_time_count); + t_noutput_bits -= t_time_bits; + t_ninput_items += t_time_bits; + } + // if completing this trellis doesn't create enough outputs ... + + if (t_noutput_bits > 0) { + + // there is a 1:1 ratio between input symbols and output bits (per + // stream), except for termination bits which are already taken + // into account in the total # of input bits per stream class + // variable; need to round the # output bits to the + + // find the number of blocks, ceil'd to the next higher integer + + int t_nblocks = (int) ceilf (((float) t_noutput_bits) / + ((float) d_block_size_bits)); + + // find the number of required input bits + + t_ninput_items += t_nblocks * d_n_total_inputs_per_stream; + } + + return (t_ninput_items); +} + +// FIXME, from here down dummies to get correct compiling; for testing +// purposes only. + +void +decoder_viterbi_full_block_i1_ic1::increment_input_indices +(bool while_decoding) +{ + if (while_decoding) + std::cout << "foo!"; + +#if 0 +// increment the in_buf index, depending on mux'ing or not + t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs; +#endif +} + +void +decoder_viterbi_full_block_i1_ic1::increment_output_indices +(bool while_decoding) +{ + if (while_decoding) + std::cout << "bar!"; +} + +void +decoder_viterbi_full_block_i1_ic1::output_bit +(char t_out_bit, + char** out_buf, + size_t t_output_stream) +{ + if (t_out_bit) + std::cout << "mop!"; +} diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h new file mode 100644 index 00000000..a7afeb39 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_DECODER_VITERBI_FULL_BLOCK_IC1_H +#define INCLUDED_DECODER_VITERBI_FULL_BLOCK_IC1_H + +#include "decoder_viterbi_full_block.h" + +class decoder_viterbi_full_block_i1_ic1 : public decoder_viterbi_full_block +{ +/*! + * class decoder_viterbi_full_block_i1_ic1 : + * public decoder_viterbi_full_block + * + * Decode the incoming metrics using a Viterbi-style decoder, doing + * full trellis block decoding before putting out any bits + * + * input is "i1": one stream per input (as defined by the + * code-output), with one metric per input item. + * + * output is "ic1": streams of char, one stream per output (as defined + * by the code-input), using only the right-most justified (LSB?) + * bit as the single output bit per output item. + * + * The rest of the options are outlined in the inherited classes' + * header files. + */ + +public: + inline decoder_viterbi_full_block_i1_ic1 + (int sample_precision, + encoder_convolutional* l_encoder) + : decoder_viterbi_full_block (sample_precision, l_encoder) {}; + + virtual ~decoder_viterbi_full_block_i1_ic1 () {}; + + virtual size_t compute_n_input_metrics (size_t n_output_bits); + virtual size_t compute_n_output_bits (size_t n_input_metrics); + +protected: + virtual void increment_input_indices (bool while_decoding); + virtual void output_bit (char t_out_bit, char** out_buf, + size_t t_output_stream); + virtual void increment_output_indices (bool while_decoding); +}; + +#endif /* INCLUDED_DECODER_VITERBI_FULL_BLOCK_I1_IC1_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder.cc b/gr-error-correcting-codes/src/lib/libecc/encoder.cc new file mode 100644 index 00000000..5bc97e7f --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder.cc @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#define DO_PRINT_DEBUG 0 + +/* + * encode a certain number of output bits + * + * the 'in_buf' and 'out_buf' must have enough memory to handle the + * number of input and output bits; no error checking is done! + * + * n_bits_to_output: the number of bits per output stream to encode + * + * returns the actual number of bits used per input stream + */ + +size_t +encoder::encode +(const char** in_buf, + char** out_buf, + size_t n_bits_to_output) +{ + if (DO_PRINT_DEBUG) { + std::cout << "encode{out}(): Starting:"; + } + + // set the class-internal number of input bits and + // output bits left to encode + + size_t saved_n_input_bits; + saved_n_input_bits = d_n_input_bits_left = + compute_n_input_bits (n_bits_to_output); + d_n_output_bits_left = n_bits_to_output; + + if (DO_PRINT_DEBUG) { + std::cout << + "# output bits provided = " << d_n_output_bits_left << "\n" + "# input bits computed = " << d_n_input_bits_left << "\n"; + } + + // call the private encode function + + encode_private (in_buf, out_buf); + + if (DO_PRINT_DEBUG) { + std::cout << + "n_input_bits_used = " << + (saved_n_input_bits - d_n_input_bits_left) << "\n" + "n_output_bits_used = " << + (n_bits_to_output - d_n_output_bits_left) << '\n'; + } + + // return the actual number of input bits used + + return (saved_n_input_bits - d_n_input_bits_left); +} + +/* + * encode a certain number of input bits + * + * the 'in_buf' and 'out_buf' must have enough memory to handle the + * number of input and output bits; no error checking is done! + * + * n_bits_to_input: the number of bits per input stream to encode + * + * returns the actual number of bits written per output stream + */ + +size_t +encoder::encode +(const char** in_buf, + size_t n_bits_to_input, + char** out_buf) +{ + // set the class-internal number of input and + // output bits left to encode + + size_t saved_n_output_bits; + saved_n_output_bits = d_n_output_bits_left = + compute_n_output_bits (n_bits_to_input); + d_n_input_bits_left = n_bits_to_input; + + // call the private encode function + + encode_private (in_buf, out_buf); + + if (DO_PRINT_DEBUG) { + std::cout << "n_input_bits_used = " << + (n_bits_to_input - d_n_input_bits_left) << '\n'; + std::cout << "n_output_bits_used = " << + (saved_n_output_bits - d_n_output_bits_left) << '\n'; + } + + // return the actual number of output bits written + + return (saved_n_output_bits - d_n_output_bits_left); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder.h b/gr-error-correcting-codes/src/lib/libecc/encoder.h new file mode 100644 index 00000000..2c3dde13 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_ENCODER_H +#define INCLUDED_ENCODER_H + +#include "code_types.h" + +// the 'encoder' class is a virtual class upon which all encoder types +// can be built. + +class encoder +{ +public: + encoder () {}; + virtual ~encoder () {}; + + virtual size_t compute_n_input_bits (size_t n_output_bits) = 0; + virtual size_t compute_n_output_bits (size_t n_input_bits) = 0; + virtual size_t encode (const char** in_buf, + char** out_buf, + size_t n_bits_to_output); + virtual size_t encode (const char** in_buf, + size_t n_bits_to_input, + char** out_buf); + +/* for remote access to internal info */ + + inline size_t block_size_bits () {return (d_block_size_bits);}; + inline size_t n_code_inputs () {return (d_n_code_inputs);}; + inline size_t n_code_outputs () {return (d_n_code_outputs);}; + +protected: + /* encode_private: encode the given in_buf and write the output bits + * to the out_buf, using internal class variables. This function is + * called from the publically available "encode()" methods, which + * first set the internal class variables before executing. + */ + + virtual void encode_private (const char** in_buf, char** out_buf) = 0; + + /* inheriting methods need to figure out what makes the most sense + * for them in terms of getting new inputs and writing outputs. + */ + + size_t d_block_size_bits, d_n_code_inputs, d_n_code_outputs; + size_t d_n_enc_bits, d_total_n_enc_bits; + size_t d_in_buf_ndx, d_out_buf_ndx; + size_t d_in_bit_shift, d_out_bit_shift; + size_t d_n_input_bits_left, d_n_output_bits_left; +}; + +#endif /* INCLUDED_ENCODER_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc new file mode 100644 index 00000000..b7bd87de --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc @@ -0,0 +1,290 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "encoder_convolutional.h" +#include +#include + +#define DO_TIME_THOUGHPUT 0 +#define DO_PRINT_DEBUG 1 + +#include +#include + +static const int g_max_block_size_bits = 10000000; +static const int g_max_num_streams = 10; +static const int g_num_bits_per_byte = 8; + +void encoder_convolutional::encoder_convolutional_init +(int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector& code_generators, + const std::vector* code_feedback, + bool do_termination, + int start_memory_state, + int end_memory_state) +{ + // error checking on the input arguments is done by the trellis class + + if (code_feedback) + d_trellis = new code_convolutional_trellis + (block_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + *code_feedback, + do_termination, + end_memory_state); + else + d_trellis = new code_convolutional_trellis + (block_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + do_termination, + end_memory_state); + + // set the initial FSM state to 'init' + + d_fsm_state = fsm_enc_conv_init; + + // create the class block variables + + d_block_size_bits = block_size_bits; + d_n_code_inputs = n_code_inputs; + d_n_code_outputs = n_code_outputs; + d_do_streaming = d_trellis->do_streaming (); + d_do_termination = d_trellis->do_termination (); + d_total_n_delays = d_trellis->total_n_delays (); + + // parse the init state + + memory_t t_mask = (memory_t)((2 << d_total_n_delays) - 1); + size_t t_n_states = (1 << d_total_n_delays); + + if (start_memory_state & t_mask) { + std::cout << "encoder_convolutional: Warning: " << + "provided end memory state out (" << end_memory_state << + ") is out of the state range [0, " << + (t_n_states-1) << "]; masking off the unused bits.\n"; + + start_memory_state &= t_mask; + } + + d_init_state = start_memory_state; + + d_current_inputs.assign (d_n_code_inputs, 0); + d_current_outputs.assign (d_n_code_outputs, 0); +} + +void +encoder_convolutional::encode_private +(const char** in_buf, + char** out_buf) +{ + struct timeval t_tp; + if (DO_TIME_THOUGHPUT) { + start_timer (&t_tp); + } + + // reset buffer indices + + d_total_n_enc_bits = d_in_buf_ndx = d_out_buf_ndx = + d_in_bit_shift = d_out_bit_shift = 0; + + if (DO_PRINT_DEBUG) { + std::cout << "Beginning this encode() call; starting parameters.\n"; + std::cout << "d_n_input_bits_left = " << d_n_input_bits_left << '\n'; + std::cout << "d_n_output_bits_left = " << d_n_output_bits_left << '\n'; + } + + // while there are inputs and outputs left to process ... + + while ((d_n_input_bits_left != 0) & (d_n_output_bits_left != 0)) { + + // jump to the correct state in the fsm + + switch (d_fsm_state) { + + case fsm_enc_conv_init: + + // copy the init states to the current memory + + d_memory = d_init_state; + + // if not doing streaming, things to do; else nothing more do + + if (d_do_streaming == false) { + + // reset the number of encoded bits in this block (which is + // used to compare with the number of bits in the block) + + d_n_enc_bits = 0; + } + + // move to the 'input' state + + d_fsm_state = fsm_enc_conv_doing_input; + break; + + case fsm_enc_conv_doing_input: + + // working through the trellis section which requires input bits + // from external sources; loop up to the block size (before + // termination bits, if any), counting down the number of + // available input bits. + + encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_block_size_bits); + + // finished this loop; check for jumping to the next state + + if ((d_n_enc_bits == d_block_size_bits) & (d_do_streaming == false)) { + + // jump to another state, depending on termination requirement + + if (d_do_termination == true) { + d_n_enc_bits = 0; + d_fsm_state = fsm_enc_conv_doing_term; + } else { + d_fsm_state = fsm_enc_conv_init; + } + } + break; + + case fsm_enc_conv_doing_term: + + // terminating the trellis, trying to get to a specific state; + // better get here only when do_termination is true, but check + // just in case; lop up to the max memory, counting down the + // number of output bits left + + if (d_do_termination == true) { + encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_total_n_delays); + + // finished this loop; check for jumping to the next state + + if (d_n_enc_bits == d_total_n_delays) + d_fsm_state = fsm_enc_conv_init; + + } else { + // should never get here! + assert (0); + } + break; + + default: + // better never get here! + assert (0); + break; + + // done (switch) with FSM + } + + // done (while) there are inputs and outputs + } + + if (DO_PRINT_DEBUG) { + std::cout << "Done with this encode() call; ending parameters.\n" + "d_in_bit_shift = " << d_in_bit_shift << "\n" + "d_out_bit_shift = " << d_out_bit_shift << "\n" + "d_in_buf_ndx = " << d_in_buf_ndx << "\n" + "d_out_buf_ndx = " << d_out_buf_ndx << "\n" + "d_n_input_bits_left = " << d_n_input_bits_left << "\n" + "d_n_output_bits_left = " << d_n_output_bits_left << "\n" + "d_total_n_enc_bits = " << d_total_n_enc_bits << "\n"; + } + + if (DO_TIME_THOUGHPUT) { + // compute the throughput for this particular function call + u_long d_t = end_timer (&t_tp); + std::cout << "Completed " << d_total_n_enc_bits << + " bits in " << d_t << " usec => " << + 1e6*(((double) d_total_n_enc_bits)/((double) d_t)) << + " b/s\n"; + } +} + +void +encoder_convolutional::encode_loop +(const char** in_buf, + char** out_buf, + size_t* which_counter, + size_t how_many) +{ + // generic encode_loop + + if (DO_PRINT_DEBUG) { + std::cout << "Starting encode_loop.\n"; + } + + while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) { + if (DO_PRINT_DEBUG) { + std::cout << "*w_c = " << (*which_counter) << ", " + "# enc_bits = " << d_n_enc_bits << " of " << how_many << ".\n" + "Getting new inputs.\n"; + } + + // get the next set of input bits from all streams; + // written into d_current_inputs + + get_next_inputs (in_buf); + + // use the trellis to do the encoding; + // updates the input memory to the new memory state for the given input + // and writes the output bits to the current_outputs + + d_trellis->encode_lookup (d_memory, d_current_inputs, d_current_outputs); + + // write the bits in d_current_outputs into the output buffer + + write_output_bits (out_buf); + + // increment the number of encoded bits for the current block, and + // the total number of bits for this running of "encode()" + + d_n_enc_bits++; + d_total_n_enc_bits++; + } + + if (DO_PRINT_DEBUG) { + std::cout << "ending encode_loop.\n"; + } +} + +void +encoder_convolutional::get_next_inputs__term +() +{ + // FIXME: how to figure out which term bit to get? + // loop to set each entry of "d_current_inputs" + + // need to do feedback separately, since it involves determining the + // FB bit value & using that as the input value to cancel it out + + d_current_inputs.assign (d_n_code_inputs, 0); + // return (d_term_states[code_input_n] & 1); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h new file mode 100644 index 00000000..4a0d479a --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h @@ -0,0 +1,230 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_H +#define INCLUDED_ENCODER_CONVOLUTIONAL_H + +#include "encoder.h" +#include "code_convolutional_trellis.h" + +class encoder_convolutional : public encoder +{ +/*! + * class encoder_convolutional : public encoder + * + * Encode the incoming streams using a convolutional encoder; This is + * a virtual class which defines the basics of a convolutional + * encoder, but not how input and output bits are handled, nor + * feedback in the encoder. These features are all defined by + * overriding methods appropriately. + * + * block_size_bits: if == 0, then do streaming encoding ("infinite" + * trellis); otherwise this is the block size in bits to encode + * before terminating the trellis. This value -does not- include + * any termination bits. + * + * n_code_inputs: + * n_code_outputs: + * code_generator: vector of integers (32 bit) representing the code + * to be implemented. E.g. "4" in binary is "100", which would be + * "D^2" for code generation. "6" == 110b == "D^2 + D" + * ==> The vector is listed in order for each output stream, so if there + * are 2 input streams (I1, I2) [specified in "n_code_inputs"] + * and 2 output streams (O1, O2) [specified in "n_code_outputs"], + * then the vector would be the code generator for: + * [I1->O1, I2->O1, I1->O2, I2->O2] + * with each element being an integer representation of the code. + * The "octal" representation is used frequently in the literature + * (e.g. [015, 06] == [1101, 0110] in binary) due to its close + * relationship with binary (each number is 3 binary digits) + * ... but any integer representation will suffice. + * + * do_termination: valid only if block_size_bits != 0, and defines + * whether or not to use trellis termination. Default is to use + * termination when doing block coding. + * + * start_memory_state: when starting a new block, the starting memory + * state to begin encoding; there will be a helper function to + * assist in creating this value for a given set of inputs; + * default is the "all zero" state. + * + * end_memory_state: when terminating a block, the ending memory + * state to stop encoding; there will be a helper function to + * assist in creating this value for a given set of inputs; + * default is the "all zero" state. + */ + +public: + inline encoder_convolutional + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0) + {encoder_convolutional_init (block_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + 0, + do_termination, + start_memory_state, + end_memory_state);}; + +/*! + * Encoder with feedback. + * + * code_feedback: vector of integers (32 bit) representing the code + * feedback to be implemented (same as for the code_generator). + * For this feedback type, the LSB ("& 1") is ignored (set to "1" + * internally, since it's always 1) ... this (effectively) + * represents the input bit for the given encoder, without which + * there would be no encoding! Each successive higher-order bit + * represents the output of that delay block; for example "6" == + * 110b == "D^2 + D" means use the current input bit + the output + * of the second delay block. Listing order is the same as for + * the code_generator. + */ + + inline encoder_convolutional + (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector& code_generators, + const std::vector& code_feedback, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0) + {encoder_convolutional_init (block_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + &code_feedback, + do_termination, + start_memory_state, + end_memory_state);}; + + virtual ~encoder_convolutional () {delete d_trellis;}; + +/* for remote access to internal info */ + + inline const bool do_termination () {return (d_do_termination);}; + inline const bool do_feedback () {return (d_trellis->do_feedback());}; + inline const bool do_streaming () {return (d_do_streaming);}; + inline const size_t total_n_delays () {return (d_total_n_delays);}; + +protected: +/* + * fsm_enc_conv_t: finite state machine for the convolutional encoder; + * output happens all the time, so that's built-in to each state. + * + * fsm_enc_conv_init: initialize for a new block / block; this is already + * done at instantiation, so do it only at the end of a block. + * + * fsm_enc_conv_doing_input: doing encoding inside the trellis + * + * fsm_enc_conv_doing_term: termination trellis, if requested + */ + + enum fsm_enc_conv_t { + fsm_enc_conv_init, fsm_enc_conv_doing_input, fsm_enc_conv_doing_term + }; + + // methods defined in this class + + void encoder_convolutional_init (int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector& code_generators, + const std::vector* code_generators, + bool do_termination, + int start_memory_state, + int end_memory_state); + + virtual void encode_private (const char** in_buf, char** out_buf); + + virtual void encode_loop (const char** in_buf, char** out_buf, + size_t* which_counter, size_t how_many); + + inline void get_next_inputs (const char** in_buf) { + switch (d_fsm_state) { + case fsm_enc_conv_doing_input: + get_next_inputs__input (in_buf); + break; + case fsm_enc_conv_doing_term: + get_next_inputs__term (); + break; + default: + assert (0); + break; + } + }; + + virtual void get_next_inputs__term (); + + void get_memory_requirements (size_t m, + size_t n, + size_t& t_max_mem, + size_t& t_n_unique_fb_prev_start, + const std::vector* code_feedback); + + // methods which are required by classes which inherit from this + // one; primarily just the parts which deal with getting input bits + // and writing output bits, changing the indices for those buffers. + + virtual void write_output_bits (char** out_buf) = 0; + virtual void get_next_inputs__input (const char** in_buf) = 0; + + // variables + + fsm_enc_conv_t d_fsm_state; + bool d_do_streaming, d_do_termination; + + // "total_n_delays" is the total # of delays, needed to determine the + // # of states in the decoder + + size_t d_total_n_delays; + + // the current state of the encoder (all delays / memories) + + memory_t d_memory; + + // "inputs" are the current input bits, in the LSB (&1) of each "char" + + std::vector d_current_inputs; + + // "outputs" are the current output bits, in the LSB (&1) of each "char" + + std::vector d_current_outputs; + + // "trellis" is the code trellis for the given input parameters + + code_convolutional_trellis* d_trellis; + + // "init_states" are the user-provided init states, + // interpreted w/r.t. the actual trellis; + + memory_t d_init_state; +}; + +#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc new file mode 100644 index 00000000..aa83c076 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc @@ -0,0 +1,188 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define DO_PRINT_DEBUG 0 + +static const int g_num_bits_per_byte = 8; + +// FIXME +size_t +encoder_convolutional_ic1_ic1::compute_n_output_bits +(size_t n_input_bits) +{ + assert (0); + return (0); +} + +/* + * Compute the number of input bits needed to produce + * 'n_output' bits. For convolutional encoders, there is + * 1 bit output per bit input per stream, with the addition of a some + * bits for trellis termination if selected. Thus the input:output + * bit ratio will be: + * + * if (streaming | no termination), 1:1 + * + * if (not streaming & termination), roughly 1:(1+X), where "X" is the + * total memory size of the code divided by the block length in bits. + * But this also depends on the state of the FSM ... how many bits are + * left before termination. + * + * The returned value will also depend on whether bits are packed, as + * well as whether streams are mux'ed together. + */ + +size_t +encoder_convolutional_ic1_ic1::compute_n_input_bits +(size_t n_output_bits) +{ + size_t t_n_output_bits, t_n_input_bits; + t_n_output_bits = t_n_input_bits = n_output_bits; + + if (d_do_termination == true) { + + // not streaming, doing termination; find the number of bits + // currently available with no required inputs, if any + + size_t n_extra = 0; + if (d_fsm_state == fsm_enc_conv_doing_term) { + n_extra = d_total_n_delays - d_n_enc_bits; + } + + // check to see if this is enough; return 0 if it is. + + if (n_extra >= t_n_output_bits) + return (0); + + // remove those which require no input + + t_n_output_bits -= n_extra; + + // find the number of blocks of data which could be processed + + size_t t_n_output_bits_per_block = d_block_size_bits + d_total_n_delays; + + // get the base number of input items required for the given + // number of blocks to be generated + + size_t t_n_blocks = t_n_output_bits / t_n_output_bits_per_block; + t_n_input_bits = t_n_blocks * d_block_size_bits; + + // add to that the number of leftover inputs needed to generate + // the remainder of the outputs within the remaining block, up to + // the given block size (since anything beyond that within this + // block requires no inputs) + + size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_block; + t_n_input_bits += ((t_leftover_bits > d_block_size_bits) ? + d_block_size_bits : t_leftover_bits); + } + + return (t_n_input_bits); +} + +void +encoder_convolutional_ic1_ic1::write_output_bits +(char** out_buf) +{ + // write all the outputs bits in d_current_outputs LSB (&1) to the + // given output buffer. + + // one bit per output 'char' for "ic1" type output + + for (size_t n = 0; n < d_n_code_outputs; n++) { + if (DO_PRINT_DEBUG) { + std::cout << "Starting output_bit:\n" + " O_i[" << n << "][" << d_out_buf_ndx << "] = " << + n2bs (out_buf[n][d_out_buf_ndx], g_num_bits_per_byte) << + ", b_out = " << n2bs (d_current_outputs[n], 1) << ", "; + } + + out_buf[n][d_out_buf_ndx] = d_current_outputs[n]; + + if (DO_PRINT_DEBUG) { + std::cout << "O_o[][] = " << + n2bs (out_buf[n][d_out_buf_ndx], g_num_bits_per_byte) << + "\n"; + } + } + + if (DO_PRINT_DEBUG) { + std::cout << "Ending write_output_bits.\n"; + } + + // decrement the number of output bits left on all streams + + d_n_output_bits_left--; + + // increment the output index (not the bit shift index) for the next + // write + + d_out_buf_ndx++; +} + +void +encoder_convolutional_ic1_ic1::get_next_inputs__input +(const char** in_buf) +{ + // get the next set of input bits, moved into the LSB (&1) of + // d_current_inputs + + // one bit per input 'char' for "ic1" type input + + for (size_t m = 0; m < d_n_code_inputs; m++) { + d_current_inputs[m] = ((in_buf[m][d_in_buf_ndx]) & 1); + + if (DO_PRINT_DEBUG) { + std::cout << "I[" << m << "][" << d_in_buf_ndx << "] = " << + n2bs (d_current_inputs[m], 1) << "\n"; + } + } + + // decrement the number of bits left on all streams + + if (DO_PRINT_DEBUG) { + std::cout << "# in bits left: " << d_n_input_bits_left << + " -> " << (d_n_input_bits_left-1) << "\n"; + } + + d_n_input_bits_left--; + + // increment the input index (not the bit shift index) for the next + // read + + if (DO_PRINT_DEBUG) { + std::cout << "# in buf ndx: " << d_in_buf_ndx << + " -> " << (d_in_buf_ndx+1) << "\n"; + } + + d_in_buf_ndx++; +} diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h new file mode 100644 index 00000000..a742b097 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h @@ -0,0 +1,91 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H +#define INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H + +#include "encoder_convolutional.h" + +class encoder_convolutional_ic1_ic1 : public encoder_convolutional +{ +public: +/*! + * class encoder_convolutional_ic1_ic1 : public encoder_convolutional + * + * Encode the incoming streams using a convolutional encoder, + * "feedforward" or feedback. Optional termination, data + * streaming, and starting and ending memory states. + * + * input is "ic1": streams of char, one stream per input as defined by the + * instantiated code, using only the right-most justified bit as + * the single input bit per input item. + * + * output is "ic1": streams of char, one stream per output as defined by the + * instantiated code, using only the right-most justified bit as + * the single output bit per output item. + */ + + encoder_convolutional_ic1_ic1 + (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0) + : encoder_convolutional (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + do_termination, + start_memory_state, + end_memory_state) {}; + + encoder_convolutional_ic1_ic1 + (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + const std::vector &code_feedback, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0) + : encoder_convolutional (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + code_feedback, + do_termination, + start_memory_state, + end_memory_state) {}; + + virtual ~encoder_convolutional_ic1_ic1 () {}; + + virtual size_t compute_n_input_bits (size_t n_output_bits); + virtual size_t compute_n_output_bits (size_t n_input_bits); + +protected: + virtual void get_next_inputs__input (const char** in_buf); + virtual void write_output_bits (char** out_buf); +}; + +#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc new file mode 100644 index 00000000..5d2a4bbb --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc @@ -0,0 +1,224 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define DO_TIME_THOUGHPUT 1 +#define DO_PRINT_DEBUG 1 + +#if DO_TIME_THOUGHPUT +#include +#endif +#if DO_PRINT_DEBUG +#include +#endif + +// FIXME: when doing packed, should probably allow user to select how +// bits are selected, so-as to make sure it's always the same +// no matter the CPU endianness + +// FIXME +size_t +encoder_convolutional_ic8_ic8::compute_n_output_bits +(size_t n_input_bits) +{ + assert (0); + return (0); +} + +/* + * Compute the number of input bits needed to produce + * 'n_output' bits. For convolutional encoders, there is + * 1 bit output per bit input per stream, with the addition of a some + * bits for trellis termination if selected. Thus the input:output + * bit ratio will be: + * + * if (streaming | no termination), 1:1 + * + * if (not streaming & termination), roughly 1:(1+X), where "X" is the + * total memory size of the code divided by the block length in bits. + * But this also depends on the state of the FSM ... how many bits are + * left before termination. + * + * The returned value will also depend on whether bits are packed, as + * well as whether streams are mux'ed together. + */ + +size_t +encoder_convolutional_ic8_ic8::compute_n_input_bits +(size_t n_output_bits) +{ + size_t t_n_output_bits, t_n_input_bits; + t_n_output_bits = t_n_input_bits = n_output_bits; + + if (d_do_termination == true) { + + // not streaming, doing termination; find the number of bits + // currently available with no required inputs, if any + + size_t n_extra = 0; + if (d_fsm_state == fsm_enc_conv_doing_term) { + n_extra = d_max_memory - d_n_enc_bits; + } + + // check to see if this is enough; return 0 if it is. + + if (n_extra >= t_n_output_bits) + return (0); + + // remove those which require no input + + t_n_output_bits -= n_extra; + + // find the number of frames of data which could be processed + + size_t t_n_output_bits_per_frame = d_frame_size_bits + d_max_memory; + + // get the base number of input items required for the given + // number of frames to be generated + + size_t t_n_frames = t_n_output_bits / t_n_output_bits_per_frame; + t_n_input_bits = t_n_frames * d_frame_size_bits; + + // add to that the number of leftover inputs needed to generate + // the remainder of the outputs within the remaining frame, up to + // the given frame size (since anything beyond that within this + // frame requires no inputs) + + size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_frame; + t_n_input_bits += ((t_leftover_bits > d_frame_size_bits) ? + d_frame_size_bits : t_leftover_bits); + } + + return (t_n_input_bits); +} + +void +encoder_convolutional_ic8_ic8::increment_io_indices +(bool while_encoding) +{ + // increment the buffer index only for this version, only after + // encoding is done and all resulting outputs are stored on the + // output streams + + if (while_encoding == false) { + d_out_buf_ndx++; + d_in_buf_ndx++; + } + + // nothing to do while encoding, so no else + +#if 0 +// move counters to the next input bit, wrapping to the next input +// byte as necessary + if (++d_in_bit_shift % g_num_bits_per_byte == 0) { + d_in_bit_shift = 0; + d_in_buf_ndx++; + } +// move counters to the next output bit, wrapping to the next output +// byte as necessary + if (++d_out_bit_shift % g_num_bits_per_byte == 0) { + d_out_bit_shift = 0; + d_out_buf_ndx++; + } +#endif +} + +void +encoder_convolutional_ic8_ic8::output_bit +(char t_out_bit, + char** out_buf, + size_t t_output_stream) +{ + // store the result for this particular output stream + // one bit per output item for "ic8" type output + + if (DO_PRINT_DEBUG) { + std::cout << ", O_i[" << t_output_stream << + "][" << d_out_buf_ndx << "] = " << + n2bs (out_buf[t_output_stream][d_out_buf_ndx], 2); + } + + out_buf[t_output_stream][d_out_buf_ndx] = t_out_bit; + + if (DO_PRINT_DEBUG) { + std::cout << ", b_out = " << t_out_bit << + ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" << + d_out_bit_shift << "] = " << + n2bs (out_buf[t_output_stream][d_out_buf_ndx], 2) << '\n'; + } + +#if 0 +#if DO_PRINT_DEBUG + std::cout << ", O_i[" << t_output_stream << + "][" << d_out_buf_ndx << "] = " << + n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte); +#endif + +// packed bits in each output item + out_buf[t_output_stream][d_out_buf_ndx] |= + (t_out_bit << d_out_bit_shift); + +#if DO_PRINT_DEBUG + std::cout << ", b_out = " << t_out_bit << + ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" << + d_out_bit_shift << "] = " << + n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte) << '\n'; +#endif +#endif +} + +char +encoder_convolutional_ic8_ic8::get_next_bit__input +(const char** in_buf, + size_t code_input_n) +{ + // get a bit from this particular input stream + // one bit per output item for "ic8" type input + + if (DO_PRINT_DEBUG) { + std::cout << "I[" << p << "][" << d_in_buf_ndx << "] = "; + cout_binary (t_next_bit, g_num_bits_per_byte); + std::cout << ", st_i[" << p << "] = "; + cout_binary ((*t_states_ptr), d_max_memory+2); + std::cout << ", I[" << p << "][" << d_in_buf_ndx << "][" << + d_in_bit_shift << "] = " << t_next_bit << + ", st_o[" << p << "] = "; + cout_binary (t_state, d_max_memory+2); + std::cout << '\n'; + } + + return ((in_buf[code_input_n][d_in_buf_ndx] >> d_in_bit_shift) & 1); +} + +char +encoder_convolutional_ic8_ic8::get_next_bit__term +(size_t code_input_n) +{ + return ((d_term_states[code_input_n] >> d_in_bit_shift) & 1); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h new file mode 100644 index 00000000..dad39400 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_IC8_IC8_H +#define INCLUDED_ENCODER_CONVOLUTIONAL_IC8_IC8_H + +#include "encoder_convolutional.h" + +/*! + * class encoder_convolutional_ic8_ic8 : public encoder_convolutional + * + * Encode the incoming streams using a convolutional encoder, + * "feedforward" or feedback. Optional termination, data + * streaming, and starting and ending memory states. + * + * input is "ic8": streams of char, one stream per input as defined by the + * instantiated code, using all 8 bits in the char. + * + * FIXME: need to have inputs for MSB or LSB first input and output. + * + * output is "ic8": streams of char, one stream per output as defined by the + * instantiated code, using all 8 bits in the char. + */ + +class encoder_convolutional_ic8_ic8 : public encoder_convolutional +{ +public: + encoder_convolutional_ic8_ic8 + (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0) + : encoder_convolutional (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + do_termination, + start_memory_state, + end_memory_state) {}; + + encoder_convolutional_ic8_ic8 + (int frame_size_bits, + int n_code_inputs, + int n_code_outputs, + const std::vector &code_generators, + const std::vector &code_feedback, + bool do_termination = true, + int start_memory_state = 0, + int end_memory_state = 0) + : encoder_convolutional (frame_size_bits, + n_code_inputs, + n_code_outputs, + code_generators, + code_feedback, + do_termination, + start_memory_state, + end_memory_state) {}; + + virtual ~encoder_convolutional_ic8_ic8 () {}; + + virtual size_t compute_n_input_bits (size_t n_output_bits); + virtual size_t compute_n_output_bits (size_t n_input_bits); + +protected: + virtual char get_next_bit__input (const char** in_buf, + size_t code_input_n); + virtual char get_next_bit__term (size_t code_input_n); + virtual void output_bit (char t_out_bit, char** out_buf, + size_t t_output_stream); + virtual void increment_io_indices (bool while_encoding); + virtual void update_memory_post_encode (); +}; + +#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_IC8_IC8_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc new file mode 100644 index 00000000..3f528cb9 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc @@ -0,0 +1,52 @@ +#include "encoder_turbo.h" + +encoder_turbo::encoder_turbo +(int n_code_inputs, + int n_code_outputs, + const std::vector &encoders, + const std::vector &interleavers) +{ + // need error checking on inputs + + d_encoders = encoders; + d_interleavers = interleavers; +} + +// dummy stuff for now to test std::vector stuff + +size_t +encoder_turbo::compute_n_input_bits +(size_t n_output_bits) +{ + return (0); +} + +size_t +encoder_turbo::compute_n_output_bits +(size_t n_input_bits) +{ + return (0); +} + +void +encoder_turbo::encode_private +(const char** in_buf, + char** out_buf) +{ +} + +char +encoder_turbo::get_next_bit +(const char** in_buf, + size_t code_input_n) +{ + return (0); +} + +void +encoder_turbo::output_bit +(char t_out_bit, + char** out_buf, + size_t t_output_stream) +{ +} diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h new file mode 100644 index 00000000..8c295f1e --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_ENCODER_TURBO_H +#define INCLUDED_ENCODER_TURBO_H + +#include "encoder_convolutional.h" +#include + +class encoder_turbo : public encoder +{ +public: +/*! + * class encoder_turbo : public encoder + * + * Encode the incoming streams using a turbo encoder; This is a + * virtual class which defines the basics of a turbo encoder, but + * not how input and output bits are handled. These features are + * all defined by overriding methods appropriately. + * + * n_code_inputs: + * n_code_outputs: the total number of code inputs and outputs for the + * overall turbo encoder (not just the constituent codes). + * + * encoders: the constituent encoders to be used; all -should- be + * configured with the same "block_size" and "termination", though + * from this encoder's perspective it doesn't really matter. + * + * interleavers: the interleavers to use before each encoder, + * respectively, except the first encoder which will not use an + * interleaver. + */ + + encoder_turbo + (int n_code_inputs, + int n_code_outputs, + const std::vector &encoders, + const std::vector &interleavers); + + virtual ~encoder_turbo () {}; + +/* for remote access to internal info */ + + inline bool do_termination () {return (d_do_termination);}; + +#if 1 + virtual size_t compute_n_input_bits (size_t n_output_bits); + virtual size_t compute_n_output_bits (size_t n_input_bits); +#endif + +protected: +/* + * fsm_enc_turbo_t: finite state machine for the turbo encoder; + * output happens all the time, so that's built-in to each state. + * + * fsm_enc_turbo_init: initialize for a new frame / block; this is already + * done at instantiation, so do it only at the end of a block. + * + * fsm_enc_turbo_doing_input: doing encoding inside the trellis + * + * fsm_enc_turbo_doing_term: termination trellis, if requested + */ + + enum fsm_enc_turbo_t { + fsm_enc_turbo_init, fsm_enc_turbo_doing_input, fsm_enc_turbo_doing_term + }; + +/* + * maio(i,o): matrix access into a vector, knowing the # of code + * outputs (from inside the class). References into a vector with + * code inputs ordered by code output. + * + * 'i' is the first dimension - immediate memory order first - the code input + * 'o' is the second dimension - slower memory order second - the code output + * + * returns ((o*n_code_outputs) + i) + */ + + inline size_t maio(size_t i, size_t o) {return ((o*d_n_code_outputs) + i);}; + +/* + * maoi(i,o): matrix access into a vector, knowing the # of code + * inputs (from inside the class). References into a vector with + * code outputs ordered by code input. + * + * 'o' is the first dimension - immediate memory order first - the code output + * 'i' is the second dimension - slower memory order second - the code input + * + * returns ((i*n_code_inputs) + o) + */ + + inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_inputs) + o);}; + + // methods defined in this class +#if 1 + // temporary just to get full compilation + + virtual void encode_private (const char** in_buf, char** out_buf); + virtual char get_next_bit (const char** in_buf, size_t code_input_n); + virtual void output_bit (char t_out_bit, char** out_buf, + size_t t_output_stream); +#else + virtual void encode_private (const char** in_buf, char** out_buf) = 0; + virtual void encode_loop (const char** in_buf, char** out_buf, + size_t* which_counter, size_t how_many) = 0; + virtual char get_next_bit (const char** in_buf, size_t code_input_n) = 0; + virtual char get_next_bit__term (size_t code_input_n) = 0; + + // methods which are required by classes which inherit from this + // one; primarily just the parts which deal with getting input bits + // and writing output bits, changing the indices for those buffers. + + virtual char get_next_bit__input (const char** in_buf, + size_t code_input_n) = 0; + virtual void increment_io_indices (bool while_encoding) = 0; +#endif + + // variables + + fsm_enc_turbo_t d_fsm_state; + bool d_do_termination; + size_t d_max_memory, d_n_memories; + + std::vector d_encoders; + std::vector d_interleavers; +}; + +#endif /* INCLUDED_ENCODER_TURBO_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am b/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am new file mode 100644 index 00000000..b5accd5a --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am @@ -0,0 +1,36 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I.. -I../.. + +noinst_LTLIBRARIES = libmld.la + +libmld_la_SOURCES = \ + mld_timer.cc n2bs.cc + +noinst_HEADERS = \ + mld_timer.h n2bs.h + +MOSTLYCLEANFILES = *.loT *~ + +CONFIG_CLEAN_FILES = *.in diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.cc b/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.cc new file mode 100644 index 00000000..91708ceb --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.cc @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +void start_timer (struct timeval *t_tp) +{ + gettimeofday (t_tp, 0); +} + +u_long end_timer (struct timeval *g_tp) +{ + struct timeval t_tp; + gettimeofday (&t_tp, 0); + + u_long retVal = (t_tp.tv_sec - g_tp->tv_sec); + u_long df_usec; + + if (t_tp.tv_usec < g_tp->tv_usec) { + retVal -= 1; + df_usec = 1000000 - (g_tp->tv_usec - t_tp.tv_usec); + } else + df_usec = t_tp.tv_usec - g_tp->tv_usec; + + retVal *= 1000000; + retVal += df_usec; + return (retVal); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.h b/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.h new file mode 100644 index 00000000..5e5f89c3 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.h @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +extern void start_timer (struct timeval *t_tp); +extern u_long end_timer (struct timeval *g_tp); diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc new file mode 100644 index 00000000..909aa086 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +const int g_num_bits_per_byte = 8; + +std::string n2bs (long long number, size_t digits) +{ + if (digits > (sizeof (long long) * g_num_bits_per_byte)) + digits = sizeof (long long); + std::string retVal (digits, '0'); + if (number != 0) + for (int n = --digits; n >= 0; n--) { + if (number & 1) { + retVal[n] = '1'; + } + number >>= 1; + } + return (retVal); +} +std::string n2bs (char number, size_t digits) +{ + if (digits > (sizeof (char) * g_num_bits_per_byte)) + digits = sizeof (char); + return n2bs ((long long) number, digits); +} +std::string n2bs (int number, size_t digits) +{ + if (digits > (sizeof (int) * g_num_bits_per_byte)) + digits = sizeof (int); + return n2bs ((long long) number, digits); +} +std::string n2bs (long number, size_t digits) +{ + if (digits > (sizeof (long) * g_num_bits_per_byte)) + digits = sizeof (long); + return n2bs ((long long) number, digits); +} +std::string n2bs (size_t number, size_t digits) +{ + if (digits > (sizeof (size_t) * g_num_bits_per_byte)) + digits = sizeof (size_t); + return n2bs ((long long) number, digits); +} + +void cout_binary (int number, int digits) +{ + while (digits-- > 0) + std::cout << ((number >> digits) & 1); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h new file mode 100644 index 00000000..a663dce8 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +extern std::string n2bs (char number, size_t digits); +extern std::string n2bs (int number, size_t digits); +extern std::string n2bs (long number, size_t digits); +extern std::string n2bs (size_t number, size_t digits); +extern std::string n2bs (long long number, size_t digits); +extern void cout_binary (int number, int digits); diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am b/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am new file mode 100644 index 00000000..79850ba7 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am @@ -0,0 +1,47 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) -I.. + +noinst_LTLIBRARIES = libecc-qa.la + +noinst_HEADERS = \ + qa_encoder_convolutional_ic1_ic1.h \ + qa_ecc.h + +libecc_qa_la_SOURCES = \ + qa_encoder_convolutional_ic1_ic1.cc \ + qa_ecc.cc + +# list of programs run by "make check" and "make distcheck" + +TESTS = test_all + +noinst_PROGRAMS = test_all + +LIBECC = ../libecc.la +LIBECCQA = libecc-qa.la $(LIBECC) + +test_all_SOURCES = test_all.cc +test_all_LDADD = $(LIBECCQA) \ + $(CPPUNIT_LIBS) diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.cc b/gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.cc new file mode 100644 index 00000000..03b185be --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.cc @@ -0,0 +1,40 @@ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include +#include + +CppUnit::TestSuite* +qa_ecc::suite +() +{ + CppUnit::TestSuite* s = new CppUnit::TestSuite ("ecc"); + + s->addTest (qa_encoder_convolutional_ic1_ic1::suite ()); + + return (s); +} diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.h b/gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.h new file mode 100644 index 00000000..ef411673 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.h @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_ECC_H_ +#define _QA_ECC_H_ + +#include + +//! collect all the tests for the gr directory + +class qa_ecc { +public: + //! return suite of tests for all of gr directory + static CppUnit::TestSuite *suite (); +}; + +#endif /* _QA_ECC_H_ */ diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc new file mode 100644 index 00000000..6ea72b6f --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc @@ -0,0 +1,430 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "encoder_convolutional_ic1_ic1.h" +#include +#include +#include +#include +#include +#include + + +void +qa_encoder_convolutional_ic1_ic1::do_encoder_check +(const char** c_in, + const char** c_res, + int n_output_items, + int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const int* code_generators, + const int* code_feedback) +{ + std::vector t_code_generators; + t_code_generators.assign (n_code_inputs * n_code_outputs, 0); + for (int m = 0; m < n_code_inputs * n_code_outputs; m++) + t_code_generators[m] = code_generators[m]; + + encoder_convolutional_ic1_ic1* t_encoder; + + if (code_feedback) { + std::vector t_code_feedback; + t_code_feedback.assign (n_code_inputs * n_code_outputs, 0); + for (int m = 0; m < n_code_inputs * n_code_outputs; m++) + t_code_feedback[m] = code_feedback[m]; + + t_encoder = new encoder_convolutional_ic1_ic1 + (block_size_bits, + n_code_inputs, + n_code_outputs, + t_code_generators, + t_code_feedback); + } else { + t_encoder = new encoder_convolutional_ic1_ic1 + (block_size_bits, + n_code_inputs, + n_code_outputs, + t_code_generators); + } + + char** t_out = new char*[n_code_outputs]; + for (int m = 0; m < n_code_outputs; m++) { + t_out[m] = new char[n_output_items]; + } + + t_encoder->encode (c_in, (char**) t_out, n_output_items); + + for (int m = 0; m < n_code_outputs; m++) { + for (int n = 0; n < n_output_items; n++) { + CPPUNIT_ASSERT_EQUAL (c_res[m][n], t_out[m][n]); + } + } + + delete t_encoder; + t_encoder = 0; + + for (int m = 0; m < n_code_outputs; m++) { + delete [] t_out[m]; + t_out[m] = 0; + } + delete [] t_out; + t_out = 0; +} + +// TEST 0 +// +// checking for SOAI realization (implicitely) +// no feedback, no termination + +const static int t0_code_generator[6] = {1, 0, 5, 0, 1, 6}; +const static int t0_n_code_inputs = 3; +const static int t0_n_code_outputs = 2; +const static int t0_n_input_items = 10; +const static int t0_n_output_items = 10; + +const static char t0_in_0[t0_n_input_items] = + {0, 1, 0, 0, 1, 0, 1, 0, 0, 0}; +const static char t0_in_1[t0_n_input_items] = + {0, 1, 0, 0, 0, 1, 1, 0, 0, 0}; +const static char t0_in_2[t0_n_input_items] = + {0, 0, 1, 1, 1, 1, 1, 0, 0, 0}; +const static char* t0_in[t0_n_code_inputs] = + {t0_in_0, t0_in_1, t0_in_2}; + +const static char t0_res_0[t0_n_output_items] = + {0, 1, 1, 1, 1, 0, 1, 1, 1, 0}; +const static char t0_res_1[t0_n_output_items] = + {0, 1, 0, 1, 0, 1, 1, 0, 1, 0}; +const static char* t0_res[t0_n_code_outputs] = + {t0_res_0, t0_res_1}; + +void +qa_encoder_convolutional_ic1_ic1::t0 +() +{ + do_encoder_check ((const char**) t0_in, (const char**) t0_res, + t0_n_output_items, 100, t0_n_code_inputs, + t0_n_code_outputs, (const int*) t0_code_generator); +} + +// TEST 1 +// +// checking for SIAO realization (implicitely) +// no feedback, no termination + +const static int t1_code_generator[6] = {1, 0, 0, 1, 5, 6}; +const static int t1_n_code_inputs = 2; +const static int t1_n_code_outputs = 3; +const static int t1_n_input_items = 9; +const static int t1_n_output_items = 9; + +const static char t1_in_0[t1_n_input_items] = + {0, 1, 1, 1, 0, 0, 0, 1, 0}; +const static char t1_in_1[t1_n_input_items] = + {0, 0, 0, 0, 0, 1, 1, 1, 0}; +const static char* t1_in[t1_n_code_inputs] = + {t1_in_0, t1_in_1}; + +const static char t1_res_0[t1_n_output_items] = + {0, 1, 1, 1, 0, 0, 0, 1, 0}; +const static char t1_res_1[t1_n_output_items] = + {0, 0, 0, 0, 0, 1, 1, 1, 0}; +const static char t1_res_2[t1_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 1, 0}; +const static char* t1_res[t1_n_code_outputs] = + {t1_res_0, t1_res_1, t1_res_2}; + +void +qa_encoder_convolutional_ic1_ic1::t1 +() +{ + do_encoder_check ((const char**) t1_in, (const char**) t1_res, + t1_n_output_items, 100, t1_n_code_inputs, + t1_n_code_outputs, (const int*) t1_code_generator); +} + +// TEST 2 +// +// checking for SIAO realization (implicitely) +// with same feedback, no termination + +const static int t2_code_generator[6] = {1, 0, 0, 1, 5, 6}; +const static int t2_code_feedback[6] = {0, 0, 0, 0, 7, 7}; +const static int t2_n_code_inputs = 2; +const static int t2_n_code_outputs = 3; +const static int t2_n_input_items = 19; +const static int t2_n_output_items = 19; + +const static char t2_in_0[t2_n_input_items] = + {0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0}; +const static char t2_in_1[t2_n_input_items] = + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0}; +const static char* t2_in[t2_n_code_inputs] = + {t2_in_0, t2_in_1}; + +const static char t2_res_0[t2_n_output_items] = + {0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0}; +const static char t2_res_1[t2_n_output_items] = + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0}; +const static char t2_res_2[t2_n_output_items] = + {0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0}; +const static char* t2_res[t2_n_code_outputs] = + {t2_res_0, t2_res_1, t2_res_2}; + +void +qa_encoder_convolutional_ic1_ic1::t2 +() +{ + do_encoder_check ((const char**) t2_in, (const char**) t2_res, + t2_n_output_items, 100, t2_n_code_inputs, + t2_n_code_outputs, (const int*) t2_code_generator, + (const int*) t2_code_feedback); +} + +// TEST 3 +// +// checking for SOAI realization (implicitely) +// with same feedback, no termination + +const static int t3_code_generator[6] = {1, 0, 5, 0, 1, 6}; +const static int t3_code_feedback[6] = {0, 0, 7, 0, 0, 7}; +const static int t3_n_code_inputs = 3; +const static int t3_n_code_outputs = 2; +const static int t3_n_input_items = 17; +const static int t3_n_output_items = 17; + +const static char t3_in_0[t3_n_input_items] = + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}; +const static char t3_in_1[t3_n_input_items] = + {0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +const static char t3_in_2[t3_n_input_items] = + {0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0}; +const static char* t3_in[t3_n_code_inputs] = + {t3_in_0, t3_in_1, t3_in_2}; + +const static char t3_res_0[t3_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0}; +const static char t3_res_1[t3_n_output_items] = + {0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0}; +const static char* t3_res[t3_n_code_outputs] = + {t3_res_0, t3_res_1}; + +void +qa_encoder_convolutional_ic1_ic1::t3 +() +{ + do_encoder_check ((const char**) t3_in, (const char**) t3_res, + t3_n_output_items, 100, t3_n_code_inputs, + t3_n_code_outputs, (const int*) t3_code_generator, + (const int*) t3_code_feedback); +} + +// TEST 4 +// +// checking for SIAO realization (implicitely), +// with different feedbacks, no termination + +const static int t4_code_generator[6] = {1, 4, 0, 3, 1, 6}; +const static int t4_code_feedback[6] = {0, 7, 0, 5, 0, 5}; +const static int t4_n_code_inputs = 2; +const static int t4_n_code_outputs = 3; +const static int t4_n_input_items = 20; +const static int t4_n_output_items = 20; + +const static char t4_in_0[t4_n_input_items] = + {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}; +const static char t4_in_1[t4_n_input_items] = + {0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0}; +const static char* t4_in[t4_n_code_inputs] = + {t4_in_0, t4_in_1}; + +const static char t4_res_0[t4_n_output_items] = + {0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0}; +const static char t4_res_1[t4_n_output_items] = + {0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0}; +const static char t4_res_2[t4_n_output_items] = + {0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0}; +const static char* t4_res[t4_n_code_outputs] = + {t4_res_0, t4_res_1, t4_res_2}; + +void +qa_encoder_convolutional_ic1_ic1::t4 +() +{ + do_encoder_check ((const char**) t4_in, (const char**) t4_res, + t4_n_output_items, 100, t4_n_code_inputs, + t4_n_code_outputs, (const int*) t4_code_generator, + (const int*) t4_code_feedback); +} + +// TEST 5 +// +// checking for SOAI realization (implicitely), +// with different feedbacks, no termination + +const static int t5_code_generator[6] = {1, 0, 0, 1, 5, 7}; +const static int t5_code_feedback[6] = {0, 0, 0, 0, 7, 3}; +const static int t5_n_code_inputs = 2; +const static int t5_n_code_outputs = 3; +const static int t5_n_input_items = 19; +const static int t5_n_output_items = 19; + +const static char t5_in_0[t5_n_input_items] = + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}; +const static char t5_in_1[t5_n_input_items] = + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}; +const static char* t5_in[t5_n_code_inputs] = + {t5_in_0, t5_in_1}; + +const static char t5_res_0[t5_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0}; +const static char t5_res_1[t5_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0}; +const static char t5_res_2[t5_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0}; +const static char* t5_res[t5_n_code_outputs] = + {t5_res_0, t5_res_1, t5_res_2}; + +void +qa_encoder_convolutional_ic1_ic1::t5 +() +{ +#if 0 + do_encoder_check ((const char**) t5_in, (const char**) t5_res, + t5_n_output_items, 100, t5_n_code_inputs, + t5_n_code_outputs, (const int*) t5_code_generator); +#endif +} + +// TEST 6 +// +// checking for termination, no feedback + +const static int t6_code_generator[6] = {1, 0, 5, 0, 1, 6}; +const static int t6_n_code_inputs = 3; +const static int t6_n_code_outputs = 2; +const static int t6_n_input_items = 6; +const static int t6_n_output_items = 8; + +const static char t6_in_0[t6_n_input_items] = + {0, 1, 0, 0, 1, 0}; +const static char t6_in_1[t6_n_input_items] = + {0, 1, 0, 0, 0, 0}; +const static char t6_in_2[t6_n_input_items] = + {0, 0, 1, 1, 1, 0}; +const static char* t6_in[t6_n_code_inputs] = + {t6_in_0, t6_in_1, t6_in_2}; + +const static char t6_res_0[t6_n_output_items] = + {0, 1, 1, 1, 1, 1, 1, 0}; +const static char t6_res_1[t6_n_output_items] = + {0, 1, 0, 1, 0, 0, 1, 0}; +const static char* t6_res[t6_n_code_outputs] = + {t6_res_0, t6_res_1}; + +void +qa_encoder_convolutional_ic1_ic1::t6 +() +{ + do_encoder_check ((const char**) t6_in, (const char**) t6_res, + t6_n_output_items, 5, t6_n_code_inputs, + t6_n_code_outputs, (const int*) t6_code_generator); +} + +// TEST 7 +// +// checking for termination, with same feedback + +const static int t7_code_generator[6] = {1, 0, 5, 0, 1, 6}; +const static int t7_code_feedback[6] = {0, 0, 7, 0, 0, 7}; +const static int t7_n_code_inputs = 3; +const static int t7_n_code_outputs = 2; +const static int t7_n_input_items = 17; +const static int t7_n_output_items = 17; + +const static char t7_in_0[t7_n_input_items] = + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}; +const static char t7_in_1[t7_n_input_items] = + {0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +const static char t7_in_2[t7_n_input_items] = + {0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0}; +const static char* t7_in[t7_n_code_inputs] = + {t7_in_0, t7_in_1, t7_in_2}; + +const static char t7_res_0[t7_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0}; +const static char t7_res_1[t7_n_output_items] = + {0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0}; +const static char* t7_res[t7_n_code_outputs] = + {t7_res_0, t7_res_1}; + +void +qa_encoder_convolutional_ic1_ic1::t7 +() +{ +#if 0 + do_encoder_check ((const char**) t7_in, (const char**) t7_res, + t7_n_output_items, 5, t7_n_code_inputs, + t7_n_code_outputs, (const int*) t7_code_generator, + (const int*) t7_code_feedback); +#endif +} + +// TEST 8 +// +// checking for termination, with different feedback + +const static int t8_code_generator[6] = {1, 0, 5, 0, 1, 6}; +const static int t8_code_feedback[6] = {0, 0, 7, 0, 0, 3}; +const static int t8_n_code_inputs = 3; +const static int t8_n_code_outputs = 2; +const static int t8_n_input_items = 17; +const static int t8_n_output_items = 17; + +const static char t8_in_0[t8_n_input_items] = + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}; +const static char t8_in_1[t8_n_input_items] = + {0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +const static char t8_in_2[t8_n_input_items] = + {0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0}; +const static char* t8_in[t8_n_code_inputs] = + {t8_in_0, t8_in_1, t8_in_2}; + +const static char t8_res_0[t8_n_output_items] = + {0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0}; +const static char t8_res_1[t8_n_output_items] = + {0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0}; +const static char* t8_res[t8_n_code_outputs] = + {t8_res_0, t8_res_1}; + +void +qa_encoder_convolutional_ic1_ic1::t8 +() +{ +#if 0 + do_encoder_check ((const char**) t8_in, (const char**) t8_res, + t8_n_output_items, 5, t8_n_code_inputs, + t8_n_code_outputs, (const int*) t8_code_generator, + (const int*) t8_code_feedback); +#endif +} diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h new file mode 100644 index 00000000..4449e9eb --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_QA_ENCODER_CONVOLUTIONAL_IC1_IC1_H +#define INCLUDED_QA_ENCODER_CONVOLUTIONAL_IC1_IC1_H + +#include +#include +#include + +class qa_encoder_convolutional_ic1_ic1 : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_encoder_convolutional_ic1_ic1); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST (t6); + CPPUNIT_TEST (t7); + CPPUNIT_TEST (t8); + CPPUNIT_TEST_SUITE_END (); + + private: + void do_encoder_check (const char** c_t1_in, + const char** c_t1_res, + int n_output_items, + int block_size_bits, + int n_code_inputs, + int n_code_outputs, + const int* code_generators, + const int* code_feedback = 0); + + void t0 (); + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); + void t6 (); + void t7 (); + void t8 (); +}; + +#endif /* INCLUDED_QA_ENCODER_CONVOLUTIONAL_IC1_IC1_H */ diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/test_all.cc b/gr-error-correcting-codes/src/lib/libecc/tests/test_all.cc new file mode 100644 index 00000000..2cd6f663 --- /dev/null +++ b/gr-error-correcting-codes/src/lib/libecc/tests/test_all.cc @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main +(int argc, + char **argv) +{ + CppUnit::TextTestRunner runner; + + runner.addTest (qa_ecc::suite ()); + + bool was_successful = runner.run ("", false); + + return ((was_successful == true) ? 0 : 1); +} diff --git a/gr-error-correcting-codes/src/lib/qa_ecc.py b/gr-error-correcting-codes/src/lib/qa_ecc.py new file mode 100755 index 00000000..6f06c9dd --- /dev/null +++ b/gr-error-correcting-codes/src/lib/qa_ecc.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest, ecc + +class qa_ecc (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have drivers, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-error-correcting-codes/src/python/Makefile.am b/gr-error-correcting-codes/src/python/Makefile.am new file mode 100644 index 00000000..7c387f92 --- /dev/null +++ b/gr-error-correcting-codes/src/python/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + +TESTS = run_tests + +noinst_PYTHON = qa_test_coding_1.py qa_test_coding_2.py + +grpython_PYTHON = + +MOSTLYCLEANFILES = *.pyc *~ run_tests diff --git a/gr-error-correcting-codes/src/python/qa_test_coding_1.py b/gr-error-correcting-codes/src/python/qa_test_coding_1.py new file mode 100755 index 00000000..90c479df --- /dev/null +++ b/gr-error-correcting-codes/src/python/qa_test_coding_1.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser +# must be imported from local directory so that make check +# can run before installation +import ecc + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + audio_option = options.audio_output + src = audio.source (sample_rate, audio_option) + src_out_chan = src.output_signature().max_streams() + dst = audio.sink (sample_rate, str(src_out_chan)) + dst_in_chan = dst.input_signature().max_streams() + audio_el_size = src.output_signature().sizeof_stream_item(1) + frame_size = 1000 + do_mux_outputs = 0 + enc_code_in_chan = src_out_chan + code_generators = [05, 06] #, 03, 04] # , 0, 07] + enc_code_out_chan = len (code_generators) / enc_code_in_chan + do_termination = 1 + + if do_mux_outputs == 1: + enc_dec_chan = 1 + else: + enc_dec_chan = enc_code_out_chan + + ss_enc = ecc.streams_encode_convolutional (frame_size, + enc_code_in_chan, + enc_code_out_chan, + code_generators, + do_termination) +# for now + ss2s = gr.streams_to_stream (1, enc_dec_chan); + ns = gr.null_sink (1); +# end for now + +# ss_dec = error-correcting-codes.frames_to_streams (audio_el_size, 1, 1000) + + for i in range (src_out_chan): + self.connect ((src, i), (ss_enc, i)) +# for now + for i in range (enc_dec_chan): + self.connect ((ss_enc, i), (ss2s, i)) + self.connect (ss2s, ns) +# end for now + +# for i in range (enc_dec_chan): +# self.connect ((ss_enc, i), (ss_dec, i)) + +# for i in range (dst_in_chan): +# self.connect ((ss_dec, i), (dst, i)) + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gr-error-correcting-codes/src/python/qa_test_coding_2.py b/gr-error-correcting-codes/src/python/qa_test_coding_2.py new file mode 100755 index 00000000..1ddd50c2 --- /dev/null +++ b/gr-error-correcting-codes/src/python/qa_test_coding_2.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser +# must be imported from local directory so that make check +# can run before installation +import ecc + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + audio_option = options.audio_output + src = audio.source (sample_rate, audio_option) + enc_chan_in = 2 + src_out_chan = src.output_signature().max_streams() + dst = audio.sink (sample_rate, str(enc_chan_in)) + dst_in_chan = dst.input_signature().max_streams() + audio_el_size = dst.input_signature().sizeof_stream_item(0) + frame_size = 10 + enc_code_in_chan = enc_chan_in + code_generators = [05, 06] #, 03, 04] #, 0, 07] + enc_code_out_chan = len (code_generators) / enc_code_in_chan + do_termination = 1 + + ss_enc = ecc.streams_encode_convolutional (frame_size, + enc_code_in_chan, + enc_code_out_chan, + code_generators, + do_termination) + + for i in range (src_out_chan): + p2up = gr.packed_to_unpacked_bb (1, 1) + self.connect ((src, i), p2up, (ss_enc, i)) + + tau_bits = 0 # 0 -> decode all first + ss_dec = error-correcting-codes.dec_blk_conv_soft_full (audio_el_size, + frame_size, + do_termination, + do_mux_outputs, + enc_code_in_chan, + enc_code_out_chan, + code_generators) + up2bf0 = gr.chunks_to_symbols_bf ([1.0, -1.0]) + self.connect ((ss_enc, 0), p2up0, up2bf0, (ss_dec, 0)) + if enc_dec_chan > 1: + p2up1 = gr.packed_to_unpacked_bb (1, 1) + up2bf1 = gr.chunks_to_symbols_bf ([1.0, -1.0]) + self.connect ((ss_enc, 1), p2up1, up2bf1, (ss_dec, 1)) + + for i in range (dst_in_chan): + self.connect ((ss_dec, i), (dst, i)) + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py b/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py new file mode 100755 index 00000000..0eeca992 --- /dev/null +++ b/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser +# must be imported from local directory so that make check +# can run before installation +import ecc + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + audio_option = options.audio_output + src = audio.source (sample_rate, audio_option) + src_out_chan = src.output_signature().max_streams() + dst = audio.sink (sample_rate, str(src_out_chan)) + dst_in_chan = dst.input_signature().max_streams() + audio_el_size = src.output_signature().sizeof_stream_item(1) + frame_size = 10 + enc_code_in_chan = src_out_chan + code_generators = [05, 06] #, 03, 04] # , 0, 07] + enc_code_out_chan = len (code_generators) / enc_code_in_chan + do_termination = 1 + + ss_enc = ecc.streams_encode_convolutional (frame_size, + enc_code_in_chan, + enc_code_out_chan, + code_generators, + do_termination) + for i in range (enc_code_in_chan): + self.connect ((src, i), (ss_enc, i)) + + for i in range (enc_code_out_chan): + ns = gr.null_sink (1) + self.connect ((ss_enc, i), ns) + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_2.py b/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_2.py new file mode 100755 index 00000000..f2ccadb1 --- /dev/null +++ b/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_2.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +import ecc + +def main (): + e1 = ecc.streams_encode_convolutional (100, 3, 2, [1, 0, 5, 0, 1, 6]) + + e2 = ecc.streams_encode_convolutional (100, 2, 3, [1, 0, 0, 1, 5, 6]) + + e3 = ecc.streams_encode_convolutional_feedback (100, 2, 3, [1, 7, 0, 1, 5, 6], [1, 1, 1, 1, 017, 017]) + +if __name__ == '__main__': + main () diff --git a/gr-error-correcting-codes/src/python/run_tests.in b/gr-error-correcting-codes/src/python/run_tests.in new file mode 100644 index 00000000..4618f76c --- /dev/null +++ b/gr-error-correcting-codes/src/python/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-error-correcting-codes/src/lib +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-error-correcting-codes/src/lib +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-error-correcting-codes/src/python + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-gsm-fr-vocoder/AUTHORS b/gr-gsm-fr-vocoder/AUTHORS new file mode 100644 index 00000000..11c18b40 --- /dev/null +++ b/gr-gsm-fr-vocoder/AUTHORS @@ -0,0 +1,3 @@ +Eric Blossom GNU Radio glue, Makefiles, etc. +Jutta Degener GSM 06.10 vocoder +Carsten Bormann GSM 06.10 vocoder diff --git a/gr-gsm-fr-vocoder/ChangeLog b/gr-gsm-fr-vocoder/ChangeLog new file mode 100644 index 00000000..f0ed1e8c --- /dev/null +++ b/gr-gsm-fr-vocoder/ChangeLog @@ -0,0 +1,45 @@ +2006-04-15 Eric Blossom + + * src/lib/gsm/config.h: modified to remove warnings. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/lib/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-01-29 Eric Blossom + + * src/lib/Makefile.am: mods for SWIG 1.3.24 + +2005-01-20 Eric Blossom + + * doc/howto-write-a-block.xml: made release 0.1 + +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-gsm-fr-vocoder/INSTALL b/gr-gsm-fr-vocoder/INSTALL new file mode 100644 index 00000000..54caf7c1 --- /dev/null +++ b/gr-gsm-fr-vocoder/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/gr-gsm-fr-vocoder/Makefile.am b/gr-gsm-fr-vocoder/Makefile.am new file mode 100644 index 00000000..9c64613e --- /dev/null +++ b/gr-gsm-fr-vocoder/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src +DIST_SUBDIRS = src diff --git a/gr-gsm-fr-vocoder/src/Makefile.am b/gr-gsm-fr-vocoder/src/Makefile.am new file mode 100644 index 00000000..122fc72c --- /dev/null +++ b/gr-gsm-fr-vocoder/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib python diff --git a/gr-gsm-fr-vocoder/src/lib/Makefile.am b/gr-gsm-fr-vocoder/src/lib/Makefile.am new file mode 100644 index 00000000..974604d9 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/Makefile.am @@ -0,0 +1,102 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = gsm . + +LIBS += $(GNURADIO_CORE_LIBS) + +# Install this stuff so that it ends up as the gnuradio.vocoder module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/vocoder + +ourpythondir = $(grpythondir)/vocoder +ourlibdir = $(grpyexecdir)/vocoder + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) + + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + + +LOCAL_IFILES = \ + gsm_full_rate.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _howto shared library +# and knows how to call our extensions. + +BUILT_SOURCES = \ + gsm_full_rate.cc \ + gsm_full_rate.py + +# This gets gsm_full_rate.py installed in the right place +ourpython_PYTHON = \ + __init__.py \ + gsm_full_rate.py + +ourlib_LTLIBRARIES = _gsm_full_rate.la + +# These are the source files that go into the shared library +_gsm_full_rate_la_SOURCES = \ + gsm_fr_decode_ps.cc \ + gsm_fr_encode_sp.cc \ + gsm_full_rate.cc + + +# magic flags +_gsm_full_rate_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against the gsm library and the +# c++ standard library +_gsm_full_rate_la_LIBADD = \ + gsm/libgsm.la \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +gsm_full_rate.cc gsm_full_rate.py: gsm_full_rate.i $(ALL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module gsm_full_rate -o gsm_full_rate.cc $< + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + gsm_fr_decode_ps.h \ + gsm_fr_encode_sp.h + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done + diff --git a/gr-gsm-fr-vocoder/src/lib/__init__.py b/gr-gsm-fr-vocoder/src/lib/__init__.py new file mode 100644 index 00000000..dde84141 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/__init__.py @@ -0,0 +1,20 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/COPYRIGHT b/gr-gsm-fr-vocoder/src/lib/gsm/COPYRIGHT new file mode 100644 index 00000000..eba0e523 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/COPYRIGHT @@ -0,0 +1,16 @@ +Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, +Technische Universitaet Berlin + +Any use of this software is permitted provided that this notice is not +removed and that neither the authors nor the Technische Universitaet Berlin +are deemed to have made any representations as to the suitability of this +software for any purpose nor are held responsible for any defects of +this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +As a matter of courtesy, the authors request to be informed about uses +this software has found, about bugs in this software, and about any +improvements that may be of general interest. + +Berlin, 28.11.1994 +Jutta Degener +Carsten Bormann diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/Makefile.am b/gr-gsm-fr-vocoder/src/lib/gsm/Makefile.am new file mode 100644 index 00000000..0d718f38 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/Makefile.am @@ -0,0 +1,75 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Machine- or installation dependent flags you should configure to port + +SASR = -DSASR +######### Define SASR if >> is a signed arithmetic shift (-1 >> 1 == -1) + +MULHACK = -DUSE_FLOAT_MUL +######### Define this if your host multiplies floats faster than integers, +######### e.g. on a SPARCstation. + +FAST = -DFAST +######### Define together with USE_FLOAT_MUL to enable the GSM library's +######### approximation option for incorrect, but good-enough results. + +# LTP_CUT = -DLTP_CUT +LTP_CUT = +######### Define to enable the GSM library's long-term correlation +######### approximation option---faster, but worse; works for +######### both integer and floating point multiplications. +######### This flag is still in the experimental stage. + +OPTIONS = $(SASR) $(MULHACK) $(FAST) $(LTP_CUT) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) -DNeedFunctionPrototypes=1 $(OPTIONS) + +noinst_LTLIBRARIES = libgsm.la + +libgsm_la_SOURCES = \ + add.c \ + code.c \ + debug.c \ + decode.c \ + gsm_create.c \ + gsm_decode.c \ + gsm_destroy.c \ + gsm_encode.c \ + gsm_explode.c \ + gsm_implode.c \ + gsm_option.c \ + gsm_print.c \ + long_term.c \ + lpc.c \ + preprocess.c \ + rpe.c \ + short_term.c \ + table.c + +noinst_HEADERS = \ + config.h \ + gsm.h \ + private.h \ + proto.h \ + unproto.h diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/README b/gr-gsm-fr-vocoder/src/lib/gsm/README new file mode 100644 index 00000000..1927d878 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/README @@ -0,0 +1,4 @@ +This code was extracted from gsm-1.0-pl10.tar.gz +See COPYRIGHT for the copyright. + +See http://kbs.cs.tu-berlin.de/~jutta/toast.html for docs. diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/README.orig b/gr-gsm-fr-vocoder/src/lib/gsm/README.orig new file mode 100644 index 00000000..cb6af85c --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/README.orig @@ -0,0 +1,37 @@ + +GSM 06.10 13 kbit/s RPE/LTP speech compression available +-------------------------------------------------------- + +The Communications and Operating Systems Research Group (KBS) at the +Technische Universitaet Berlin is currently working on a set of +UNIX-based tools for computer-mediated telecooperation that will be +made freely available. + +As part of this effort we are publishing an implementation of the +European GSM 06.10 provisional standard for full-rate speech +transcoding, prI-ETS 300 036, which uses RPE/LTP (residual pulse +excitation/long term prediction) coding at 13 kbit/s. + +GSM 06.10 compresses frames of 160 13-bit samples (8 kHz sampling +rate, i.e. a frame rate of 50 Hz) into 260 bits; for compatibility +with typical UNIX applications, our implementation turns frames of 160 +16-bit linear samples into 33-byte frames (1650 Bytes/s). +The quality of the algorithm is good enough for reliable speaker +recognition; even music often survives transcoding in recognizable +form (given the bandwidth limitations of 8 kHz sampling rate). + +The interfaces offered are a front end modelled after compress(1), and +a library API. Compression and decompression run faster than realtime +on most SPARCstations. The implementation has been verified against the +ETSI standard test patterns. + +Jutta Degener (jutta@cs.tu-berlin.de) +Carsten Bormann (cabo@cs.tu-berlin.de) + +Communications and Operating Systems Research Group, TU Berlin +Fax: +49.30.31425156, Phone: +49.30.31424315 + +-- +Copyright 1992 by Jutta Degener and Carsten Bormann, Technische +Universitaet Berlin. See the accompanying file "COPYRIGHT" for +details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/add.c b/gr-gsm-fr-vocoder/src/lib/gsm/add.c new file mode 100644 index 00000000..21ccfabe --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/add.c @@ -0,0 +1,235 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +/* + * See private.h for the more commonly used macro versions. + */ + +#include +#include + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +#define saturate(x) \ + ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) + +word gsm_add P2((a,b), word a, word b) +{ + longword sum = (longword)a + (longword)b; + return saturate(sum); +} + +word gsm_sub P2((a,b), word a, word b) +{ + longword diff = (longword)a - (longword)b; + return saturate(diff); +} + +word gsm_mult P2((a,b), word a, word b) +{ + if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; + else return SASR( (longword)a * (longword)b, 15 ); +} + +word gsm_mult_r P2((a,b), word a, word b) +{ + if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; + else { + longword prod = (longword)a * (longword)b + 16384; + prod >>= 15; + return prod & 0xFFFF; + } +} + +word gsm_abs P1((a), word a) +{ + return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; +} + +longword gsm_L_mult P2((a,b),word a, word b) +{ + assert( a != MIN_WORD || b != MIN_WORD ); + return ((longword)a * (longword)b) << 1; +} + +longword gsm_L_add P2((a,b), longword a, longword b) +{ + if (a < 0) { + if (b >= 0) return a + b; + else { + ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); + return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; + } + } + else if (b <= 0) return a + b; + else { + ulongword A = (ulongword)a + (ulongword)b; + return A > MAX_LONGWORD ? MAX_LONGWORD : A; + } +} + +longword gsm_L_sub P2((a,b), longword a, longword b) +{ + if (a >= 0) { + if (b >= 0) return a - b; + else { + /* a>=0, b<0 */ + + ulongword A = (ulongword)a + -(b + 1); + return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); + } + } + else if (b <= 0) return a - b; + else { + /* a<0, b>0 */ + + ulongword A = (ulongword)-(a + 1) + b; + return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; + } +} + +static unsigned char const bitoff[ 256 ] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +word gsm_norm P1((a), longword a ) +/* + * the number of left shifts needed to normalize the 32 bit + * variable L_var1 for positive values on the interval + * + * with minimum of + * minimum of 1073741824 (01000000000000000000000000000000) and + * maximum of 2147483647 (01111111111111111111111111111111) + * + * + * and for negative values on the interval with + * minimum of -2147483648 (-10000000000000000000000000000000) and + * maximum of -1073741824 ( -1000000000000000000000000000000). + * + * in order to normalize the result, the following + * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); + * + * (That's 'ffs', only from the left, not the right..) + */ +{ + assert(a != 0); + + if (a < 0) { + if (a <= -1073741824) return 0; + a = ~a; + } + + return a & 0xffff0000 + ? ( a & 0xff000000 + ? -1 + bitoff[ 0xFF & (a >> 24) ] + : 7 + bitoff[ 0xFF & (a >> 16) ] ) + : ( a & 0xff00 + ? 15 + bitoff[ 0xFF & (a >> 8) ] + : 23 + bitoff[ 0xFF & a ] ); +} + +longword gsm_L_asl P2((a,n), longword a, int n) +{ + if (n >= 32) return 0; + if (n <= -32) return -(a < 0); + if (n < 0) return gsm_L_asr(a, -n); + return a << n; +} + +word gsm_asl P2((a,n), word a, int n) +{ + if (n >= 16) return 0; + if (n <= -16) return -(a < 0); + if (n < 0) return gsm_asr(a, -n); + return a << n; +} + +longword gsm_L_asr P2((a,n), longword a, int n) +{ + if (n >= 32) return -(a < 0); + if (n <= -32) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(longword)( -(ulongword)a >> n ); +# endif +} + +word gsm_asr P2((a,n), word a, int n) +{ + if (n >= 16) return -(a < 0); + if (n <= -16) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(word)( -(uword)a >> n ); +# endif +} + +/* + * (From p. 46, end of section 4.2.5) + * + * NOTE: The following lines gives [sic] one correct implementation + * of the div(num, denum) arithmetic operation. Compute div + * which is the integer division of num by denum: with denum + * >= num > 0 + */ + +word gsm_div P2((num,denum), word num, word denum) +{ + longword L_num = num; + longword L_denum = denum; + word div = 0; + int k = 15; + + /* The parameter num sometimes becomes zero. + * Although this is explicitly guarded against in 4.2.5, + * we assume that the result should then be zero as well. + */ + + /* assert(num != 0); */ + + assert(num >= 0 && denum >= num); + if (num == 0) + return 0; + + while (k--) { + div <<= 1; + L_num <<= 1; + + if (L_num >= L_denum) { + L_num -= L_denum; + div++; + } + } + + return div; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/code.c b/gr-gsm-fr-vocoder/src/lib/gsm/code.c new file mode 100644 index 00000000..73955429 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/code.c @@ -0,0 +1,99 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "config.h" + + +#ifdef HAS_STDLIB_H +#include +#else +# include "proto.h" + extern char * memcpy P((char *, char *, int)); +#endif + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +/* + * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER + */ + +void Gsm_Coder P8((S,s,LARc,Nc,bc,Mc,xmaxc,xMc), + + struct gsm_state * S, + + word * s, /* [0..159] samples IN */ + +/* + * The RPE-LTD coder works on a frame by frame basis. The length of + * the frame is equal to 160 samples. Some computations are done + * once per frame to produce at the output of the coder the + * LARc[1..8] parameters which are the coded LAR coefficients and + * also to realize the inverse filtering operation for the entire + * frame (160 samples of signal d[0..159]). These parts produce at + * the output of the coder: + */ + + word * LARc, /* [0..7] LAR coefficients OUT */ + +/* + * Procedure 4.2.11 to 4.2.18 are to be executed four times per + * frame. That means once for each sub-segment RPE-LTP analysis of + * 40 samples. These parts produce at the output of the coder: + */ + + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */ +) +{ + int k; + word * dp = S->dp0 + 120; /* [ -120...-1 ] */ + word * dpp = dp; /* [ 0...39 ] */ + + static word e[50]; + + word so[160]; + + Gsm_Preprocess (S, s, so); + Gsm_LPC_Analysis (S, so, LARc); + Gsm_Short_Term_Analysis_Filter (S, LARc, so); + + for (k = 0; k <= 3; k++, xMc += 13) { + + Gsm_Long_Term_Predictor ( S, + so+k*40, /* d [0..39] IN */ + dp, /* dp [-120..-1] IN */ + e + 5, /* e [0..39] OUT */ + dpp, /* dpp [0..39] OUT */ + Nc++, + bc++); + + Gsm_RPE_Encoding ( S, + e + 5, /* e ][0..39][ IN/OUT */ + xmaxc++, Mc++, xMc ); + /* + * Gsm_Update_of_reconstructed_short_time_residual_signal + * ( dpp, e + 5, dp ); + */ + + { register int i; + register longword ltmp; + for (i = 0; i <= 39; i++) + dp[ i ] = GSM_ADD( e[5 + i], dpp[i] ); + } + dp += 40; + dpp += 40; + + } + (void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160), + 120 * sizeof(*S->dp0) ); +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/config.h b/gr-gsm-fr-vocoder/src/lib/gsm/config.h new file mode 100644 index 00000000..2a962ac7 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/config.h @@ -0,0 +1,37 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#undef SIGHANDLER_T /* signal handlers are void */ +#undef HAS_SYSV_SIGNAL /* sigs not blocked/reset? */ + +#define HAS_STDLIB_H 1 /* /usr/include/stdlib.h */ +#undef HAS_LIMITS_H /* /usr/include/limits.h */ +#define HAS_FCNTL_H 1 /* /usr/include/fcntl.h */ +#undef HAS_ERRNO_DECL /* errno.h declares errno */ + +#define HAS_FSTAT 1 /* fstat syscall */ +#define HAS_FCHMOD 1 /* fchmod syscall */ +#define HAS_CHMOD 1 /* chmod syscall */ +#define HAS_FCHOWN 1 /* fchown syscall */ +#define HAS_CHOWN 1 /* chown syscall */ +#undef HAS__FSETMODE /* _fsetmode -- set file mode */ + +#define HAS_STRING_H 1 /* /usr/include/string.h */ +#undef HAS_STRINGS_H /* /usr/include/strings.h */ + +#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */ +#define HAS_UTIME 1 /* POSIX utime(path, times) */ +#undef HAS_UTIMES /* use utimes() syscall instead */ +#define HAS_UTIME_H 1 /* UTIME header file */ +#undef HAS_UTIMBUF /* struct utimbuf */ +#undef HAS_UTIMEUSEC /* microseconds in utimbuf? */ + +#endif /* CONFIG_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/debug.c b/gr-gsm-fr-vocoder/src/lib/gsm/debug.c new file mode 100644 index 00000000..e0521042 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/debug.c @@ -0,0 +1,76 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#ifndef NDEBUG + +/* If NDEBUG _is_ defined and no debugging should be performed, + * calls to functions in this module are #defined to nothing + * in private.h. + */ + +#include +#include "proto.h" + +void gsm_debug_words P4( (name, from, to, ptr), + char * name, + int from, + int to, + word * ptr) +{ + int nprinted = 0; + + fprintf( stderr, "%s [%d .. %d]: ", name, from, to ); + while (from <= to) { + fprintf(stderr, "%d ", ptr[ from ] ); + from++; + if (nprinted++ >= 7) { + nprinted = 0; + if (from < to) putc('\n', stderr); + } + } + putc('\n', stderr); +} + +void gsm_debug_longwords P4( (name, from, to, ptr), + char * name, + int from, + int to, + longword * ptr) +{ + int nprinted = 0; + + fprintf( stderr, "%s [%d .. %d]: ", name, from, to ); + while (from <= to) { + + fprintf(stderr, "%ld ", ptr[ from ] ); + from++; + if (nprinted++ >= 7) { + nprinted = 0; + if (from < to) putc('\n', stderr); + } + } + putc('\n', stderr); +} + +void gsm_debug_longword P2( (name, value), + char * name, + longword value ) +{ + fprintf(stderr, "%s: %ld\n", name, (long)value ); +} + +void gsm_debug_word P2( (name, value), + char * name, + word value ) +{ + fprintf(stderr, "%s: %ld\n", name, (long)value); +} + +#endif diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/decode.c b/gr-gsm-fr-vocoder/src/lib/gsm/decode.c new file mode 100644 index 00000000..34e55866 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/decode.c @@ -0,0 +1,63 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +/* + * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER + */ + +static void Postprocessing P2((S,s), + struct gsm_state * S, + register word * s) +{ + register int k; + register word msr = S->msr; + register longword ltmp; /* for GSM_ADD */ + register word tmp; + + for (k = 160; k--; s++) { + tmp = GSM_MULT_R( msr, 28180 ); + msr = GSM_ADD(*s, tmp); /* Deemphasis */ + *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ + } + S->msr = msr; +} + +void Gsm_Decoder P8((S,LARcr, Ncr,bcr,Mcr,xmaxcr,xMcr,s), + struct gsm_state * S, + + word * LARcr, /* [0..7] IN */ + + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + + word * s) /* [0..159] OUT */ +{ + int j, k; + word erp[40], wt[160]; + word * drp = S->dp0 + 120; + + for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { + + Gsm_RPE_Decoding( S, *xmaxcr, *Mcr, xMcr, erp ); + Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); + + for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; + } + + Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); + Postprocessing(S, s); +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm.h b/gr-gsm-fr-vocoder/src/lib/gsm/gsm.h new file mode 100644 index 00000000..990e42af --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm.h @@ -0,0 +1,73 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef GSM_H +#define GSM_H + +#ifdef __cplusplus +# define NeedFunctionPrototypes 1 +#endif + +#if __STDC__ +# define NeedFunctionPrototypes 1 +#endif + +#ifdef _NO_PROTO +# undef NeedFunctionPrototypes +#endif + +#ifdef NeedFunctionPrototypes +# include /* for FILE * */ +#endif + +#undef GSM_P +#if NeedFunctionPrototypes +# define GSM_P( protos ) protos +#else +# define GSM_P( protos ) ( /* protos */ ) +#endif + +/* + * Interface + */ + +typedef struct gsm_state * gsm; +typedef short gsm_signal; /* signed 16 bit */ +typedef unsigned char gsm_byte; +typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ + +#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ + +#define GSM_PATCHLEVEL 10 +#define GSM_MINOR 0 +#define GSM_MAJOR 1 + +#define GSM_OPT_VERBOSE 1 +#define GSM_OPT_FAST 2 +#define GSM_OPT_LTP_CUT 3 +#define GSM_OPT_WAV49 4 +#define GSM_OPT_FRAME_INDEX 5 +#define GSM_OPT_FRAME_CHAIN 6 + +#define GSM_SAMPLES_PER_FRAME 160 + +extern gsm gsm_create GSM_P((void)); +extern void gsm_destroy GSM_P((gsm)); + +extern int gsm_print GSM_P((FILE *, gsm, gsm_byte *)); +extern int gsm_option GSM_P((gsm, int, int *)); + +extern void gsm_encode GSM_P((gsm, gsm_signal *, gsm_byte *)); +extern int gsm_decode GSM_P((gsm, gsm_byte *, gsm_signal *)); + +extern int gsm_explode GSM_P((gsm, gsm_byte *, gsm_signal *)); +extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *)); + +#undef GSM_P + +#endif /* GSM_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_create.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_create.c new file mode 100644 index 00000000..a59aa2f2 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_create.c @@ -0,0 +1,45 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +static char const ident[] = "$Header$"; + +#include "config.h" + +#ifdef HAS_STRING_H +#include +#else +# include "proto.h" + extern char * memset P((char *, int, int)); +#endif + +#ifdef HAS_STDLIB_H +# include +#else +# ifdef HAS_MALLOC_H +# include +# else + extern char * malloc(); +# endif +#endif + +#include + +#include "gsm.h" +#include "private.h" +#include "proto.h" + +gsm gsm_create P0() +{ + gsm r; + + r = (gsm)malloc(sizeof(struct gsm_state)); + if (!r) return r; + + memset((char *)r, 0, sizeof(*r)); + r->nrp = 40; + + return r; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_decode.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_decode.c new file mode 100644 index 00000000..7318ba2d --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_decode.c @@ -0,0 +1,361 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_decode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + s->frame_index = !s->frame_index; + if (s->frame_index) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + Nc[0] = (*c >> 1) & 0x7F; + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + Mc[0] = (*c >> 5) & 0x3; + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + Nc[1] = (*c >> 1) & 0x7F; + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + Mc[1] = (*c >> 5) & 0x3; + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + Nc[2] = (*c >> 1) & 0x7F; + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + Mc[2] = (*c >> 5) & 0x3; + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + Nc[3] = (*c >> 1) & 0x7F; + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + Mc[3] = (*c >> 5) & 0x3; + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + } + + Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); + + return 0; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_destroy.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_destroy.c new file mode 100644 index 00000000..4807c0ac --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_destroy.c @@ -0,0 +1,26 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "gsm.h" +#include "config.h" +#include "proto.h" + +#ifdef HAS_STDLIB_H +# include +#else +# ifdef HAS_MALLOC_H +# include +# else + extern void free(); +# endif +#endif + +void gsm_destroy P1((S), gsm S) +{ + if (S) free((char *)S); +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_encode.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_encode.c new file mode 100644 index 00000000..62338300 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_encode.c @@ -0,0 +1,451 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +void gsm_encode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); + + + /* variable size + + GSM_MAGIC 4 + + LARc[0] 6 + LARc[1] 6 + LARc[2] 5 + LARc[3] 5 + LARc[4] 4 + LARc[5] 4 + LARc[6] 3 + LARc[7] 3 + + Nc[0] 7 + bc[0] 2 + Mc[0] 2 + xmaxc[0] 6 + xmc[0] 3 + xmc[1] 3 + xmc[2] 3 + xmc[3] 3 + xmc[4] 3 + xmc[5] 3 + xmc[6] 3 + xmc[7] 3 + xmc[8] 3 + xmc[9] 3 + xmc[10] 3 + xmc[11] 3 + xmc[12] 3 + + Nc[1] 7 + bc[1] 2 + Mc[1] 2 + xmaxc[1] 6 + xmc[13] 3 + xmc[14] 3 + xmc[15] 3 + xmc[16] 3 + xmc[17] 3 + xmc[18] 3 + xmc[19] 3 + xmc[20] 3 + xmc[21] 3 + xmc[22] 3 + xmc[23] 3 + xmc[24] 3 + xmc[25] 3 + + Nc[2] 7 + bc[2] 2 + Mc[2] 2 + xmaxc[2] 6 + xmc[26] 3 + xmc[27] 3 + xmc[28] 3 + xmc[29] 3 + xmc[30] 3 + xmc[31] 3 + xmc[32] 3 + xmc[33] 3 + xmc[34] 3 + xmc[35] 3 + xmc[36] 3 + xmc[37] 3 + xmc[38] 3 + + Nc[3] 7 + bc[3] 2 + Mc[3] 2 + xmaxc[3] 6 + xmc[39] 3 + xmc[40] 3 + xmc[41] 3 + xmc[42] 3 + xmc[43] 3 + xmc[44] 3 + xmc[45] 3 + xmc[46] 3 + xmc[47] 3 + xmc[48] 3 + xmc[49] 3 + xmc[50] 3 + xmc[51] 3 + */ + +#ifdef WAV49 + + if (s->wav_fmt) { + s->frame_index = !s->frame_index; + if (s->frame_index) { + + uword sr; + + sr = 0; + sr = sr >> 6 | LARc[0] << 10; + sr = sr >> 6 | LARc[1] << 10; + *c++ = sr >> 4; + sr = sr >> 5 | LARc[2] << 11; + *c++ = sr >> 7; + sr = sr >> 5 | LARc[3] << 11; + sr = sr >> 4 | LARc[4] << 12; + *c++ = sr >> 6; + sr = sr >> 4 | LARc[5] << 12; + sr = sr >> 3 | LARc[6] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | LARc[7] << 13; + sr = sr >> 7 | Nc[0] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[0] << 14; + sr = sr >> 2 | Mc[0] << 14; + sr = sr >> 6 | xmaxc[0] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[0] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[1] << 13; + sr = sr >> 3 | xmc[2] << 13; + sr = sr >> 3 | xmc[3] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[4] << 13; + sr = sr >> 3 | xmc[5] << 13; + sr = sr >> 3 | xmc[6] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[7] << 13; + sr = sr >> 3 | xmc[8] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[9] << 13; + sr = sr >> 3 | xmc[10] << 13; + sr = sr >> 3 | xmc[11] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[12] << 13; + sr = sr >> 7 | Nc[1] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[1] << 14; + sr = sr >> 2 | Mc[1] << 14; + sr = sr >> 6 | xmaxc[1] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[13] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[14] << 13; + sr = sr >> 3 | xmc[15] << 13; + sr = sr >> 3 | xmc[16] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[17] << 13; + sr = sr >> 3 | xmc[18] << 13; + sr = sr >> 3 | xmc[19] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[20] << 13; + sr = sr >> 3 | xmc[21] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[22] << 13; + sr = sr >> 3 | xmc[23] << 13; + sr = sr >> 3 | xmc[24] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[25] << 13; + sr = sr >> 7 | Nc[2] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[2] << 14; + sr = sr >> 2 | Mc[2] << 14; + sr = sr >> 6 | xmaxc[2] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[26] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[27] << 13; + sr = sr >> 3 | xmc[28] << 13; + sr = sr >> 3 | xmc[29] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[30] << 13; + sr = sr >> 3 | xmc[31] << 13; + sr = sr >> 3 | xmc[32] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[33] << 13; + sr = sr >> 3 | xmc[34] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[35] << 13; + sr = sr >> 3 | xmc[36] << 13; + sr = sr >> 3 | xmc[37] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[38] << 13; + sr = sr >> 7 | Nc[3] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[3] << 14; + sr = sr >> 2 | Mc[3] << 14; + sr = sr >> 6 | xmaxc[3] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[39] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[40] << 13; + sr = sr >> 3 | xmc[41] << 13; + sr = sr >> 3 | xmc[42] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[43] << 13; + sr = sr >> 3 | xmc[44] << 13; + sr = sr >> 3 | xmc[45] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[46] << 13; + sr = sr >> 3 | xmc[47] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[48] << 13; + sr = sr >> 3 | xmc[49] << 13; + sr = sr >> 3 | xmc[50] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[51] << 13; + sr = sr >> 4; + *c = sr >> 8; + s->frame_chain = *c; + } + else { + uword sr; + + sr = 0; + sr = sr >> 4 | s->frame_chain << 12; + sr = sr >> 6 | LARc[0] << 10; + *c++ = sr >> 6; + sr = sr >> 6 | LARc[1] << 10; + *c++ = sr >> 8; + sr = sr >> 5 | LARc[2] << 11; + sr = sr >> 5 | LARc[3] << 11; + *c++ = sr >> 6; + sr = sr >> 4 | LARc[4] << 12; + sr = sr >> 4 | LARc[5] << 12; + *c++ = sr >> 6; + sr = sr >> 3 | LARc[6] << 13; + sr = sr >> 3 | LARc[7] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[0] << 9; + sr = sr >> 2 | bc[0] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[0] << 14; + sr = sr >> 6 | xmaxc[0] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[0] << 13; + sr = sr >> 3 | xmc[1] << 13; + sr = sr >> 3 | xmc[2] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[3] << 13; + sr = sr >> 3 | xmc[4] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[5] << 13; + sr = sr >> 3 | xmc[6] << 13; + sr = sr >> 3 | xmc[7] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[8] << 13; + sr = sr >> 3 | xmc[9] << 13; + sr = sr >> 3 | xmc[10] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[11] << 13; + sr = sr >> 3 | xmc[12] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[1] << 9; + sr = sr >> 2 | bc[1] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[1] << 14; + sr = sr >> 6 | xmaxc[1] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[13] << 13; + sr = sr >> 3 | xmc[14] << 13; + sr = sr >> 3 | xmc[15] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[16] << 13; + sr = sr >> 3 | xmc[17] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[18] << 13; + sr = sr >> 3 | xmc[19] << 13; + sr = sr >> 3 | xmc[20] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[21] << 13; + sr = sr >> 3 | xmc[22] << 13; + sr = sr >> 3 | xmc[23] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[24] << 13; + sr = sr >> 3 | xmc[25] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[2] << 9; + sr = sr >> 2 | bc[2] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[2] << 14; + sr = sr >> 6 | xmaxc[2] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[26] << 13; + sr = sr >> 3 | xmc[27] << 13; + sr = sr >> 3 | xmc[28] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[29] << 13; + sr = sr >> 3 | xmc[30] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[31] << 13; + sr = sr >> 3 | xmc[32] << 13; + sr = sr >> 3 | xmc[33] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[34] << 13; + sr = sr >> 3 | xmc[35] << 13; + sr = sr >> 3 | xmc[36] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[37] << 13; + sr = sr >> 3 | xmc[38] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[3] << 9; + sr = sr >> 2 | bc[3] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[3] << 14; + sr = sr >> 6 | xmaxc[3] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[39] << 13; + sr = sr >> 3 | xmc[40] << 13; + sr = sr >> 3 | xmc[41] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[42] << 13; + sr = sr >> 3 | xmc[43] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[44] << 13; + sr = sr >> 3 | xmc[45] << 13; + sr = sr >> 3 | xmc[46] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[47] << 13; + sr = sr >> 3 | xmc[48] << 13; + sr = sr >> 3 | xmc[49] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[50] << 13; + sr = sr >> 3 | xmc[51] << 13; + *c++ = sr >> 8; + } + } + + else + +#endif /* WAV49 */ + { + + *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ + | ((LARc[0] >> 2) & 0xF); + *c++ = ((LARc[0] & 0x3) << 6) + | (LARc[1] & 0x3F); + *c++ = ((LARc[2] & 0x1F) << 3) + | ((LARc[3] >> 2) & 0x7); + *c++ = ((LARc[3] & 0x3) << 6) + | ((LARc[4] & 0xF) << 2) + | ((LARc[5] >> 2) & 0x3); + *c++ = ((LARc[5] & 0x3) << 6) + | ((LARc[6] & 0x7) << 3) + | (LARc[7] & 0x7); + *c++ = ((Nc[0] & 0x7F) << 1) + | ((bc[0] >> 1) & 0x1); + *c++ = ((bc[0] & 0x1) << 7) + | ((Mc[0] & 0x3) << 5) + | ((xmaxc[0] >> 1) & 0x1F); + *c++ = ((xmaxc[0] & 0x1) << 7) + | ((xmc[0] & 0x7) << 4) + | ((xmc[1] & 0x7) << 1) + | ((xmc[2] >> 2) & 0x1); + *c++ = ((xmc[2] & 0x3) << 6) + | ((xmc[3] & 0x7) << 3) + | (xmc[4] & 0x7); + *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ + | ((xmc[6] & 0x7) << 2) + | ((xmc[7] >> 1) & 0x3); + *c++ = ((xmc[7] & 0x1) << 7) + | ((xmc[8] & 0x7) << 4) + | ((xmc[9] & 0x7) << 1) + | ((xmc[10] >> 2) & 0x1); + *c++ = ((xmc[10] & 0x3) << 6) + | ((xmc[11] & 0x7) << 3) + | (xmc[12] & 0x7); + *c++ = ((Nc[1] & 0x7F) << 1) + | ((bc[1] >> 1) & 0x1); + *c++ = ((bc[1] & 0x1) << 7) + | ((Mc[1] & 0x3) << 5) + | ((xmaxc[1] >> 1) & 0x1F); + *c++ = ((xmaxc[1] & 0x1) << 7) + | ((xmc[13] & 0x7) << 4) + | ((xmc[14] & 0x7) << 1) + | ((xmc[15] >> 2) & 0x1); + *c++ = ((xmc[15] & 0x3) << 6) + | ((xmc[16] & 0x7) << 3) + | (xmc[17] & 0x7); + *c++ = ((xmc[18] & 0x7) << 5) + | ((xmc[19] & 0x7) << 2) + | ((xmc[20] >> 1) & 0x3); + *c++ = ((xmc[20] & 0x1) << 7) + | ((xmc[21] & 0x7) << 4) + | ((xmc[22] & 0x7) << 1) + | ((xmc[23] >> 2) & 0x1); + *c++ = ((xmc[23] & 0x3) << 6) + | ((xmc[24] & 0x7) << 3) + | (xmc[25] & 0x7); + *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ + | ((bc[2] >> 1) & 0x1); + *c++ = ((bc[2] & 0x1) << 7) + | ((Mc[2] & 0x3) << 5) + | ((xmaxc[2] >> 1) & 0x1F); + *c++ = ((xmaxc[2] & 0x1) << 7) + | ((xmc[26] & 0x7) << 4) + | ((xmc[27] & 0x7) << 1) + | ((xmc[28] >> 2) & 0x1); + *c++ = ((xmc[28] & 0x3) << 6) + | ((xmc[29] & 0x7) << 3) + | (xmc[30] & 0x7); + *c++ = ((xmc[31] & 0x7) << 5) + | ((xmc[32] & 0x7) << 2) + | ((xmc[33] >> 1) & 0x3); + *c++ = ((xmc[33] & 0x1) << 7) + | ((xmc[34] & 0x7) << 4) + | ((xmc[35] & 0x7) << 1) + | ((xmc[36] >> 2) & 0x1); + *c++ = ((xmc[36] & 0x3) << 6) + | ((xmc[37] & 0x7) << 3) + | (xmc[38] & 0x7); + *c++ = ((Nc[3] & 0x7F) << 1) + | ((bc[3] >> 1) & 0x1); + *c++ = ((bc[3] & 0x1) << 7) + | ((Mc[3] & 0x3) << 5) + | ((xmaxc[3] >> 1) & 0x1F); + *c++ = ((xmaxc[3] & 0x1) << 7) + | ((xmc[39] & 0x7) << 4) + | ((xmc[40] & 0x7) << 1) + | ((xmc[41] >> 2) & 0x1); + *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ + | ((xmc[42] & 0x7) << 3) + | (xmc[43] & 0x7); + *c++ = ((xmc[44] & 0x7) << 5) + | ((xmc[45] & 0x7) << 2) + | ((xmc[46] >> 1) & 0x3); + *c++ = ((xmc[46] & 0x1) << 7) + | ((xmc[47] & 0x7) << 4) + | ((xmc[48] & 0x7) << 1) + | ((xmc[49] >> 2) & 0x1); + *c++ = ((xmc[49] & 0x3) << 6) + | ((xmc[50] & 0x7) << 3) + | (xmc[51] & 0x7); + + } +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_explode.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_explode.c new file mode 100644 index 00000000..a906fc2e --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_explode.c @@ -0,0 +1,417 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +int gsm_explode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) +{ +# define LARc target +# define Nc *((gsm_signal (*) [17])(target + 8)) +# define bc *((gsm_signal (*) [17])(target + 9)) +# define Mc *((gsm_signal (*) [17])(target + 10)) +# define xmaxc *((gsm_signal (*) [17])(target + 11)) + + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + if (s->frame_index == 1) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 12) + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 29 - 13) + + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; + +#undef xmc +#define xmc (target + 46 - 26) + + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 12) + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 29 - 13) + + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 46 - 26) + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; + +#undef xmc +#define xmc (target + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + + Nc[0] = (*c >> 1) & 0x7F; + + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + + Mc[0] = (*c >> 5) & 0x3; + + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 12) + + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + + Nc[1] = (*c >> 1) & 0x7F; + + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + + Mc[1] = (*c >> 5) & 0x3; + + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 29 - 13) + + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + + Nc[2] = (*c >> 1) & 0x7F; + + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + + Mc[2] = (*c >> 5) & 0x3; + + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 46 - 26) + + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + + Nc[3] = (*c >> 1) & 0x7F; + + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + + Mc[3] = (*c >> 5) & 0x3; + + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 63 - 39) + + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + } + + return 0; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_implode.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_implode.c new file mode 100644 index 00000000..453b8cf3 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_implode.c @@ -0,0 +1,515 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +void gsm_implode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) +{ + /* variable size index + + GSM_MAGIC 4 - + + LARc[0] 6 0 + LARc[1] 6 1 + LARc[2] 5 2 + LARc[3] 5 3 + LARc[4] 4 4 + LARc[5] 4 5 + LARc[6] 3 6 + LARc[7] 3 7 + + Nc[0] 7 8 + bc[0] 2 9 + Mc[0] 2 10 + xmaxc[0] 6 11 + xmc[0] 3 12 + xmc[1] 3 13 + xmc[2] 3 14 + xmc[3] 3 15 + xmc[4] 3 16 + xmc[5] 3 17 + xmc[6] 3 18 + xmc[7] 3 19 + xmc[8] 3 20 + xmc[9] 3 21 + xmc[10] 3 22 + xmc[11] 3 23 + xmc[12] 3 24 + + Nc[1] 7 25 + bc[1] 2 26 + Mc[1] 2 27 + xmaxc[1] 6 28 + xmc[13] 3 29 + xmc[14] 3 30 + xmc[15] 3 31 + xmc[16] 3 32 + xmc[17] 3 33 + xmc[18] 3 34 + xmc[19] 3 35 + xmc[20] 3 36 + xmc[21] 3 37 + xmc[22] 3 38 + xmc[23] 3 39 + xmc[24] 3 40 + xmc[25] 3 41 + + Nc[2] 7 42 + bc[2] 2 43 + Mc[2] 2 44 + xmaxc[2] 6 45 + xmc[26] 3 46 + xmc[27] 3 47 + xmc[28] 3 48 + xmc[29] 3 49 + xmc[30] 3 50 + xmc[31] 3 51 + xmc[32] 3 52 + xmc[33] 3 53 + xmc[34] 3 54 + xmc[35] 3 55 + xmc[36] 3 56 + xmc[37] 3 57 + xmc[38] 3 58 + + Nc[3] 7 59 + bc[3] 2 60 + Mc[3] 2 61 + xmaxc[3] 6 62 + xmc[39] 3 63 + xmc[40] 3 64 + xmc[41] 3 65 + xmc[42] 3 66 + xmc[43] 3 67 + xmc[44] 3 68 + xmc[45] 3 69 + xmc[46] 3 70 + xmc[47] 3 71 + xmc[48] 3 72 + xmc[49] 3 73 + xmc[50] 3 74 + xmc[51] 3 75 + */ + + /* There are 76 parameters per frame. The first eight are + * unique. The remaining 68 are four identical subframes of + * 17 parameters each. gsm_implode converts from a representation + * of these parameters as values in one array of signed words + * to the "packed" version of a GSM frame. + */ + +# define LARc source +# define Nc *((gsm_signal (*) [17])(source + 8)) +# define bc *((gsm_signal (*) [17])(source + 9)) +# define Mc *((gsm_signal (*) [17])(source + 10)) +# define xmaxc *((gsm_signal (*) [17])(source + 11)) + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + if (s->frame_index == 0) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 12) + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 29 - 13) + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 46 - 26) + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 12) + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 29 - 13) + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 46 - 26) + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + + *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ + | ((LARc[0] >> 2) & 0xF); + *c++ = ((LARc[0] & 0x3) << 6) + | (LARc[1] & 0x3F); + *c++ = ((LARc[2] & 0x1F) << 3) + | ((LARc[3] >> 2) & 0x7); + *c++ = ((LARc[3] & 0x3) << 6) + | ((LARc[4] & 0xF) << 2) + | ((LARc[5] >> 2) & 0x3); + *c++ = ((LARc[5] & 0x3) << 6) + | ((LARc[6] & 0x7) << 3) + | (LARc[7] & 0x7); + + + *c++ = ((Nc[0] & 0x7F) << 1) + + + | ((bc[0] >> 1) & 0x1); + *c++ = ((bc[0] & 0x1) << 7) + + + | ((Mc[0] & 0x3) << 5) + + | ((xmaxc[0] >> 1) & 0x1F); + *c++ = ((xmaxc[0] & 0x1) << 7) + +#undef xmc +#define xmc (source + 12) + + | ((xmc[0] & 0x7) << 4) + | ((xmc[1] & 0x7) << 1) + | ((xmc[2] >> 2) & 0x1); + *c++ = ((xmc[2] & 0x3) << 6) + | ((xmc[3] & 0x7) << 3) + | (xmc[4] & 0x7); + *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ + | ((xmc[6] & 0x7) << 2) + | ((xmc[7] >> 1) & 0x3); + *c++ = ((xmc[7] & 0x1) << 7) + | ((xmc[8] & 0x7) << 4) + | ((xmc[9] & 0x7) << 1) + | ((xmc[10] >> 2) & 0x1); + *c++ = ((xmc[10] & 0x3) << 6) + | ((xmc[11] & 0x7) << 3) + | (xmc[12] & 0x7); + + + *c++ = ((Nc[1] & 0x7F) << 1) + + + | ((bc[1] >> 1) & 0x1); + *c++ = ((bc[1] & 0x1) << 7) + + + | ((Mc[1] & 0x3) << 5) + + + | ((xmaxc[1] >> 1) & 0x1F); + *c++ = ((xmaxc[1] & 0x1) << 7) + +#undef xmc +#define xmc (source + 29 - 13) + + | ((xmc[13] & 0x7) << 4) + | ((xmc[14] & 0x7) << 1) + | ((xmc[15] >> 2) & 0x1); + *c++ = ((xmc[15] & 0x3) << 6) + | ((xmc[16] & 0x7) << 3) + | (xmc[17] & 0x7); + *c++ = ((xmc[18] & 0x7) << 5) + | ((xmc[19] & 0x7) << 2) + | ((xmc[20] >> 1) & 0x3); + *c++ = ((xmc[20] & 0x1) << 7) + | ((xmc[21] & 0x7) << 4) + | ((xmc[22] & 0x7) << 1) + | ((xmc[23] >> 2) & 0x1); + *c++ = ((xmc[23] & 0x3) << 6) + | ((xmc[24] & 0x7) << 3) + | (xmc[25] & 0x7); + + + *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ + + + | ((bc[2] >> 1) & 0x1); + *c++ = ((bc[2] & 0x1) << 7) + + + | ((Mc[2] & 0x3) << 5) + + + | ((xmaxc[2] >> 1) & 0x1F); + *c++ = ((xmaxc[2] & 0x1) << 7) + +#undef xmc +#define xmc (source + 46 - 26) + + | ((xmc[26] & 0x7) << 4) + | ((xmc[27] & 0x7) << 1) + | ((xmc[28] >> 2) & 0x1); + *c++ = ((xmc[28] & 0x3) << 6) + | ((xmc[29] & 0x7) << 3) + | (xmc[30] & 0x7); + *c++ = ((xmc[31] & 0x7) << 5) + | ((xmc[32] & 0x7) << 2) + | ((xmc[33] >> 1) & 0x3); + *c++ = ((xmc[33] & 0x1) << 7) + | ((xmc[34] & 0x7) << 4) + | ((xmc[35] & 0x7) << 1) + | ((xmc[36] >> 2) & 0x1); + *c++ = ((xmc[36] & 0x3) << 6) + | ((xmc[37] & 0x7) << 3) + | (xmc[38] & 0x7); + + + *c++ = ((Nc[3] & 0x7F) << 1) + + + | ((bc[3] >> 1) & 0x1); + *c++ = ((bc[3] & 0x1) << 7) + + + | ((Mc[3] & 0x3) << 5) + + + | ((xmaxc[3] >> 1) & 0x1F); + *c++ = ((xmaxc[3] & 0x1) << 7) + +#undef xmc +#define xmc (source + 63 - 39) + + | ((xmc[39] & 0x7) << 4) + | ((xmc[40] & 0x7) << 1) + | ((xmc[41] >> 2) & 0x1); + *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ + | ((xmc[42] & 0x7) << 3) + | (xmc[43] & 0x7); + *c++ = ((xmc[44] & 0x7) << 5) + | ((xmc[45] & 0x7) << 2) + | ((xmc[46] >> 1) & 0x3); + *c++ = ((xmc[46] & 0x1) << 7) + | ((xmc[47] & 0x7) << 4) + | ((xmc[48] & 0x7) << 1) + | ((xmc[49] >> 2) & 0x1); + *c++ = ((xmc[49] & 0x3) << 6) + | ((xmc[50] & 0x7) << 3) + | (xmc[51] & 0x7); + } +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_option.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_option.c new file mode 100644 index 00000000..28078013 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_option.c @@ -0,0 +1,69 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_option P3((r, opt, val), gsm r, int opt, int * val) +{ + int result = -1; + + switch (opt) { + case GSM_OPT_LTP_CUT: +#ifdef LTP_CUT + result = r->ltp_cut; + if (val) r->ltp_cut = *val; +#endif + break; + + case GSM_OPT_VERBOSE: +#ifndef NDEBUG + result = r->verbose; + if (val) r->verbose = *val; +#endif + break; + + case GSM_OPT_FAST: + +#if defined(FAST) && defined(USE_FLOAT_MUL) + result = r->fast; + if (val) r->fast = !!*val; +#endif + break; + + case GSM_OPT_FRAME_CHAIN: + +#ifdef WAV49 + result = r->frame_chain; + if (val) r->frame_chain = *val; +#endif + break; + + case GSM_OPT_FRAME_INDEX: + +#ifdef WAV49 + result = r->frame_index; + if (val) r->frame_index = *val; +#endif + break; + + case GSM_OPT_WAV49: + +#ifdef WAV49 + result = r->wav_fmt; + if (val) r->wav_fmt = !!*val; +#endif + break; + + default: + break; + } + return result; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/gsm_print.c b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_print.c new file mode 100644 index 00000000..af745bc4 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/gsm_print.c @@ -0,0 +1,167 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_print P3((f, s, c), FILE * f, gsm s, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + + + Nc[0] = (*c >> 1) & 0x7F; + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + Mc[0] = (*c >> 5) & 0x3; + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + + Nc[1] = (*c >> 1) & 0x7F; + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + Mc[1] = (*c >> 5) & 0x3; + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + + + Nc[2] = (*c >> 1) & 0x7F; + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + Mc[2] = (*c >> 5) & 0x3; + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + + Nc[3] = (*c >> 1) & 0x7F; + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + Mc[3] = (*c >> 5) & 0x3; + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + + fprintf(f, + "LARc:\t%2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d\n", + LARc[0],LARc[1],LARc[2],LARc[3],LARc[4],LARc[5],LARc[6],LARc[7]); + + fprintf(f, "#1: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[0], bc[0], Mc[0], xmaxc[0]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[0],xmc[1],xmc[2],xmc[3],xmc[4],xmc[5],xmc[6], + xmc[7],xmc[8],xmc[9],xmc[10],xmc[11],xmc[12] ); + + fprintf(f, "#2: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[1], bc[1], Mc[1], xmaxc[1]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[13+0],xmc[13+1],xmc[13+2],xmc[13+3],xmc[13+4],xmc[13+5], + xmc[13+6], xmc[13+7],xmc[13+8],xmc[13+9],xmc[13+10],xmc[13+11], + xmc[13+12] ); + + fprintf(f, "#3: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[2], bc[2], Mc[2], xmaxc[2]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[26+0],xmc[26+1],xmc[26+2],xmc[26+3],xmc[26+4],xmc[26+5], + xmc[26+6], xmc[26+7],xmc[26+8],xmc[26+9],xmc[26+10],xmc[26+11], + xmc[26+12] ); + + fprintf(f, "#4: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[3], bc[3], Mc[3], xmaxc[3]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[39+0],xmc[39+1],xmc[39+2],xmc[39+3],xmc[39+4],xmc[39+5], + xmc[39+6], xmc[39+7],xmc[39+8],xmc[39+9],xmc[39+10],xmc[39+11], + xmc[39+12] ); + + return 0; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/long_term.c b/gr-gsm-fr-vocoder/src/lib/gsm/long_term.c new file mode 100644 index 00000000..fd67bda1 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/long_term.c @@ -0,0 +1,949 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* + * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION + */ + + +/* + * This module computes the LTP gain (bc) and the LTP lag (Nc) + * for the long term analysis filter. This is done by calculating a + * maximum of the cross-correlation function between the current + * sub-segment short term residual signal d[0..39] (output of + * the short term analysis filter; for simplification the index + * of this array begins at 0 and ends at 39 for each sub-segment of the + * RPE-LTP analysis) and the previous reconstructed short term + * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be + * performed to avoid overflow. + */ + + /* The next procedure exists in six versions. First two integer + * version (if USE_FLOAT_MUL is not defined); then four floating + * point versions, twice with proper scaling (USE_FLOAT_MUL defined), + * once without (USE_FLOAT_MUL and FAST defined, and fast run-time + * option used). Every pair has first a Cut version (see the -C + * option to toast or the LTP_CUT option to gsm_option()), then the + * uncut one. (For a detailed explanation of why this is altogether + * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered + * Harmful''.) + */ + +#ifndef USE_FLOAT_MUL + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), + + struct gsm_state * st, + + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_result; + longword L_max, L_power; + word R, S, dmax, scal, best_k; + word ltp_cut; + + register word temp, wt_k; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) { + dmax = temp; + best_k = k; + } + } + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + if (temp > 6) scal = 0; + else scal = 6 - temp; + assert(scal >= 0); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + wt_k = SASR(d[best_k], scal); + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = (longword)wt_k * dp[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + *Nc_out = Nc; + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k <= 39; k++) wt[k] = SASR( d[k], scal ); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + +# undef STEP +# define STEP(k) (longword)wt[k] * dp[k - lambda] + + register longword L_result; + + L_result = STEP(0) ; L_result += STEP(1) ; + L_result += STEP(2) ; L_result += STEP(3) ; + L_result += STEP(4) ; L_result += STEP(5) ; + L_result += STEP(6) ; L_result += STEP(7) ; + L_result += STEP(8) ; L_result += STEP(9) ; + L_result += STEP(10) ; L_result += STEP(11) ; + L_result += STEP(12) ; L_result += STEP(13) ; + L_result += STEP(14) ; L_result += STEP(15) ; + L_result += STEP(16) ; L_result += STEP(17) ; + L_result += STEP(18) ; L_result += STEP(19) ; + L_result += STEP(20) ; L_result += STEP(21) ; + L_result += STEP(22) ; L_result += STEP(23) ; + L_result += STEP(24) ; L_result += STEP(25) ; + L_result += STEP(26) ; L_result += STEP(27) ; + L_result += STEP(28) ; L_result += STEP(29) ; + L_result += STEP(30) ; L_result += STEP(31) ; + L_result += STEP(32) ; L_result += STEP(33) ; + L_result += STEP(34) ; L_result += STEP(35) ; + L_result += STEP(36) ; L_result += STEP(37) ; + L_result += STEP(38) ; L_result += STEP(39) ; + + if (L_result > L_max) { + + Nc = lambda; + L_max = L_result; + } + } + + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#else /* USE_FLOAT_MUL */ + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word ltp_cut; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + ltp_cut = (longword)SASR(dmax, scal) * st->ltp_cut / 100; + + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) { + register word w = SASR( d[k], scal ); + if (w < 0 ? w > -ltp_cut : w < ltp_cut) { + wt_float[k] = 0.0; + } + else { + wt_float[k] = w; + } + } + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + if ((W = wt_float[K]) != 0.0) { \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E; } else (a = lp[K]) + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) wt_float[k] = SASR( d[k], scal ); + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#ifdef FAST +#ifdef LTP_CUT + +static void Cut_Fast_Calculation_of_the_LTP_parameters P5((st, + d,dp,bc_out,Nc_out), + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + register float wt_float; + word Nc, bc; + word wt_max, best_k, ltp_cut; + + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_result, L_max, L_power; + + wt_max = 0; + + for (k = 0; k < 40; ++k) { + if ( d[k] > wt_max) wt_max = d[best_k = k]; + else if (-d[k] > wt_max) wt_max = -d[best_k = k]; + } + + assert(wt_max >= 0); + wt_float = (float)wt_max; + + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = wt_float * dp_float[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + + *Nc_out = Nc; + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Fast_Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_max, L_power; + + for (k = 0; k < 40; ++k) wt_float[k] = (float)d[k]; + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* FAST */ +#endif /* USE_FLOAT_MUL */ + + +/* 4.2.12 */ + +static void Long_term_analysis_filtering P6((bc,Nc,dp,d,dpp,e), + word bc, /* IN */ + word Nc, /* IN */ + register word * dp, /* previous d [-120..-1] IN */ + register word * d, /* d [0..39] IN */ + register word * dpp, /* estimate [0..39] OUT */ + register word * e /* long term res. signal [0..39] OUT */ +) +/* + * In this part, we have to decode the bc parameter to compute + * the samples of the estimate dpp[0..39]. The decoding of bc needs the + * use of table 4.3b. The long term residual signal e[0..39] + * is then calculated to be fed to the RPE encoding section. + */ +{ + register int k; + register longword ltmp; + +# undef STEP +# define STEP(BP) \ + for (k = 0; k <= 39; k++) { \ + dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \ + e[k] = GSM_SUB( d[k], dpp[k] ); \ + } + + switch (bc) { + case 0: STEP( 3277 ); break; + case 1: STEP( 11469 ); break; + case 2: STEP( 21299 ); break; + case 3: STEP( 32767 ); break; + } +} + +void Gsm_Long_Term_Predictor P7((S,d,dp,e,dpp,Nc,bc), /* 4x for 160 samples */ + + struct gsm_state * S, + + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + + word * e, /* [0..39] OUT */ + word * dpp, /* [0..39] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */ +) +{ + assert( d ); assert( dp ); assert( e ); + assert( dpp); assert( Nc ); assert( bc ); + +#if defined(FAST) && defined(USE_FLOAT_MUL) + if (S->fast) +#if defined (LTP_CUT) + if (S->ltp_cut) + Cut_Fast_Calculation_of_the_LTP_parameters(S, + d, dp, bc, Nc); + else +#endif /* LTP_CUT */ + Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); + else +#endif /* FAST & USE_FLOAT_MUL */ +#ifdef LTP_CUT + if (S->ltp_cut) + Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); + else +#endif + Calculation_of_the_LTP_parameters(d, dp, bc, Nc); + + Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); +} + +/* 4.3.2 */ +void Gsm_Long_Term_Synthesis_Filtering P5((S,Ncr,bcr,erp,drp), + struct gsm_state * S, + + word Ncr, + word bcr, + register word * erp, /* [0..39] IN */ + register word * drp /* [-120..-1] IN, [-120..40] OUT */ +) +/* + * This procedure uses the bcr and Ncr parameter to realize the + * long term synthesis filtering. The decoding of bcr needs + * table 4.3b. + */ +{ + register longword ltmp; /* for ADD */ + register int k; + word brp, drpp, Nr; + + /* Check the limits of Nr. + */ + Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; + S->nrp = Nr; + assert(Nr >= 40 && Nr <= 120); + + /* Decoding of the LTP gain bcr + */ + brp = gsm_QLB[ bcr ]; + + /* Computation of the reconstructed short term residual + * signal drp[0..39] + */ + assert(brp != MIN_WORD); + + for (k = 0; k <= 39; k++) { + drpp = GSM_MULT_R( brp, drp[ k - Nr ] ); + drp[k] = GSM_ADD( erp[k], drpp ); + } + + /* + * Update of the reconstructed short term residual signal + * drp[ -1..-120 ] + */ + + for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/lpc.c b/gr-gsm-fr-vocoder/src/lib/gsm/lpc.c new file mode 100644 index 00000000..ac2b8a9e --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/lpc.c @@ -0,0 +1,341 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +#undef P + +/* + * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION + */ + +/* 4.2.4 */ + + +static void Autocorrelation P2((s, L_ACF), + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +/* + * The goal is to compute the array L_ACF[k]. The signal s[i] must + * be scaled in order to avoid an overflow situation. + */ +{ + register int k, i; + + word temp, smax, scalauto; + +#ifdef USE_FLOAT_MUL + float float_s[160]; +#endif + + /* Dynamic scaling of the array s[0..159] + */ + + /* Search for the maximum. + */ + smax = 0; + for (k = 0; k <= 159; k++) { + temp = GSM_ABS( s[k] ); + if (temp > smax) smax = temp; + } + + /* Computation of the scaling factor. + */ + if (smax == 0) scalauto = 0; + else { + assert(smax > 0); + scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ + } + + /* Scaling of the array s[0...159] + */ + + if (scalauto > 0) { + +# ifdef USE_FLOAT_MUL +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + float_s[k] = (float) \ + (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ + break; +# else +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ + break; +# endif /* USE_FLOAT_MUL */ + + switch (scalauto) { + SCALE(1) + SCALE(2) + SCALE(3) + SCALE(4) + } +# undef SCALE + } +# ifdef USE_FLOAT_MUL + else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; +# endif + + /* Compute the L_ACF[..]. + */ + { +# ifdef USE_FLOAT_MUL + register float * sp = float_s; + register float sl = *sp; + +# define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); +# else + word * sp = s; + word sl = *sp; + +# define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); +# endif + +# define NEXTI sl = *++sp + + + for (k = 9; k--; L_ACF[k] = 0) ; + + STEP (0); + NEXTI; + STEP(0); STEP(1); + NEXTI; + STEP(0); STEP(1); STEP(2); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); + + for (i = 8; i <= 159; i++) { + + NEXTI; + + STEP(0); + STEP(1); STEP(2); STEP(3); STEP(4); + STEP(5); STEP(6); STEP(7); STEP(8); + } + + for (k = 9; k--; L_ACF[k] <<= 1) ; + + } + /* Rescaling of the array s[0..159] + */ + if (scalauto > 0) { + assert(scalauto <= 4); + for (k = 160; k--; *s++ <<= scalauto) ; + } +} + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Autocorrelation P2((s, L_ACF), + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +{ + register int k, i; + float f_L_ACF[9]; + float scale; + + float s_f[160]; + register float *sf = s_f; + + for (i = 0; i < 160; ++i) sf[i] = s[i]; + for (k = 0; k <= 8; k++) { + register float L_temp2 = 0; + register float *sfl = sf - k; + for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; + f_L_ACF[k] = L_temp2; + } + scale = MAX_LONGWORD / f_L_ACF[0]; + + for (k = 0; k <= 8; k++) { + L_ACF[k] = f_L_ACF[k] * scale; + } +} +#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ + +/* 4.2.5 */ + +static void Reflection_coefficients P2( (L_ACF, r), + longword * L_ACF, /* 0...8 IN */ + register word * r /* 0...7 OUT */ +) +{ + register int i, m, n; + register word temp; + register longword ltmp; + word ACF[9]; /* 0..8 */ + word P[ 9]; /* 0..8 */ + word K[ 9]; /* 2..8 */ + + /* Schur recursion with 16 bits arithmetic. + */ + + if (L_ACF[0] == 0) { + for (i = 8; i--; *r++ = 0) ; + return; + } + + assert( L_ACF[0] != 0 ); + temp = gsm_norm( L_ACF[0] ); + + assert(temp >= 0 && temp < 32); + + /* ? overflow ? */ + for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 ); + + /* Initialize array P[..] and K[..] for the recursion. + */ + + for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; + for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; + + /* Compute reflection coefficients + */ + for (n = 1; n <= 8; n++, r++) { + + temp = P[1]; + temp = GSM_ABS(temp); + if (P[0] < temp) { + for (i = n; i <= 8; i++) *r++ = 0; + return; + } + + *r = gsm_div( temp, P[0] ); + + assert(*r >= 0); + if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ + assert (*r != MIN_WORD); + if (n == 8) return; + + /* Schur recursion + */ + temp = GSM_MULT_R( P[1], *r ); + P[0] = GSM_ADD( P[0], temp ); + + for (m = 1; m <= 8 - n; m++) { + temp = GSM_MULT_R( K[ m ], *r ); + P[m] = GSM_ADD( P[ m+1 ], temp ); + + temp = GSM_MULT_R( P[ m+1 ], *r ); + K[m] = GSM_ADD( K[ m ], temp ); + } + } +} + +/* 4.2.6 */ + +static void Transformation_to_Log_Area_Ratios P1((r), + register word * r /* 0..7 IN/OUT */ +) +/* + * The following scaling for r[..] and LAR[..] has been used: + * + * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. + * LAR[..] = integer( real_LAR[..] * 16384 ); + * with -1.625 <= real_LAR <= 1.625 + */ +{ + register word temp; + register int i; + + + /* Computation of the LAR[0..7] from the r[0..7] + */ + for (i = 1; i <= 8; i++, r++) { + + temp = *r; + temp = GSM_ABS(temp); + assert(temp >= 0); + + if (temp < 22118) { + temp >>= 1; + } else if (temp < 31130) { + assert( temp >= 11059 ); + temp -= 11059; + } else { + assert( temp >= 26112 ); + temp -= 26112; + temp <<= 2; + } + + *r = *r < 0 ? -temp : temp; + assert( *r != MIN_WORD ); + } +} + +/* 4.2.7 */ + +static void Quantization_and_coding P1((LAR), + register word * LAR /* [0..7] IN/OUT */ +) +{ + register word temp; + longword ltmp; + + + /* This procedure needs four tables; the following equations + * give the optimum scaling for the constants: + * + * A[0..7] = integer( real_A[0..7] * 1024 ) + * B[0..7] = integer( real_B[0..7] * 512 ) + * MAC[0..7] = maximum of the LARc[0..7] + * MIC[0..7] = minimum of the LARc[0..7] + */ + +# undef STEP +# define STEP( A, B, MAC, MIC ) \ + temp = GSM_MULT( A, *LAR ); \ + temp = GSM_ADD( temp, B ); \ + temp = GSM_ADD( temp, 256 ); \ + temp = SASR( temp, 9 ); \ + *LAR = temp>MAC ? MAC - MIC : (tempfast) Fast_Autocorrelation (s, L_ACF ); + else +#endif + Autocorrelation (s, L_ACF ); + Reflection_coefficients (L_ACF, LARc ); + Transformation_to_Log_Area_Ratios (LARc); + Quantization_and_coding (LARc); +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/preprocess.c b/gr-gsm-fr-vocoder/src/lib/gsm/preprocess.c new file mode 100644 index 00000000..99c0709d --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/preprocess.c @@ -0,0 +1,113 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION + * + * After A-law to linear conversion (or directly from the + * Ato D converter) the following scaling is assumed for + * input to the RPE-LTP algorithm: + * + * in: 0.1.....................12 + * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* + * + * Where S is the sign bit, v a valid bit, and * a "don't care" bit. + * The original signal is called sop[..] + * + * out: 0.1................... 12 + * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 + */ + + +void Gsm_Preprocess P3((S, s, so), + struct gsm_state * S, + word * s, + word * so ) /* [0..159] IN/OUT */ +{ + + word z1 = S->z1; + longword L_z2 = S->L_z2; + word mp = S->mp; + + word s1; + longword L_s2; + + longword L_temp; + + word msp, lsp; + word SO; + + longword ltmp; /* for ADD */ + ulongword utmp; /* for L_ADD */ + + register int k = 160; + + while (k--) { + + /* 4.2.1 Downscaling of the input signal + */ + SO = SASR( *s, 3 ) << 2; + s++; + + assert (SO >= -0x4000); /* downscaled by */ + assert (SO <= 0x3FFC); /* previous routine. */ + + + /* 4.2.2 Offset compensation + * + * This part implements a high-pass filter and requires extended + * arithmetic precision for the recursive part of this filter. + * The input of this procedure is the array so[0...159] and the + * output the array sof[ 0...159 ]. + */ + /* Compute the non-recursive part + */ + + s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */ + z1 = SO; + + assert(s1 != MIN_WORD); + + /* Compute the recursive part + */ + L_s2 = s1; + L_s2 <<= 15; + + /* Execution of a 31 bv 16 bits multiplication + */ + + msp = SASR( L_z2, 15 ); + lsp = L_z2-((longword)msp<<15); /* gsm_L_sub(L_z2,(msp<<15)); */ + + L_s2 += GSM_MULT_R( lsp, 32735 ); + L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/ + L_z2 = GSM_L_ADD( L_temp, L_s2 ); + + /* Compute sof[k] with rounding + */ + L_temp = GSM_L_ADD( L_z2, 16384 ); + + /* 4.2.3 Preemphasis + */ + + msp = GSM_MULT_R( mp, -28180 ); + mp = SASR( L_temp, 15 ); + *so++ = GSM_ADD( mp, msp ); + } + + S->z1 = z1; + S->L_z2 = L_z2; + S->mp = mp; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/private.h b/gr-gsm-fr-vocoder/src/lib/gsm/private.h new file mode 100644 index 00000000..6b538cc2 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/private.h @@ -0,0 +1,268 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef PRIVATE_H +#define PRIVATE_H + +typedef short word; /* 16 bit signed int */ +typedef long longword; /* 32 bit signed int */ + +typedef unsigned short uword; /* unsigned word */ +typedef unsigned long ulongword; /* unsigned longword */ + +struct gsm_state { + + word dp0[ 280 ]; + + word z1; /* preprocessing.c, Offset_com. */ + longword L_z2; /* Offset_com. */ + int mp; /* Preemphasis */ + + word u[8]; /* short_term_aly_filter.c */ + word LARpp[2][8]; /* */ + word j; /* */ + + word ltp_cut; /* long_term.c, LTP crosscorr. */ + word nrp; /* 40 */ /* long_term.c, synthesis */ + word v[9]; /* short_term.c, synthesis */ + word msr; /* decoder.c, Postprocessing */ + + char verbose; /* only used if !NDEBUG */ + char fast; /* only used if FAST */ + + char wav_fmt; /* only used if WAV49 defined */ + unsigned char frame_index; /* odd/even chaining */ + unsigned char frame_chain; /* half-byte to carry forward */ +}; + + +#define MIN_WORD (-32767 - 1) +#define MAX_WORD 32767 + +#define MIN_LONGWORD (-2147483647 - 1) +#define MAX_LONGWORD 2147483647 + +#ifdef SASR /* flag: >> is a signed arithmetic shift right */ +#undef SASR +#define SASR(x, by) ((x) >> (by)) +#else +#define SASR(x, by) ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by)))) +#endif /* SASR */ + +#include "proto.h" + +/* + * Prototypes from add.c + */ +extern word gsm_mult P((word a, word b)); +extern longword gsm_L_mult P((word a, word b)); +extern word gsm_mult_r P((word a, word b)); + +extern word gsm_div P((word num, word denum)); + +extern word gsm_add P(( word a, word b )); +extern longword gsm_L_add P(( longword a, longword b )); + +extern word gsm_sub P((word a, word b)); +extern longword gsm_L_sub P((longword a, longword b)); + +extern word gsm_abs P((word a)); + +extern word gsm_norm P(( longword a )); + +extern longword gsm_L_asl P((longword a, int n)); +extern word gsm_asl P((word a, int n)); + +extern longword gsm_L_asr P((longword a, int n)); +extern word gsm_asr P((word a, int n)); + +/* + * Inlined functions from add.h + */ + +/* + * #define GSM_MULT_R(a, b) (* word a, word b, !(a == b == MIN_WORD) *) \ + * (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15)) + */ +#define GSM_MULT_R(a, b) /* word a, word b, !(a == b == MIN_WORD) */ \ + (SASR( ((longword)(a) * (longword)(b) + 16384), 15 )) + +# define GSM_MULT(a,b) /* word a, word b, !(a == b == MIN_WORD) */ \ + (SASR( ((longword)(a) * (longword)(b)), 15 )) + +# define GSM_L_MULT(a, b) /* word a, word b */ \ + (((longword)(a) * (longword)(b)) << 1) + +# define GSM_L_ADD(a, b) \ + ( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \ + : (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \ + >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \ + : ((b) <= 0 ? (a) + (b) \ + : (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \ + ? MAX_LONGWORD : utmp)) + +/* + * # define GSM_ADD(a, b) \ + * ((ltmp = (longword)(a) + (longword)(b)) >= MAX_WORD \ + * ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) + */ +/* Nonportable, but faster: */ + +#define GSM_ADD(a, b) \ + ((ulongword)((ltmp = (longword)(a) + (longword)(b)) - MIN_WORD) > \ + MAX_WORD - MIN_WORD ? (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp) + +# define GSM_SUB(a, b) \ + ((ltmp = (longword)(a) - (longword)(b)) >= MAX_WORD \ + ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) + +# define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a)) + +/* Use these if necessary: + +# define GSM_MULT_R(a, b) gsm_mult_r(a, b) +# define GSM_MULT(a, b) gsm_mult(a, b) +# define GSM_L_MULT(a, b) gsm_L_mult(a, b) + +# define GSM_L_ADD(a, b) gsm_L_add(a, b) +# define GSM_ADD(a, b) gsm_add(a, b) +# define GSM_SUB(a, b) gsm_sub(a, b) + +# define GSM_ABS(a) gsm_abs(a) + +*/ + +/* + * More prototypes from implementations.. + */ +extern void Gsm_Coder P(( + struct gsm_state * S, + word * s, /* [0..159] samples IN */ + word * LARc, /* [0..7] LAR coefficients OUT */ + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */)); + +extern void Gsm_Long_Term_Predictor P(( /* 4x for 160 samples */ + struct gsm_state * S, + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + word * e, /* [0..40] OUT */ + word * dpp, /* [0..40] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */)); + +extern void Gsm_LPC_Analysis P(( + struct gsm_state * S, + word * s, /* 0..159 signals IN/OUT */ + word * LARc)); /* 0..7 LARc's OUT */ + +extern void Gsm_Preprocess P(( + struct gsm_state * S, + word * s, word * so)); + +extern void Gsm_Encoding P(( + struct gsm_state * S, + word * e, + word * ep, + word * xmaxc, + word * Mc, + word * xMc)); + +extern void Gsm_Short_Term_Analysis_Filter P(( + struct gsm_state * S, + word * LARc, /* coded log area ratio [0..7] IN */ + word * d /* st res. signal [0..159] IN/OUT */)); + +extern void Gsm_Decoder P(( + struct gsm_state * S, + word * LARcr, /* [0..7] IN */ + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + word * s)); /* [0..159] OUT */ + +extern void Gsm_Decoding P(( + struct gsm_state * S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12] IN */ + word * erp)); /* [0..39] OUT */ + +extern void Gsm_Long_Term_Synthesis_Filtering P(( + struct gsm_state* S, + word Ncr, + word bcr, + word * erp, /* [0..39] IN */ + word * drp)); /* [-120..-1] IN, [0..40] OUT */ + +void Gsm_RPE_Decoding P(( + struct gsm_state *S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp)); /* [0..39] OUT */ + +void Gsm_RPE_Encoding P(( + struct gsm_state * S, + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc)); /* [0..12] OUT */ + +extern void Gsm_Short_Term_Synthesis_Filter P(( + struct gsm_state * S, + word * LARcr, /* log area ratios [0..7] IN */ + word * drp, /* received d [0...39] IN */ + word * s)); /* signal s [0..159] OUT */ + +extern void Gsm_Update_of_reconstructed_short_time_residual_signal P(( + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp)); /* [-120...-1] IN/OUT */ + +/* + * Tables from table.c + */ +#ifndef GSM_TABLE_C + +extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8]; +extern word gsm_INVA[8]; +extern word gsm_DLB[4], gsm_QLB[4]; +extern word gsm_H[11]; +extern word gsm_NRFAC[8]; +extern word gsm_FAC[8]; + +#endif /* GSM_TABLE_C */ + +/* + * Debugging + */ +#ifdef NDEBUG + +# define gsm_debug_words(a, b, c, d) /* nil */ +# define gsm_debug_longwords(a, b, c, d) /* nil */ +# define gsm_debug_word(a, b) /* nil */ +# define gsm_debug_longword(a, b) /* nil */ + +#else /* !NDEBUG => DEBUG */ + + extern void gsm_debug_words P((char * name, int, int, word *)); + extern void gsm_debug_longwords P((char * name, int, int, longword *)); + extern void gsm_debug_longword P((char * name, longword)); + extern void gsm_debug_word P((char * name, word)); + +#endif /* !NDEBUG */ + +#include "unproto.h" + +#endif /* PRIVATE_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/proto.h b/gr-gsm-fr-vocoder/src/lib/gsm/proto.h new file mode 100644 index 00000000..87cf05e8 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/proto.h @@ -0,0 +1,65 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef PROTO_H +#define PROTO_H + +#if __cplusplus +# define NeedFunctionPrototypes 1 +#endif + +#if __STDC__ +# define NeedFunctionPrototypes 1 +#endif + +#ifdef _NO_PROTO +# undef NeedFunctionPrototypes +#endif + +#undef P /* gnu stdio.h actually defines this... */ +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 + +#if NeedFunctionPrototypes + +# define P( protos ) protos + +# define P0() (void) +# define P1(x, a) (a) +# define P2(x, a, b) (a, b) +# define P3(x, a, b, c) (a, b, c) +# define P4(x, a, b, c, d) (a, b, c, d) +# define P5(x, a, b, c, d, e) (a, b, c, d, e) +# define P6(x, a, b, c, d, e, f) (a, b, c, d, e, f) +# define P7(x, a, b, c, d, e, f, g) (a, b, c, d, e, f, g) +# define P8(x, a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h) + +#else /* !NeedFunctionPrototypes */ + +# define P( protos ) ( /* protos */ ) + +# define P0() () +# define P1(x, a) x a; +# define P2(x, a, b) x a; b; +# define P3(x, a, b, c) x a; b; c; +# define P4(x, a, b, c, d) x a; b; c; d; +# define P5(x, a, b, c, d, e) x a; b; c; d; e; +# define P6(x, a, b, c, d, e, f) x a; b; c; d; e; f; +# define P7(x, a, b, c, d, e, f, g) x a; b; c; d; e; f; g; +# define P8(x, a, b, c, d, e, f, g, h) x a; b; c; d; e; f; g; h; + +#endif /* !NeedFunctionPrototypes */ + +#endif /* PROTO_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/rpe.c b/gr-gsm-fr-vocoder/src/lib/gsm/rpe.c new file mode 100644 index 00000000..8a6b81fa --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/rpe.c @@ -0,0 +1,488 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION + */ + +/* 4.2.13 */ + +static void Weighting_filter P2((e, x), + register word * e, /* signal [-5..0.39.44] IN */ + word * x /* signal [0..39] OUT */ +) +/* + * The coefficients of the weighting filter are stored in a table + * (see table 4.4). The following scaling is used: + * + * H[0..10] = integer( real_H[ 0..10] * 8192 ); + */ +{ + /* word wt[ 50 ]; */ + + register longword L_result; + register int k /* , i */ ; + + /* Initialization of a temporary working array wt[0...49] + */ + + /* for (k = 0; k <= 4; k++) wt[k] = 0; + * for (k = 5; k <= 44; k++) wt[k] = *e++; + * for (k = 45; k <= 49; k++) wt[k] = 0; + * + * (e[-5..-1] and e[40..44] are allocated by the caller, + * are initially zero and are not written anywhere.) + */ + e -= 5; + + /* Compute the signal x[0..39] + */ + for (k = 0; k <= 39; k++) { + + L_result = 8192 >> 1; + + /* for (i = 0; i <= 10; i++) { + * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] ); + * L_result = GSM_L_ADD( L_result, L_temp ); + * } + */ + +#undef STEP +#define STEP( i, H ) (e[ k + i ] * (longword)H) + + /* Every one of these multiplications is done twice -- + * but I don't see an elegant way to optimize this. + * Do you? + */ + +#ifdef STUPID_COMPILER + L_result += STEP( 0, -134 ) ; + L_result += STEP( 1, -374 ) ; + /* + STEP( 2, 0 ) */ + L_result += STEP( 3, 2054 ) ; + L_result += STEP( 4, 5741 ) ; + L_result += STEP( 5, 8192 ) ; + L_result += STEP( 6, 5741 ) ; + L_result += STEP( 7, 2054 ) ; + /* + STEP( 8, 0 ) */ + L_result += STEP( 9, -374 ) ; + L_result += STEP( 10, -134 ) ; +#else + L_result += + STEP( 0, -134 ) + + STEP( 1, -374 ) + /* + STEP( 2, 0 ) */ + + STEP( 3, 2054 ) + + STEP( 4, 5741 ) + + STEP( 5, 8192 ) + + STEP( 6, 5741 ) + + STEP( 7, 2054 ) + /* + STEP( 8, 0 ) */ + + STEP( 9, -374 ) + + STEP(10, -134 ) + ; +#endif + + /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *) + * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *) + * + * x[k] = SASR( L_result, 16 ); + */ + + /* 2 adds vs. >>16 => 14, minus one shift to compensate for + * those we lost when replacing L_MULT by '*'. + */ + + L_result = SASR( L_result, 13 ); + x[k] = ( L_result < MIN_WORD ? MIN_WORD + : (L_result > MAX_WORD ? MAX_WORD : L_result )); + } +} + +/* 4.2.14 */ + +static void RPE_grid_selection P3((x,xM,Mc_out), + word * x, /* [0..39] IN */ + word * xM, /* [0..12] OUT */ + word * Mc_out /* OUT */ +) +/* + * The signal x[0..39] is used to select the RPE grid which is + * represented by Mc. + */ +{ + /* register word temp1; */ + register int /* m, */ i; + register longword L_result, L_temp; + longword EM; /* xxx should be L_EM? */ + word Mc; + + longword L_common_0_3; + + EM = 0; + Mc = 0; + + /* for (m = 0; m <= 3; m++) { + * L_result = 0; + * + * + * for (i = 0; i <= 12; i++) { + * + * temp1 = SASR( x[m + 3*i], 2 ); + * + * assert(temp1 != MIN_WORD); + * + * L_temp = GSM_L_MULT( temp1, temp1 ); + * L_result = GSM_L_ADD( L_temp, L_result ); + * } + * + * if (L_result > EM) { + * Mc = m; + * EM = L_result; + * } + * } + */ + +#undef STEP +#define STEP( m, i ) L_temp = SASR( x[m + 3 * i], 2 ); \ + L_result += L_temp * L_temp; + + /* common part of 0 and 3 */ + + L_result = 0; + STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 ); + STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 ); + STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12); + L_common_0_3 = L_result; + + /* i = 0 */ + + STEP( 0, 0 ); + L_result <<= 1; /* implicit in L_MULT */ + EM = L_result; + + /* i = 1 */ + + L_result = 0; + STEP( 1, 0 ); + STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 ); + STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 ); + STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 1; + EM = L_result; + } + + /* i = 2 */ + + L_result = 0; + STEP( 2, 0 ); + STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 ); + STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 ); + STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 2; + EM = L_result; + } + + /* i = 3 */ + + L_result = L_common_0_3; + STEP( 3, 12 ); + L_result <<= 1; + if (L_result > EM) { + Mc = 3; + EM = L_result; + } + + /**/ + + /* Down-sampling by a factor 3 to get the selected xM[0..12] + * RPE sequence. + */ + for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; + *Mc_out = Mc; +} + +/* 4.12.15 */ + +static void APCM_quantization_xmaxc_to_exp_mant P3((xmaxc,exp_out,mant_out), + word xmaxc, /* IN */ + word * exp_out, /* OUT */ + word * mant_out ) /* OUT */ +{ + word exp, mant; + + /* Compute exponent and mantissa of the decoded version of xmaxc + */ + + exp = 0; + if (xmaxc > 15) exp = SASR(xmaxc, 3) - 1; + mant = xmaxc - (exp << 3); + + if (mant == 0) { + exp = -4; + mant = 7; + } + else { + while (mant <= 7) { + mant = mant << 1 | 1; + exp--; + } + mant -= 8; + } + + assert( exp >= -4 && exp <= 6 ); + assert( mant >= 0 && mant <= 7 ); + + *exp_out = exp; + *mant_out = mant; +} + +static void APCM_quantization P5((xM,xMc,mant_out,exp_out,xmaxc_out), + word * xM, /* [0..12] IN */ + + word * xMc, /* [0..12] OUT */ + word * mant_out, /* OUT */ + word * exp_out, /* OUT */ + word * xmaxc_out /* OUT */ +) +{ + int i, itest; + + word xmax, xmaxc, temp, temp1, temp2; + word exp, mant; + + + /* Find the maximum absolute value xmax of xM[0..12]. + */ + + xmax = 0; + for (i = 0; i <= 12; i++) { + temp = xM[i]; + temp = GSM_ABS(temp); + if (temp > xmax) xmax = temp; + } + + /* Qantizing and coding of xmax to get xmaxc. + */ + + exp = 0; + temp = SASR( xmax, 9 ); + itest = 0; + + for (i = 0; i <= 5; i++) { + + itest |= (temp <= 0); + temp = SASR( temp, 1 ); + + assert(exp <= 5); + if (itest == 0) exp++; /* exp = add (exp, 1) */ + } + + assert(exp <= 6 && exp >= 0); + temp = exp + 5; + + assert(temp <= 11 && temp >= 0); + xmaxc = gsm_add( SASR(xmax, temp), exp << 3 ); + + /* Quantizing and coding of the xM[0..12] RPE sequence + * to get the xMc[0..12] + */ + + APCM_quantization_xmaxc_to_exp_mant( xmaxc, &exp, &mant ); + + /* This computation uses the fact that the decoded version of xmaxc + * can be calculated by using the exponent and the mantissa part of + * xmaxc (logarithmic table). + * So, this method avoids any division and uses only a scaling + * of the RPE samples by a function of the exponent. A direct + * multiplication by the inverse of the mantissa (NRFAC[0..7] + * found in table 4.5) gives the 3 bit coded version xMc[0..12] + * of the RPE samples. + */ + + + /* Direct computation of xMc[0..12] using table 4.5 + */ + + assert( exp <= 4096 && exp >= -4096); + assert( mant >= 0 && mant <= 7 ); + + temp1 = 6 - exp; /* normalization by the exponent */ + temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ + + for (i = 0; i <= 12; i++) { + + assert(temp1 >= 0 && temp1 < 16); + + temp = xM[i] << temp1; + temp = GSM_MULT( temp, temp2 ); + temp = SASR(temp, 12); + xMc[i] = temp + 4; /* see note below */ + } + + /* NOTE: This equation is used to make all the xMc[i] positive. + */ + + *mant_out = mant; + *exp_out = exp; + *xmaxc_out = xmaxc; +} + +/* 4.2.16 */ + +static void APCM_inverse_quantization P4((xMc,mant,exp,xMp), + register word * xMc, /* [0..12] IN */ + word mant, + word exp, + register word * xMp) /* [0..12] OUT */ +/* + * This part is for decoding the RPE sequence of coded xMc[0..12] + * samples to obtain the xMp[0..12] array. Table 4.6 is used to get + * the mantissa of xmaxc (FAC[0..7]). + */ +{ + int i; + word temp, temp1, temp2, temp3; + longword ltmp; + + assert( mant >= 0 && mant <= 7 ); + + temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ + temp2 = gsm_sub( 6, exp ); /* see 4.2-15 for exp */ + temp3 = gsm_asl( 1, gsm_sub( temp2, 1 )); + + for (i = 13; i--;) { + + assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */ + + /* temp = gsm_sub( *xMc++ << 1, 7 ); */ + temp = (*xMc++ << 1) - 7; /* restore sign */ + assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */ + + temp <<= 12; /* 16 bit signed */ + temp = GSM_MULT_R( temp1, temp ); + temp = GSM_ADD( temp, temp3 ); + *xMp++ = gsm_asr( temp, temp2 ); + } +} + +/* 4.2.17 */ + +static void RPE_grid_positioning P3((Mc,xMp,ep), + word Mc, /* grid position IN */ + register word * xMp, /* [0..12] IN */ + register word * ep /* [0..39] OUT */ +) +/* + * This procedure computes the reconstructed long term residual signal + * ep[0..39] for the LTP analysis filter. The inputs are the Mc + * which is the grid position selection and the xMp[0..12] decoded + * RPE samples which are upsampled by a factor of 3 by inserting zero + * values. + */ +{ + int i = 13; + + assert(0 <= Mc && Mc <= 3); + + switch (Mc) { + case 3: *ep++ = 0; + case 2: do { + *ep++ = 0; + case 1: *ep++ = 0; + case 0: *ep++ = *xMp++; + } while (--i); + } + while (++Mc < 4) *ep++ = 0; + + /* + + int i, k; + for (k = 0; k <= 39; k++) ep[k] = 0; + for (i = 0; i <= 12; i++) { + ep[ Mc + (3*i) ] = xMp[i]; + } + */ +} + +/* 4.2.18 */ + +/* This procedure adds the reconstructed long term residual signal + * ep[0..39] to the estimated signal dpp[0..39] from the long term + * analysis filter to compute the reconstructed short term residual + * signal dp[-40..-1]; also the reconstructed short term residual + * array dp[-120..-41] is updated. + */ + +#if 0 /* Has been inlined in code.c */ +void Gsm_Update_of_reconstructed_short_time_residual_signal P3((dpp, ep, dp), + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp) /* [-120...-1] IN/OUT */ +{ + int k; + + for (k = 0; k <= 79; k++) + dp[ -120 + k ] = dp[ -80 + k ]; + + for (k = 0; k <= 39; k++) + dp[ -40 + k ] = gsm_add( ep[k], dpp[k] ); +} +#endif /* Has been inlined in code.c */ + +void Gsm_RPE_Encoding P5((S,e,xmaxc,Mc,xMc), + + struct gsm_state * S, + + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc) /* [0..12] OUT */ +{ + word x[40]; + word xM[13], xMp[13]; + word mant, exp; + + Weighting_filter(e, x); + RPE_grid_selection(x, xM, Mc); + + APCM_quantization( xM, xMc, &mant, &exp, xmaxc); + APCM_inverse_quantization( xMc, mant, exp, xMp); + + RPE_grid_positioning( *Mc, xMp, e ); + +} + +void Gsm_RPE_Decoding P5((S, xmaxcr, Mcr, xMcr, erp), + struct gsm_state * S, + + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp /* [0..39] OUT */ +) +{ + word exp, mant; + word xMp[ 13 ]; + + APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &exp, &mant ); + APCM_inverse_quantization( xMcr, mant, exp, xMp ); + RPE_grid_positioning( Mcr, xMp, erp ); + +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/short_term.c b/gr-gsm-fr-vocoder/src/lib/gsm/short_term.c new file mode 100644 index 00000000..4f5fd7be --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/short_term.c @@ -0,0 +1,429 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* + * SHORT TERM ANALYSIS FILTERING SECTION + */ + +/* 4.2.8 */ + +static void Decoding_of_the_coded_Log_Area_Ratios P2((LARc,LARpp), + word * LARc, /* coded log area ratio [0..7] IN */ + word * LARpp) /* out: decoded .. */ +{ + register word temp1 /* , temp2 */; + register long ltmp; /* for GSM_ADD */ + + /* This procedure requires for efficient implementation + * two tables. + * + * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) + * MIC[1..8] = minimum value of the LARc[1..8] + */ + + /* Compute the LARpp[1..8] + */ + + /* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) { + * + * temp1 = GSM_ADD( *LARc, *MIC ) << 10; + * temp2 = *B << 1; + * temp1 = GSM_SUB( temp1, temp2 ); + * + * assert(*INVA != MIN_WORD); + * + * temp1 = GSM_MULT_R( *INVA, temp1 ); + * *LARpp = GSM_ADD( temp1, temp1 ); + * } + */ + +#undef STEP +#define STEP( B, MIC, INVA ) \ + temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ + temp1 = GSM_SUB( temp1, B << 1 ); \ + temp1 = GSM_MULT_R( INVA, temp1 ); \ + *LARpp++ = GSM_ADD( temp1, temp1 ); + + STEP( 0, -32, 13107 ); + STEP( 0, -32, 13107 ); + STEP( 2048, -16, 13107 ); + STEP( -2560, -16, 13107 ); + + STEP( 94, -8, 19223 ); + STEP( -1792, -8, 17476 ); + STEP( -341, -4, 31454 ); + STEP( -1144, -4, 29708 ); + + /* NOTE: the addition of *MIC is used to restore + * the sign of *LARc. + */ +} + +/* 4.2.9 */ +/* Computation of the quantized reflection coefficients + */ + +/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] + */ + +/* + * Within each frame of 160 analyzed speech samples the short term + * analysis and synthesis filters operate with four different sets of + * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) + * and the actual set of decoded LARs (LARpp(j)) + * + * (Initial value: LARpp(j-1)[1..8] = 0.) + */ + +static void Coefficients_0_12 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + register longword ltmp; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR( *LARpp_j_1, 1)); + } +} + +static void Coefficients_13_26 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + register longword ltmp; + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 1), SASR( *LARpp_j, 1 )); + } +} + +static void Coefficients_27_39 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + register longword ltmp; + + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR( *LARpp_j, 1 )); + } +} + + +static void Coefficients_40_159 P2((LARpp_j, LARp), + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j++) + *LARp = *LARpp_j; +} + +/* 4.2.9.2 */ + +static void LARp_to_rp P1((LARp), + register word * LARp) /* [0..7] IN/OUT */ +/* + * The input of this procedure is the interpolated LARp[0..7] array. + * The reflection coefficients, rp[i], are used in the analysis + * filter and in the synthesis filter. + */ +{ + register int i; + register word temp; + register longword ltmp; + + for (i = 1; i <= 8; i++, LARp++) { + + /* temp = GSM_ABS( *LARp ); + * + * if (temp < 11059) temp <<= 1; + * else if (temp < 20070) temp += 11059; + * else temp = GSM_ADD( temp >> 2, 26112 ); + * + * *LARp = *LARp < 0 ? -temp : temp; + */ + + if (*LARp < 0) { + temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp); + *LARp = - ((temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( temp >> 2, 26112 ))); + } else { + temp = *LARp; + *LARp = (temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( temp >> 2, 26112 )); + } + } +} + + +/* 4.2.10 */ +static void Short_term_analysis_filtering P4((S,rp,k_n,s), + struct gsm_state * S, + register word * rp, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +/* + * This procedure computes the short term residual signal d[..] to be fed + * to the RPE-LTP loop from the s[..] signal and from the local rp[..] + * array (quantized reflection coefficients). As the call of this + * procedure can be done in many ways (see the interpolation of the LAR + * coefficient), it is assumed that the computation begins with index + * k_start (for arrays d[..] and s[..]) and stops with index k_end + * (k_start and k_end are defined in 4.2.9.1). This procedure also + * needs to keep the array u[0..7] in memory for each call. + */ +{ + register word * u = S->u; + register int i; + register word di, zzz, ui, sav, rpi; + register longword ltmp; + + for (; k_n--; s++) { + + di = sav = *s; + + for (i = 0; i < 8; i++) { /* YYY */ + + ui = u[i]; + rpi = rp[i]; + u[i] = sav; + + zzz = GSM_MULT_R(rpi, di); + sav = GSM_ADD( ui, zzz); + + zzz = GSM_MULT_R(rpi, ui); + di = GSM_ADD( di, zzz ); + } + + *s = di; + } +} + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Short_term_analysis_filtering P4((S,rp,k_n,s), + struct gsm_state * S, + register word * rp, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +{ + register word * u = S->u; + register int i; + + float uf[8], + rpf[8]; + + register float scalef = 3.0517578125e-5; + register float sav, di, temp; + + for (i = 0; i < 8; ++i) { + uf[i] = u[i]; + rpf[i] = rp[i] * scalef; + } + for (; k_n--; s++) { + sav = di = *s; + for (i = 0; i < 8; ++i) { + register float rpfi = rpf[i]; + register float ufi = uf[i]; + + uf[i] = sav; + temp = rpfi * di + ufi; + di += rpfi * ufi; + sav = temp; + } + *s = di; + } + for (i = 0; i < 8; ++i) u[i] = uf[i]; +} +#endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */ + +static void Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + register word sri, tmp1, tmp2; + register longword ltmp; /* for GSM_ADD & GSM_SUB */ + + while (k--) { + sri = *wt++; + for (i = 8; i--;) { + + /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) ); + */ + tmp1 = rrp[i]; + tmp2 = v[i]; + tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD + ? MAX_WORD + : 0x0FFFF & (( (longword)tmp1 * (longword)tmp2 + + 16384) >> 15)) ; + + sri = GSM_SUB( sri, tmp2 ); + + /* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) ); + */ + tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD + ? MAX_WORD + : 0x0FFFF & (( (longword)tmp1 * (longword)sri + + 16384) >> 15)) ; + + v[i+1] = GSM_ADD( v[i], tmp1); + } + *sr++ = v[0] = sri; + } +} + + +#if defined(FAST) && defined(USE_FLOAT_MUL) + +static void Fast_Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + + float va[9], rrpa[8]; + register float scalef = 3.0517578125e-5, temp; + + for (i = 0; i < 8; ++i) { + va[i] = v[i]; + rrpa[i] = (float)rrp[i] * scalef; + } + while (k--) { + register float sri = *wt++; + for (i = 8; i--;) { + sri -= rrpa[i] * va[i]; + if (sri < -32768.) sri = -32768.; + else if (sri > 32767.) sri = 32767.; + + temp = va[i] + rrpa[i] * sri; + if (temp < -32768.) temp = -32768.; + else if (temp > 32767.) temp = 32767.; + va[i+1] = temp; + } + *sr++ = va[0] = sri; + } + for (i = 0; i < 9; ++i) v[i] = va[i]; +} + +#endif /* defined(FAST) && defined(USE_FLOAT_MUL) */ + +void Gsm_Short_Term_Analysis_Filter P3((S,LARc,s), + + struct gsm_state * S, + + word * LARc, /* coded log area ratio [0..7] IN */ + word * s /* signal [0..159] IN/OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) +# define FILTER (* (S->fast \ + ? Fast_Short_term_analysis_filtering \ + : Short_term_analysis_filtering )) + +#else +# define FILTER Short_term_analysis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, s); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 14, s + 13); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, s + 27); + + Coefficients_40_159( LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 120, s + 40); +} + +void Gsm_Short_Term_Synthesis_Filter P4((S, LARcr, wt, s), + struct gsm_state * S, + + word * LARcr, /* received log area ratios [0..7] IN */ + word * wt, /* received d [0..159] IN */ + + word * s /* signal s [0..159] OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^=1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) + +# define FILTER (* (S->fast \ + ? Fast_Short_term_synthesis_filtering \ + : Short_term_synthesis_filtering )) +#else +# define FILTER Short_term_synthesis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt, s ); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 14, wt + 13, s + 13 ); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt + 27, s + 27 ); + + Coefficients_40_159( LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER(S, LARp, 120, wt + 40, s + 40); +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/table.c b/gr-gsm-fr-vocoder/src/lib/gsm/table.c new file mode 100644 index 00000000..16a04118 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/table.c @@ -0,0 +1,63 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +/* Most of these tables are inlined at their point of use. + */ + +/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP + * CODER AND DECODER + * + * (Most of them inlined, so watch out.) + */ + +#define GSM_TABLE_C +#include "private.h" +#include "gsm.h" + +/* Table 4.1 Quantization of the Log.-Area Ratios + */ +/* i 1 2 3 4 5 6 7 8 */ +word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036}; +word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144}; +word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 }; +word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 }; + + +/* Table 4.2 Tabulation of 1/A[1..8] + */ +word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 }; + + +/* Table 4.3a Decision level of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_DLB[4] = { 6554, 16384, 26214, 32767 }; + + +/* Table 4.3b Quantization levels of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_QLB[4] = { 3277, 11469, 21299, 32767 }; + + +/* Table 4.4 Coefficients of the weighting filter + */ +/* i 0 1 2 3 4 5 6 7 8 9 10 */ +word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; + + +/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; + + +/* Table 4.6 Normalized direct mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; diff --git a/gr-gsm-fr-vocoder/src/lib/gsm/unproto.h b/gr-gsm-fr-vocoder/src/lib/gsm/unproto.h new file mode 100644 index 00000000..ccd56510 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm/unproto.h @@ -0,0 +1,23 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifdef PROTO_H /* sic */ +#undef PROTO_H + +#undef P +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 + +#endif /* PROTO_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.cc b/gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.cc new file mode 100644 index 00000000..59dcd3d8 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gsm_fr_decode_ps.h" +extern "C"{ +#include "gsm/gsm.h" +} +#include +#include +#include + +gsm_fr_decode_ps_sptr +gsm_fr_make_decode_ps () +{ + return gsm_fr_decode_ps_sptr (new gsm_fr_decode_ps ()); +} + +gsm_fr_decode_ps::gsm_fr_decode_ps () + : gr_sync_interpolator ("gsm_fr_decode_ps", + gr_make_io_signature (1, 1, sizeof (gsm_frame)), + gr_make_io_signature (1, 1, sizeof (short)), + GSM_SAMPLES_PER_FRAME) +{ + if ((d_gsm = gsm_create ()) == 0) + throw std::runtime_error ("gsm_fr_decode_ps: gsm_create failed"); +} + +gsm_fr_decode_ps::~gsm_fr_decode_ps () +{ + gsm_destroy (d_gsm); +} + +int +gsm_fr_decode_ps::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]; + short *out = (short *) output_items[0]; + + assert ((noutput_items % GSM_SAMPLES_PER_FRAME) == 0); + + for (int i = 0; i < noutput_items; i += GSM_SAMPLES_PER_FRAME){ + gsm_decode (d_gsm, const_cast(in), out); + in += sizeof (gsm_frame); + out += GSM_SAMPLES_PER_FRAME; + } + + return noutput_items; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.h b/gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.h new file mode 100644 index 00000000..4e1b2120 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GSM_FR_DECODE_PS_H +#define INCLUDED_GSM_FR_DECODE_PS_H + +#include + +class gsm_fr_decode_ps; +typedef boost::shared_ptr gsm_fr_decode_ps_sptr; + +gsm_fr_decode_ps_sptr gsm_fr_make_decode_ps (); + +/*! + * \brief GSM 06.10 Full Rate Vocoder Decoder + */ +class gsm_fr_decode_ps : public gr_sync_interpolator { + struct gsm_state *d_gsm; + + friend gsm_fr_decode_ps_sptr gsm_fr_make_decode_ps (); + gsm_fr_decode_ps (); + +public: + ~gsm_fr_decode_ps (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GSM_FR_DECODE_PS_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.cc b/gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.cc new file mode 100644 index 00000000..8f492809 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gsm_fr_encode_sp.h" +extern "C"{ +#include "gsm/gsm.h" +} +#include +#include + +gsm_fr_encode_sp_sptr +gsm_fr_make_encode_sp () +{ + return gsm_fr_encode_sp_sptr (new gsm_fr_encode_sp ()); +} + +gsm_fr_encode_sp::gsm_fr_encode_sp () + : gr_sync_decimator ("gsm_fr_encode_sp", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (1, 1, sizeof (gsm_frame)), + GSM_SAMPLES_PER_FRAME) +{ + if ((d_gsm = gsm_create ()) == 0) + throw std::runtime_error ("gsm_fr_encode_sp: gsm_create failed"); +} + +gsm_fr_encode_sp::~gsm_fr_encode_sp () +{ + gsm_destroy (d_gsm); +} + +int +gsm_fr_encode_sp::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const short *in = (const short *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + gsm_encode (d_gsm, const_cast(in), out); + in += GSM_SAMPLES_PER_FRAME; + out += sizeof (gsm_frame); + } + + return noutput_items; +} diff --git a/gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.h b/gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.h new file mode 100644 index 00000000..5cbc3ae5 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GSM_FR_ENCODE_SP_H +#define INCLUDED_GSM_FR_ENCODE_SP_H + +#include + +class gsm_fr_encode_sp; +typedef boost::shared_ptr gsm_fr_encode_sp_sptr; + +gsm_fr_encode_sp_sptr gsm_fr_make_encode_sp (); + +/*! + * \brief GSM 06.10 Full Rate Vocoder Encoder + * \ingroup block + * + * shorts in; 33 byte packets out + */ +class gsm_fr_encode_sp : public gr_sync_decimator { + struct gsm_state *d_gsm; + + friend gsm_fr_encode_sp_sptr gsm_fr_make_encode_sp (); + gsm_fr_encode_sp (); + +public: + ~gsm_fr_encode_sp (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GSM_FR_ENCODE_SP_H */ diff --git a/gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i b/gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i new file mode 100644 index 00000000..80c55575 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); +%include "exception.i" +%import "gnuradio.i" + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "gsm_fr_encode_sp.h" +#include "gsm_fr_decode_ps.h" +#include +%} + +GR_SWIG_BLOCK_MAGIC(gsm_fr,encode_sp); + +gsm_fr_encode_sp_sptr gsm_fr_make_encode_sp (); + +class gsm_fr_encode_sp : public gr_sync_decimator { +public: + ~gsm_fr_encode_sp (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(gsm_fr,decode_ps); + +gsm_fr_decode_ps_sptr gsm_fr_make_decode_ps (); + +class gsm_fr_decode_ps : public gr_sync_interpolator { +public: + ~gsm_fr_decode_ps (); +}; diff --git a/gr-gsm-fr-vocoder/src/python/Makefile.am b/gr-gsm-fr-vocoder/src/python/Makefile.am new file mode 100644 index 00000000..4df9ca37 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/python/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +noinst_PYTHON = \ + encdec.py \ + qa_gsm_full_rate.py diff --git a/gr-gsm-fr-vocoder/src/python/encdec.py b/gr-gsm-fr-vocoder/src/python/encdec.py new file mode 100755 index 00000000..c8a46227 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/python/encdec.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.vocoder import gsm_full_rate + +def build_graph(): + fg = gr.flow_graph() + src = audio.source(8000) + src_scale = gr.multiply_const_ff(32767) + f2s = gr.float_to_short () + enc = gsm_full_rate.encode_sp() + dec = gsm_full_rate.decode_ps() + s2f = gr.short_to_float () + sink_scale = gr.multiply_const_ff(1.0/32767.) + sink = audio.sink(8000) + fg.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) + return fg + +if __name__ == '__main__': + fg = build_graph() + fg.start() + raw_input ('Press Enter to exit: ') + fg.stop() diff --git a/gr-gsm-fr-vocoder/src/python/qa_gsm_full_rate.py b/gr-gsm-fr-vocoder/src/python/qa_gsm_full_rate.py new file mode 100755 index 00000000..6b318d20 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/python/qa_gsm_full_rate.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import gsm_full_rate + +class qa_howto (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-gsm-fr-vocoder/src/python/run_tests.in b/gr-gsm-fr-vocoder/src/python/run_tests.in new file mode 100644 index 00000000..2c3be907 --- /dev/null +++ b/gr-gsm-fr-vocoder/src/python/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-gsm-fr-vocoder/src/lib +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-gsm-fr-vocoder/src/lib +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-gsm-fr-vocoder/src/python + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-howto-write-a-block/.buildpri b/gr-howto-write-a-block/.buildpri new file mode 100644 index 00000000..29ba0dff --- /dev/null +++ b/gr-howto-write-a-block/.buildpri @@ -0,0 +1 @@ +450 diff --git a/gr-howto-write-a-block/AUTHORS b/gr-howto-write-a-block/AUTHORS new file mode 100644 index 00000000..ee4560a5 --- /dev/null +++ b/gr-howto-write-a-block/AUTHORS @@ -0,0 +1 @@ +Eric Blossom diff --git a/gr-howto-write-a-block/COPYING b/gr-howto-write-a-block/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/gr-howto-write-a-block/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gr-howto-write-a-block/ChangeLog b/gr-howto-write-a-block/ChangeLog new file mode 100644 index 00000000..fcb7af60 --- /dev/null +++ b/gr-howto-write-a-block/ChangeLog @@ -0,0 +1,46 @@ +2006-07-21 Eric Blossom + + * doc/howto-write-a-block.xml: clarified 1:1 i/o relationship + versus size of input and output items. Thanks Jens! + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/lib/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-01-29 Eric Blossom + + * src/lib/Makefile.am: mods for SWIG 1.3.24 + +2005-01-20 Eric Blossom + + * doc/howto-write-a-block.xml: made release 0.1 + +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-howto-write-a-block/INSTALL b/gr-howto-write-a-block/INSTALL new file mode 100644 index 00000000..54caf7c1 --- /dev/null +++ b/gr-howto-write-a-block/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/gr-howto-write-a-block/Makefile.am b/gr-howto-write-a-block/Makefile.am new file mode 100644 index 00000000..dcab9124 --- /dev/null +++ b/gr-howto-write-a-block/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = bootstrap configure config.h.in .buildpri +SUBDIRS = config src +DIST_SUBDIRS = config src doc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = diff --git a/gr-howto-write-a-block/Makefile.common b/gr-howto-write-a-block/Makefile.common new file mode 100644 index 00000000..261de509 --- /dev/null +++ b/gr-howto-write-a-block/Makefile.common @@ -0,0 +1,38 @@ +# -*- Makefile -*- +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# includes +grincludedir = $(includedir)/gnuradio + +# swig includes +swigincludedir = $(grincludedir)/swig + +# Install this stuff in the appropriate subdirectory +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +grpythondir = $(pythondir)/gnuradio +grpyexecdir = $(pyexecdir)/gnuradio + +# swig flags +SWIGPYTHONFLAGS = -fvirtual -python -modern +SWIGGRFLAGS = -I$(GNURADIO_CORE_INCLUDEDIR)/swig -I$(GNURADIO_CORE_INCLUDEDIR) diff --git a/gr-howto-write-a-block/NEWS b/gr-howto-write-a-block/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/gr-howto-write-a-block/README b/gr-howto-write-a-block/README new file mode 100644 index 00000000..2b5e9a50 --- /dev/null +++ b/gr-howto-write-a-block/README @@ -0,0 +1,44 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This tarball contains a build tree with examples, Makefiles, etc that +demonstrate how to write signal processing blocks for the GNU Radio +system. + +To build the examples from the tarball use the normal recipe: + + $ ./configure + $ make + $ make check + +If you're building from CVS, you'll need to use this sequence, since +CVS doesn't contain configure or the generated Makefiles. + + $ ./bootstrap + $ ./configure + $ make + $ make check + + +The doc directory is not built by default. This is to avoid spurious +build problems on systems that don't have xmlto installed. If you +have xmlto and its dependencies installed, you can build the html +version of the howto article by cd'ing to doc and invoking make. diff --git a/gr-howto-write-a-block/bootstrap b/gr-howto-write-a-block/bootstrap new file mode 100755 index 00000000..7df375ee --- /dev/null +++ b/gr-howto-write-a-block/bootstrap @@ -0,0 +1,29 @@ +#!/bin/sh + +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + + +rm -fr config.cache autom4te*.cache + +aclocal -I config +autoconf +autoheader +libtoolize --automake +automake --add-missing diff --git a/gr-howto-write-a-block/config.guess b/gr-howto-write-a-block/config.guess new file mode 100644 index 00000000..52c01be4 --- /dev/null +++ b/gr-howto-write-a-block/config.guess @@ -0,0 +1,1465 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-11-11' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[345]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/gr-howto-write-a-block/config.sub b/gr-howto-write-a-block/config.sub new file mode 100644 index 00000000..a4aba165 --- /dev/null +++ b/gr-howto-write-a-block/config.sub @@ -0,0 +1,1587 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-11-13' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ms1 \ + | msp430 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m32c) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | ms1-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + m32c-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/gr-howto-write-a-block/config/Makefile.am b/gr-howto-write-a-block/config/Makefile.am new file mode 100644 index 00000000..2154a227 --- /dev/null +++ b/gr-howto-write-a-block/config/Makefile.am @@ -0,0 +1,66 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install m4 macros in this directory +m4datadir = $(datadir)/aclocal + +# List your m4 macros here +m4macros = \ + acx_pthread.m4 \ + bnv_have_qt.m4 \ + cppunit.m4 \ + gr_as.m4 \ + gr_boost.m4 \ + gr_check_createfilemapping.m4 \ + gr_check_usrp.m4 \ + gr_check_mc4020.m4 \ + gr_check_shm_open.m4 \ + gr_doxygen.m4 \ + gr_gprof.m4 \ + gr_libgnuradio_core_extra_ldflags.m4 \ + gr_no_undefined.m4 \ + gr_omnithread.m4 \ + gr_pwin32.m4 \ + gr_python.m4 \ + gr_require_mc4020.m4 \ + gr_scripting.m4 \ + gr_set_md_cpu.m4 \ + gr_swig.m4 \ + gr_sysv_shm.m4 \ + gr_x86_64.m4 \ + lf_cc.m4 \ + lf_cxx.m4 \ + lf_warnings.m4 \ + lf_x11.m4 \ + mkstemp.m4 \ + onceonly.m4 \ + pkg.m4 \ + usrp_fusb_tech.m4 \ + usrp_libusb.m4 \ + usrp_sdcc.m4 + + +# Don't install m4 macros anymore +# m4data_DATA = $(m4macros) + +EXTRA_DIST = $(m4macros) diff --git a/gr-howto-write-a-block/config/acx_pthread.m4 b/gr-howto-write-a-block/config/acx_pthread.m4 new file mode 100644 index 00000000..d318ab01 --- /dev/null +++ b/gr-howto-write-a-block/config/acx_pthread.m4 @@ -0,0 +1,190 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# pthread: Linux, etcetera +# --thread-safe: KAI C++ + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthread or + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: threads are created detached by default + # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + AC_MSG_CHECKING([for joinable pthread attribute]) + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_UNDETACHED;], + ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) + fi + if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then + AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, + [Define to the necessary symbol if this constant + uses a non-standard name on your system.]) + fi + AC_MSG_RESULT(${ok}) + if test x"$ok" = xunknown; then + AC_MSG_WARN([we do not know how to create joinable pthreads]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/gr-howto-write-a-block/config/bnv_have_qt.m4 b/gr-howto-write-a-block/config/bnv_have_qt.m4 new file mode 100644 index 00000000..1469bfbf --- /dev/null +++ b/gr-howto-write-a-block/config/bnv_have_qt.m4 @@ -0,0 +1,404 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/bnv_have_qt.html +dnl +AC_DEFUN([BNV_HAVE_QT], +[ + dnl THANKS! This code includes bug fixes by: + dnl Tim McClarren. + + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PATH_X]) + AC_REQUIRE([AC_PATH_XTRA]) + + AC_MSG_CHECKING(for Qt) + + AC_ARG_WITH([Qt-dir], + [ --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the + installation instructions of Trolltech. Header + files are in DIR/include, binary utilities are + in DIR/bin and the library is in DIR/lib]) + AC_ARG_WITH([Qt-include-dir], + [ --with-Qt-include-dir=DIR + Qt header files are in DIR]) + AC_ARG_WITH([Qt-bin-dir], + [ --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR]) + AC_ARG_WITH([Qt-lib-dir], + [ --with-Qt-lib-dir=DIR The Qt library is in DIR]) + AC_ARG_WITH([Qt-lib], + [ --with-Qt-lib=LIB Use -lLIB to link with the Qt library]) + if test x"$with_Qt_dir" = x"no" || + test x"$with_Qt_include-dir" = x"no" || + test x"$with_Qt_bin_dir" = x"no" || + test x"$with_Qt_lib_dir" = x"no" || + test x"$with_Qt_lib" = x"no"; then + # user disabled Qt. Leave cache alone. + have_qt="User disabled Qt." + else + # "yes" is a bogus option + if test x"$with_Qt_dir" = xyes; then + with_Qt_dir= + fi + if test x"$with_Qt_include_dir" = xyes; then + with_Qt_include_dir= + fi + if test x"$with_Qt_bin_dir" = xyes; then + with_Qt_bin_dir= + fi + if test x"$with_Qt_lib_dir" = xyes; then + with_Qt_lib_dir= + fi + if test x"$with_Qt_lib" = xyes; then + with_Qt_lib= + fi + # No Qt unless we discover otherwise + have_qt=no + # Check whether we are requested to link with a specific version + if test x"$with_Qt_lib" != x; then + bnv_qt_lib="$with_Qt_lib" + fi + # Check whether we were supplied with an answer already + if test x"$with_Qt_dir" != x; then + have_qt=yes + bnv_qt_dir="$with_Qt_dir" + bnv_qt_include_dir="$with_Qt_dir/include" + bnv_qt_bin_dir="$with_Qt_dir/bin" + bnv_qt_lib_dir="$with_Qt_dir/lib" + # Only search for the lib if the user did not define one already + if test x"$bnv_qt_lib" = x; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # Use cached value or do search, starting with suggestions from + # the command line + AC_CACHE_VAL(bnv_cv_have_qt, + [ + # We are not given a solution and there is no cached value. + bnv_qt_dir=NO + bnv_qt_include_dir=NO + bnv_qt_lib_dir=NO + if test x"$bnv_qt_lib" = x; then + bnv_qt_lib=NO + fi + BNV_PATH_QT_DIRECT + if test "$bnv_qt_dir" = NO || + test "$bnv_qt_include_dir" = NO || + test "$bnv_qt_lib_dir" = NO || + test "$bnv_qt_lib" = NO; then + # Problem with finding complete Qt. Cache the known absence of Qt. + bnv_cv_have_qt="have_qt=no" + else + # Record where we found Qt for the cache. + bnv_cv_have_qt="have_qt=yes \ + bnv_qt_dir=$bnv_qt_dir \ + bnv_qt_include_dir=$bnv_qt_include_dir \ + bnv_qt_bin_dir=$bnv_qt_bin_dir \ + bnv_qt_LIBS=\"$bnv_qt_LIBS\"" + fi + ])dnl + eval "$bnv_cv_have_qt" + fi # all $bnv_qt_* are set + fi # $have_qt reflects the system status + if test x"$have_qt" = xyes; then + QT_CXXFLAGS="-I$bnv_qt_include_dir" + QT_DIR="$bnv_qt_dir" + QT_LIBS="$bnv_qt_LIBS" + # If bnv_qt_dir is defined, utilities are expected to be in the + # bin subdirectory + if test x"$bnv_qt_dir" != x; then + if test -x "$bnv_qt_dir/bin/uic"; then + QT_UIC="$bnv_qt_dir/bin/uic" + else + # Old versions of Qt don't have uic + QT_UIC= + fi + QT_MOC="$bnv_qt_dir/bin/moc" + else + # Or maybe we are told where to look for the utilities + if test x"$bnv_qt_bin_dir" != x; then + if test -x "$bnv_qt_bin_dir/uic"; then + QT_UIC="$bnv_qt_bin_dir/uic" + else + # Old versions of Qt don't have uic + QT_UIC= + fi + QT_MOC="$bnv_qt_bin_dir/moc" + else + # Last possibility is that they are in $PATH + QT_UIC="`which uic`" + QT_MOC="`which moc`" + fi + fi + # All variables are defined, report the result + AC_MSG_RESULT([$have_qt: + QT_CXXFLAGS=$QT_CXXFLAGS + QT_DIR=$QT_DIR + QT_LIBS=$QT_LIBS + QT_UIC=$QT_UIC + QT_MOC=$QT_MOC]) + else + # Qt was not found + QT_CXXFLAGS= + QT_DIR= + QT_LIBS= + QT_UIC= + QT_MOC= + AC_MSG_RESULT($have_qt) + fi + AC_SUBST(QT_CXXFLAGS) + AC_SUBST(QT_DIR) + AC_SUBST(QT_LIBS) + AC_SUBST(QT_UIC) + AC_SUBST(QT_MOC) + + #### Being paranoid: + if test x"$have_qt" = xyes; then + AC_MSG_CHECKING(correct functioning of Qt installation) + AC_CACHE_VAL(bnv_cv_qt_test_result, + [ + cat > bnv_qt_test.h << EOF +#include +class Test : public QObject +{ +Q_OBJECT +public: + Test() {} + ~Test() {} +public slots: + void receive() {} +signals: + void send(); +}; +EOF + + cat > bnv_qt_main.$ac_ext << EOF +#include "bnv_qt_test.h" +#include +int main( int argc, char **argv ) +{ + QApplication app( argc, argv ); + Test t; + QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) ); +} +EOF + + bnv_cv_qt_test_result="failure" + bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out" + AC_TRY_EVAL(bnv_try_1) + bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"` + if test x"$bnv_err_1" != x; then + echo "$bnv_err_1" >&AC_FD_CC + echo "configure: could not run $QT_MOC on:" >&AC_FD_CC + cat bnv_qt_test.h >&AC_FD_CC + else + bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out" + AC_TRY_EVAL(bnv_try_2) + bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"` + if test x"$bnv_err_2" != x; then + echo "$bnv_err_2" >&AC_FD_CC + echo "configure: could not compile:" >&AC_FD_CC + cat bnv_qt_test.$ac_ext >&AC_FD_CC + else + bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out" + AC_TRY_EVAL(bnv_try_3) + bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"` + if test x"$bnv_err_3" != x; then + echo "$bnv_err_3" >&AC_FD_CC + echo "configure: could not compile:" >&AC_FD_CC + cat bnv_qt_main.$ac_ext >&AC_FD_CC + else + bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out" + AC_TRY_EVAL(bnv_try_4) + bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out` + if test x"$bnv_err_4" != x; then + echo "$bnv_err_4" >&AC_FD_CC + else + bnv_cv_qt_test_result="success" + fi + fi + fi + fi + ])dnl AC_CACHE_VAL bnv_cv_qt_test_result + AC_MSG_RESULT([$bnv_cv_qt_test_result]); + if test x"$bnv_cv_qt_test_result" = "xfailure"; then + # working Qt was not found + QT_CXXFLAGS= + QT_DIR= + QT_LIBS= + QT_UIC= + QT_MOC= + have_qt=no + AC_MSG_WARN([Failed to find matching components of a complete + Qt installation. Try using more options, + see ./configure --help.]) + fi + + rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \ + bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \ + bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out + fi +]) + +dnl Internal subroutine of BNV_HAVE_QT +dnl Set bnv_qt_dir bnv_qt_include_dir bnv_qt_bin_dir bnv_qt_lib_dir bnv_qt_lib +dnl Copyright 2001 Bastiaan N. Veelo +AC_DEFUN([BNV_PATH_QT_DIRECT], +[ + ## Binary utilities ## + if test x"$with_Qt_bin_dir" != x; then + bnv_qt_bin_dir=$with_Qt_bin_dir + fi + ## Look for header files ## + if test x"$with_Qt_include_dir" != x; then + bnv_qt_include_dir="$with_Qt_include_dir" + else + # The following header file is expected to define QT_VERSION. + qt_direct_test_header=qglobal.h + # Look for the header file in a standard set of common directories. + bnv_include_path_list=" + /usr/include + `ls -dr /usr/include/qt* 2>/dev/null` + `ls -dr /usr/lib/qt*/include 2>/dev/null` + `ls -dr /usr/local/qt*/include 2>/dev/null` + `ls -dr /opt/qt*/include 2>/dev/null` + " + for bnv_dir in $bnv_include_path_list; do + if test -r "$bnv_dir/$qt_direct_test_header"; then + bnv_dirs="$bnv_dirs $bnv_dir" + fi + done + # Now look for the newest in this list + bnv_prev_ver=0 + for bnv_dir in $bnv_dirs; do + bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/$qt_direct_test_header | sed s/'#define QT_VERSION'//` + if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then + bnv_qt_include_dir=$bnv_dir + bnv_prev_ver=$bnv_this_ver + fi + done + fi dnl Found header files. + + # Are these headers located in a traditional Trolltech installation? + # That would be $bnv_qt_include_dir stripped from its last element: + bnv_possible_qt_dir=`dirname $bnv_qt_include_dir` + if test -x $bnv_possible_qt_dir/bin/moc && + ls $bnv_possible_qt_dir/lib/libqt* > /dev/null; then + # Then the rest is a piece of cake + bnv_qt_dir=$bnv_possible_qt_dir + bnv_qt_bin_dir="$bnv_qt_dir/bin" + bnv_qt_lib_dir="$bnv_qt_dir/lib" + # Only look for lib if the user did not supply it already + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # There is no valid definition for $QTDIR as Trolltech likes to see it + bnv_qt_dir= + ## Look for Qt library ## + if test x"$with_Qt_lib_dir" != x; then + bnv_qt_lib_dir="$with_Qt_lib_dir" + # Only look for lib if the user did not supply it already + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # Normally, when there is no traditional Trolltech installation, + # the library is installed in a place where the linker finds it + # automatically. + # If the user did not define the library name, try with qt + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib=qt + fi + qt_direct_test_header=qapplication.h + qt_direct_test_main=" + int argc; + char ** argv; + QApplication app(argc,argv); + " + # See if we find the library without any special options. + # Don't add top $LIBS permanently yet + bnv_save_LIBS="$LIBS" + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + bnv_qt_LIBS="$LIBS" + bnv_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="-I$bnv_qt_include_dir" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Success. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Try the multi-threaded version + echo "Non-critical error, please neglect the above." >&AC_FD_CC + bnv_qt_lib=qt-mt + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Success. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Try the OpenGL version + echo "Non-critical error, please neglect the above." >&AC_FD_CC + bnv_qt_lib=qt-gl + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Succes. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Maybe a library version I don't know about? + echo "Non-critical error, please neglect the above." >&AC_FD_CC + # Look for some Qt lib in a standard set of common directories. + bnv_dir_list=" + `echo $bnv_qt_includes | sed ss/includess` + /lib + /usr/lib + /usr/local/lib + /opt/lib + `ls -dr /usr/lib/qt* 2>/dev/null` + `ls -dr /usr/local/qt* 2>/dev/null` + `ls -dr /opt/qt* 2>/dev/null` + " + for bnv_dir in $bnv_dir_list; do + if ls $bnv_dir/libqt*; then + # Gamble that it's the first one... + bnv_qt_lib="`ls $bnv_dir/libqt* | sed -n 1p | + sed s@$bnv_dir/lib@@ | sed s/[.].*//`" + bnv_qt_lib_dir="$bnv_dir" + break + fi + done + # Try with that one + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Succes. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # Leave bnv_qt_lib_dir defined + ]) + ]) + ]) + ]) + if test x"$bnv_qt_lib_dir" != x; then + bnv_qt_LIBS="-l$bnv_qt_lib_dir $LIBS" + else + bnv_qt_LIBS="$LIBS" + fi + LIBS="$bnv_save_LIBS" + CXXFLAGS="$bnv_save_CXXFLAGS" + fi dnl $with_Qt_lib_dir was not given + fi dnl Done setting up for non-traditional Trolltech installation +]) diff --git a/gr-howto-write-a-block/config/cppunit.m4 b/gr-howto-write-a-block/config/cppunit.m4 new file mode 100644 index 00000000..0991d51e --- /dev/null +++ b/gr-howto-write-a-block/config/cppunit.m4 @@ -0,0 +1,80 @@ +dnl +dnl AM_PATH_CPPUNIT(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([AM_PATH_CPPUNIT], +[ + +AC_ARG_WITH(cppunit-prefix,[ --with-cppunit-prefix=PFX Prefix where CppUnit is installed (optional)], + cppunit_config_prefix="$withval", cppunit_config_prefix="") +AC_ARG_WITH(cppunit-exec-prefix,[ --with-cppunit-exec-prefix=PFX Exec prefix where CppUnit is installed (optional)], + cppunit_config_exec_prefix="$withval", cppunit_config_exec_prefix="") + + if test x$cppunit_config_exec_prefix != x ; then + cppunit_config_args="$cppunit_config_args --exec-prefix=$cppunit_config_exec_prefix" + if test x${CPPUNIT_CONFIG+set} != xset ; then + CPPUNIT_CONFIG=$cppunit_config_exec_prefix/bin/cppunit-config + fi + fi + if test x$cppunit_config_prefix != x ; then + cppunit_config_args="$cppunit_config_args --prefix=$cppunit_config_prefix" + if test x${CPPUNIT_CONFIG+set} != xset ; then + CPPUNIT_CONFIG=$cppunit_config_prefix/bin/cppunit-config + fi + fi + + AC_PATH_PROG(CPPUNIT_CONFIG, cppunit-config, no) + cppunit_version_min=$1 + + AC_MSG_CHECKING(for Cppunit - version >= $cppunit_version_min) + no_cppunit="" + if test "$CPPUNIT_CONFIG" = "no" ; then + no_cppunit=yes + else + CPPUNIT_CFLAGS=`$CPPUNIT_CONFIG --cflags` + CPPUNIT_LIBS=`$CPPUNIT_CONFIG --libs` + cppunit_version=`$CPPUNIT_CONFIG --version` + + cppunit_major_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + cppunit_minor_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + cppunit_micro_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + cppunit_major_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + cppunit_minor_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + cppunit_micro_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + cppunit_version_proper=`expr \ + $cppunit_major_version \> $cppunit_major_min \| \ + $cppunit_major_version \= $cppunit_major_min \& \ + $cppunit_minor_version \> $cppunit_minor_min \| \ + $cppunit_major_version \= $cppunit_major_min \& \ + $cppunit_minor_version \= $cppunit_minor_min \& \ + $cppunit_micro_version \>= $cppunit_micro_min ` + + if test "$cppunit_version_proper" = "1" ; then + AC_MSG_RESULT([$cppunit_major_version.$cppunit_minor_version.$cppunit_micro_version]) + else + AC_MSG_RESULT(no) + no_cppunit=yes + fi + fi + + if test "x$no_cppunit" = x ; then + ifelse([$2], , :, [$2]) + else + CPPUNIT_CFLAGS="" + CPPUNIT_LIBS="" + ifelse([$3], , :, [$3]) + fi + + AC_SUBST(CPPUNIT_CFLAGS) + AC_SUBST(CPPUNIT_LIBS) +]) + + + diff --git a/gr-howto-write-a-block/config/gr_as.m4 b/gr-howto-write-a-block/config/gr_as.m4 new file mode 100644 index 00000000..a0695473 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_as.m4 @@ -0,0 +1,34 @@ +# Figure out how to run the assembler. -*- Autoconf -*- + +# serial 2 + +# Copyright 2001 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# I just copy and renamed this from automake-1.6.3 so we should work +# under both 1.4-p6 and later. -eb + +# GR_PROG_AS +# ---------- +AC_DEFUN([GR_PROG_AS], +[# By default we simply use the C compiler to build assembly code. +AC_REQUIRE([AC_PROG_CC]) +: ${CCAS='$(CC)'} +# Set ASFLAGS if not already set. +: ${CCASFLAGS='$(CFLAGS)'} +AC_SUBST(CCAS) +AC_SUBST(CCASFLAGS)]) diff --git a/gr-howto-write-a-block/config/gr_boost.m4 b/gr-howto-write-a-block/config/gr_boost.m4 new file mode 100644 index 00000000..b1751c06 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_boost.m4 @@ -0,0 +1,111 @@ +dnl +dnl Copyright 2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl This tries to do the "right thing" to locate the boost include files. +dnl If the user explicitly specified --with-boost-include-dir= +dnl we believe them and use it. Otherwise, +dnl +dnl We look for boost/shared_ptr.hpp in the "normal places". That is, +dnl wherever AC_CHECK_HEADER looks. If the boost includes are in /usr/local/include +dnl this step will find them. +dnl +dnl Otherwise, we check to see if the boost stuff was installed in a version-specific +dnl directory under /usr/local/include. These look like: /usr/local/include/boost-1_33_1 +dnl If there's more than one version installed, we select the +dnl lexicographically greatest one. +dnl +dnl If none of these work, we bail. + +AC_DEFUN([GR_REQUIRE_BOOST_INCLUDES], +[ + AC_LANG_PUSH(C++) + gr_boost_include_dir= + AC_ARG_WITH([boost-include-dir], + AC_HELP_STRING([--with-boost-include-dir=], + [path to boost c++ include files]), + [ + # "yes" and "no" are bogus answers + if test x"$with_boost_include_dir" == xyes || + test x"$with_boost_include_dir" == xno; then + gr_boost_include_dir= + else + gr_boost_include_dir=$with_boost_include_dir + fi + ]) + echo "gr_boost_include_dir = $gr_boost_include_dir" + if test x$gr_boost_include_dir != x; then + # + # If the user specified a directory, then we use it + # + OLD_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -I$gr_boost_include_dir" + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS="-I$gr_boost_include_dir"], + [AC_MSG_ERROR( + [Failed to locate boost/shared_ptr.hpp. +Try using --with-boost-include-dir=, +E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])]) + CPPFLAGS=$OLD_CPPFLAGS + else + # + # Otherwise we check in the default places + # + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS=""], + [ # Nope, look for latest version if any in $prefix/include/boost-* + + # Wipe out cached value. KLUDGE: AC should have API for this + unset AS_TR_SH([ac_cv_header_boost/shared_ptr.hpp]) + + boost_last_match(){ + #echo "boost_last_match: [$]*" + pattern="[$]1" + shift + if test "[$]pattern" = "[$]1" + then + LM='' + else + shift `expr [$]# - 1` + LM=[$]1 + fi + #echo "LM(1)='[$]LM'" + } + + pattern="/usr/local/include/boost-*" + boost_last_match "$pattern" $pattern + #echo "LM(2)='$LM'" + + OLD_CPPFLAGS=$CPP_FLAGS + CPPFLAGS="$CPPFLAGS -I$LM" + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS="-I$LM"], + [AC_MSG_ERROR( + [Failed to locate boost/shared_ptr.hpp. +Try using --with-boost-include-dir=, +E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])]) + CPPFLAGS=$OLD_CPPFLAGS + ]) + + fi + unset boost_last_match LM + AC_LANG_POP + AC_SUBST(BOOST_CFLAGS) +]) diff --git a/gr-howto-write-a-block/config/gr_check_createfilemapping.m4 b/gr-howto-write-a-block/config/gr_check_createfilemapping.m4 new file mode 100644 index 00000000..9cb94f57 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_check_createfilemapping.m4 @@ -0,0 +1,52 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +dnl AC_DEFUN([GR_CHECK_CREATEFILEMAPPING], +dnl [ +dnl AC_CHECK_FUNCS([CreateFileMapping]) +dnl ]) + +AC_DEFUN([GR_CHECK_CREATEFILEMAPPING],[ + AC_MSG_CHECKING([for CreateFileMapping function]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + HANDLE handle; + int size; + char seg_name[[1024]]; + handle = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + size, // buffer size + seg_name); // name of mapping object + return 0; +} +],[HAVE_CREATEFILEMAPPING=yes + AC_DEFINE(HAVE_CREATEFILEMAPPING,[1],[Define if you have the CreateFilemapping function(win32).])], + [HAVE_CREATEFILEMAPPING=no]) + + AC_MSG_RESULT($HAVE_CREATEFILEMAPPING) + AM_CONDITIONAL(HAVE_CREATEFILEMAPPING, test x$HAVE_CREATEFILEMAPPING = xyes) +]) + + diff --git a/gr-howto-write-a-block/config/gr_check_mc4020.m4 b/gr-howto-write-a-block/config/gr_check_mc4020.m4 new file mode 100644 index 00000000..0c4318ef --- /dev/null +++ b/gr-howto-write-a-block/config/gr_check_mc4020.m4 @@ -0,0 +1,37 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_CHECK_MC4020],[ + AC_MSG_CHECKING([for mc4020 A/D driver include file]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + return 0; +} +],[HAVE_MC4020=yes + AC_DEFINE(HAVE_MC4020,[1],[Define if you have a Measurement Computing PCI-DAS4020/12 A/D])], + [HAVE_MC4020=no]) + + AC_MSG_RESULT($HAVE_MC4020) + AM_CONDITIONAL(HAVE_MC4020, test x$HAVE_MC4020 = xyes) +]) + diff --git a/gr-howto-write-a-block/config/gr_check_shm_open.m4 b/gr-howto-write-a-block/config/gr_check_shm_open.m4 new file mode 100644 index 00000000..27c9ee6c --- /dev/null +++ b/gr-howto-write-a-block/config/gr_check_shm_open.m4 @@ -0,0 +1,29 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_CHECK_SHM_OPEN], +[ + SHM_OPEN_LIBS="" + save_LIBS="$LIBS" + AC_SEARCH_LIBS([shm_open], [rt], [SHM_OPEN_LIBS="$LIBS"]) + AC_CHECK_FUNCS([shm_open]) + LIBS="$save_LIBS" + AC_SUBST(SHM_OPEN_LIBS) +]) diff --git a/gr-howto-write-a-block/config/gr_check_usrp.m4 b/gr-howto-write-a-block/config/gr_check_usrp.m4 new file mode 100644 index 00000000..b818a690 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_check_usrp.m4 @@ -0,0 +1,32 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl Check for Universal Software Radio Peripheral + +AC_DEFUN([GR_CHECK_USRP],[ + PKG_CHECK_MODULES(USRP, usrp >= 0.2, + [HAVE_USRP=yes + AC_DEFINE(HAVE_USRP,[1],[Define if you have a USRP])], + [HAVE_USRP=no]) + + AM_CONDITIONAL(HAVE_USRP, test x$HAVE_USRP = xyes) +]) + diff --git a/gr-howto-write-a-block/config/gr_doxygen.m4 b/gr-howto-write-a-block/config/gr_doxygen.m4 new file mode 100644 index 00000000..82aea350 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_doxygen.m4 @@ -0,0 +1,59 @@ +dnl +dnl Copyright 2003,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_CHECK_DOXYGEN],[ + AC_ARG_ENABLE(doxygen, [ --enable-doxygen enable documentation generation with doxygen (no)]) + AC_ARG_ENABLE(dot, [ --enable-dot use 'dot' to generate graphs in doxygen (auto)]) + AC_ARG_ENABLE(html-docs, [ --enable-html-docs enable HTML generation with doxygen (yes)], [], [ enable_html_docs=yes]) + AC_ARG_ENABLE(latex-docs, [ --enable-latex-docs enable LaTeX doc generation with doxygen (no)], [], [ enable_latex_docs=no]) + + if test "x$enable_doxygen" = xyes; then + AC_PATH_PROG(DOXYGEN, doxygen, , $PATH) + if test x$DOXYGEN = x; then + if test "x$enable_doxygen" = xyes; then + AC_MSG_ERROR([could not find doxygen]) + fi + enable_doc=no + generate_docs= + else + enable_doc=yes + generate_docs=docs + AC_PATH_PROG(DOT, dot, , $PATH) + fi + else + enable_doc=no + fi + + AM_CONDITIONAL(DOC, test x$enable_doc = xyes) + + if test x$DOT = x; then + if test "x$enable_dot" = xyes; then + AC_MSG_ERROR([could not find dot]) + fi + enable_dot=no + else + enable_dot=yes + fi + AC_SUBST(enable_dot) + AC_SUBST(enable_html_docs) + AC_SUBST(enable_latex_docs) + AC_SUBST(generate_docs) +]) diff --git a/gr-howto-write-a-block/config/gr_gprof.m4 b/gr-howto-write-a-block/config/gr_gprof.m4 new file mode 100644 index 00000000..cc505088 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_gprof.m4 @@ -0,0 +1,72 @@ +dnl +dnl Copyright 2002 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl FIXME probably need to add linker flag too... + +AC_DEFUN([GR_SET_GPROF],[ + dnl Check for --with-gprof + AC_MSG_CHECKING([whether user wants gprof]) + AC_ARG_WITH(gprof, + [ --with-gprof Turn on gprof profiling], + [], [ with_gprof=no ]) + AC_MSG_RESULT($with_gprof) + + dnl gprof profiling flags for the two main compilers + cc_profiling_flags="-pg" + cxx_profiling_flags="-pg" + ld_profiling_flags="-pg" + if test $with_gprof = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_profiling_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_profiling_flags) + fi + fi +]) + +AC_DEFUN([GR_SET_PROF],[ + dnl Check for --with-prof + AC_MSG_CHECKING([whether user wants prof]) + AC_ARG_WITH(prof, + [ --with-prof Turn on prof profiling], + [], [ with_prof=no ]) + AC_MSG_RESULT($with_prof) + + dnl prof profiling flags for the two main compilers + cc_profiling_flags="-p" + cxx_profiling_flags="-p" + ld_profiling_flags="-p" + if test $with_prof = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_profiling_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_profiling_flags) + fi + fi +]) diff --git a/gr-howto-write-a-block/config/gr_libgnuradio_core_extra_ldflags.m4 b/gr-howto-write-a-block/config/gr_libgnuradio_core_extra_ldflags.m4 new file mode 100644 index 00000000..491f7a04 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_libgnuradio_core_extra_ldflags.m4 @@ -0,0 +1,40 @@ +# Check for (MinGW)win32 extra ld options. -*- Autoconf -*- + +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +dnl +AC_DEFUN([GR_LIBGNURADIO_CORE_EXTRA_LDFLAGS], [ +AC_REQUIRE([AC_PROG_LD]) +# on Mingw32 extra LDFLAGS are required to ease global variable linking +LIBGNURADIO_CORE_EXTRA_LDFLAGS="" + +AC_MSG_CHECKING([whether $LD accepts --enable-runtime-pseudo-reloc]) +if ${LD} --enable-runtime-pseudo-reloc --version >/dev/null 2>&1 +then + # libtool requires the quotes + LIBGNURADIO_CORE_EXTRA_LDFLAGS="\"-Wl,--enable-runtime-pseudo-reloc\"" + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_SUBST(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +]) diff --git a/gr-howto-write-a-block/config/gr_no_undefined.m4 b/gr-howto-write-a-block/config/gr_no_undefined.m4 new file mode 100644 index 00000000..8780fab3 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_no_undefined.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# GR_NO_UNDEFINED() +# +# Detemine whether we need to use the -no-undefined linker flag +# when building shared libraries. +# Sets NO_UNDEFINED to "" or "-no-undefined" +# +# As far as I can tell, we need -no-undefined only when building +# windows DLLs. This occurs when using MinGW and Cygwin. +# +# For now, we stub this out. + +AC_DEFUN([GR_NO_UNDEFINED],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + no_undefined="" + case "${host_os}" in + *mingw* | *cygwin*) + + # on MinGW/Cygwin extra LDFLAGS are required + no_undefined="-no-undefined" + ;; + esac + AC_SUBST(NO_UNDEFINED,[$no_undefined]) +]) diff --git a/gr-howto-write-a-block/config/gr_omnithread.m4 b/gr-howto-write-a-block/config/gr_omnithread.m4 new file mode 100644 index 00000000..7c3150ba --- /dev/null +++ b/gr-howto-write-a-block/config/gr_omnithread.m4 @@ -0,0 +1,51 @@ +# Check for Omnithread (pthread/NT) thread support. -*- Autoconf -*- + +# Copyright 2003 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([GR_OMNITHREAD], +[ + # Check first for POSIX + ACX_PTHREAD( + [ ot_posix="yes" + AC_DEFINE(OMNITHREAD_POSIX,[1],[Define to 1 to enable pthread]) + ],[ + # If no POSIX support found, then check for NT threads + AC_MSG_CHECKING([for NT threads]) + + AC_LINK_IFELSE([ + #include + #include + int main() { InitializeCriticalSection(NULL); return 0; } + ], + [ + ot_nt="yes" + AC_DEFINE(OMNITHREAD_NT,[1],[Define to 1 to enable NT thread]) + ], + [AC_MSG_FAILURE([GNU Radio requires POSIX threads. pthreads not found.])] + ) + AC_MSG_RESULT(yes) + ]) + AM_CONDITIONAL(OMNITHREAD_POSIX, test "x$ot_posix" = xyes) + AM_CONDITIONAL(OMNITHREAD_NT, test "x$ot_nt" = xyes) + + save_LIBS="$LIBS" + AC_SEARCH_LIBS([clock_gettime], [rt], [PTHREAD_LIBS="$PTHREAD_LIBS $LIBS"]) + AC_CHECK_FUNCS([clock_gettime gettimeofday nanosleep]) + LIBS="$save_LIBS" +]) + diff --git a/gr-howto-write-a-block/config/gr_pwin32.m4 b/gr-howto-write-a-block/config/gr_pwin32.m4 new file mode 100644 index 00000000..5f748afc --- /dev/null +++ b/gr-howto-write-a-block/config/gr_pwin32.m4 @@ -0,0 +1,146 @@ +# Check for (mingw)win32 POSIX replacements. -*- Autoconf -*- + +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + + +AC_DEFUN([GR_PWIN32], +[ +AC_REQUIRE([AC_HEADER_TIME]) +AC_CHECK_HEADERS([sys/types.h fcntl.h io.h]) +AC_CHECK_HEADERS([windows.h]) +AC_CHECK_HEADERS([winioctl.h winbase.h], [], [], [ + #if HAVE_WINDOWS_H + #include + #endif +]) + +AC_CHECK_FUNCS([getopt usleep gettimeofday nanosleep rand srand random srandom sleep sigaction]) +AC_CHECK_TYPES([struct timezone, struct timespec, ssize_t],[],[],[ + #if HAVE_SYS_TYPES_H + # include + #endif + #if TIME_WITH_SYS_TIME + # include + # include + #else + # if HAVE_SYS_TIME_H + # include + # else + # include + # endif + #endif +]) + +dnl Checks for replacements +AC_REPLACE_FUNCS([getopt usleep gettimeofday]) + + +AC_MSG_CHECKING(for Sleep) +AC_TRY_LINK([ #include + #include + ], [ Sleep(0); ], + [AC_DEFINE(HAVE_SSLEEP,1,[Define to 1 if you have win32 Sleep]) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no) + ) + +dnl Under Win32, mkdir prototype in io.h has only one arg +AC_MSG_CHECKING(whether mkdir accepts only one arg) +AC_TRY_COMPILE([#include + #include + #include ], [ + mkdir("") + ], [ AC_MSG_RESULT(yes) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ], + [ AC_MSG_RESULT(no) + ]) + +AH_BOTTOM( +[ +/* Define missing prototypes, implemented in replacement lib */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HAVE_GETOPT +int getopt (int argc, char * const argv[], const char * optstring); +extern char * optarg; +extern int optind, opterr, optopt; +#endif + +#ifndef HAVE_USLEEP +int usleep(unsigned long usec); /* SUSv2 */ +#endif + +#ifndef HAVE_NANOSLEEP +#ifndef HAVE_STRUCT_TIMESPEC +#if HAVE_SYS_TYPES_H +# include /* need time_t */ +#endif +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +static inline int nanosleep(const struct timespec *req, struct timespec *rem) { return usleep(req->tv_sec*1000000+req->tv_nsec/1000); } +#endif + +#if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP) +#ifdef HAVE_WINBASE_H +#include +#include +#endif +/* TODO: what about SleepEx? */ +static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; } +#endif + +#ifndef HAVE_GETTIMEOFDAY +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifndef HAVE_STRUCT_TIMEZONE +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; +#endif +int gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + +#if !defined(HAVE_RANDOM) && defined(HAVE_RAND) +#include +static inline long int random (void) { return rand(); } +#endif + +#if !defined(HAVE_SRANDOM) && defined(HAVE_SRAND) +static inline void srandom (unsigned int seed) { srand(seed); } +#endif + +#ifndef HAVE_SSIZE_T +typedef size_t ssize_t; +#endif + +#ifdef __cplusplus +} +#endif +]) + + +]) diff --git a/gr-howto-write-a-block/config/gr_python.m4 b/gr-howto-write-a-block/config/gr_python.m4 new file mode 100644 index 00000000..760a0f74 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_python.m4 @@ -0,0 +1,116 @@ +dnl +dnl Copyright 2003,2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# PYTHON_DEVEL() +# +# Checks for Python and tries to get the include path to 'Python.h'. +# It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) output variables. +# +AC_DEFUN([PYTHON_DEVEL],[ + AC_REQUIRE([AM_PATH_PYTHON]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + # Check for Python include path + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON" ; then + AC_MSG_ERROR([cannot find Python path]) + fi + + # ask distutils which include path we should use + python_cmd=' +import distutils.sysconfig +import os +path = distutils.sysconfig.get_python_inc(plat_specific=False) +if os.sep == "\\": + path = path.replace("\\", "/") +print path +' + python_path=`$PYTHON -c "$python_cmd"` + AC_MSG_RESULT([$python_path]) + if test -z "$python_path" ; then + AC_MSG_ERROR([cannot find Python include path]) + fi + + AC_SUBST(PYTHON_CPPFLAGS,[-I$python_path]) + + # Check for Python headers usability + python_save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" + AC_CHECK_HEADERS([Python.h], [], + [AC_MSG_ERROR([cannot find usable Python headers])]) + CPPFLAGS="$python_save_CPPFLAGS" + + # Only set this on mingw and cygwin hosts, (only implemented + # for mingw host, for crosscompiling you need to trick this) + + PYTHON_LDFLAGS="" + case $host_os in + *mingw* | *cygwin* ) + AC_MSG_CHECKING([for Python LDFLAGS]) + + python_cmd=' +import distutils.sysconfig +import os +path = distutils.sysconfig.get_config_var("LIBPL") +if path == None: + path = distutils.sysconfig.PREFIX + "/libs" +if os.sep == "\\": + path = path.replace("\\", "/") +print path +' + python_stdlib_path=`$PYTHON -c "$python_cmd"` + + python_version_nodot=`echo $PYTHON_VERSION | sed "s,\.,,"` + libpython_name="python$PYTHON_VERSION" + + # Standard install of python for win32 has libpython24.a + # instead of libpython2.4.a so we check for the library + # without the dot in the version number. + + python_stdlib_filename=`find $python_stdlib_path -type f -name libpython$python_version_nodot.* -print | sed "1q"` + if test -n "$python_stdlib_filename" ; then + libpython_name="python$python_version_nodot" + fi + + PYTHON_LDFLAGS="-L$python_stdlib_path -l$libpython_name" + AC_MSG_RESULT($PYTHON_LDFLAGS) + # Replace all backslashes in PYTHON Paths with forward slashes + AC_MSG_CHECKING([for pythondir]) + pythondir=`echo $pythondir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pythondir) + AC_SUBST([pythondir]) + AC_MSG_CHECKING([for pkgpythondir]) + pkgpythondir=`echo $pkgpythondir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pkgpythondir) + AC_SUBST([pkgpythondir]) + AC_MSG_CHECKING([for pyexecdir]) + pyexecdir=`echo $pyexecdir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pyexecdir) + AC_SUBST([pyexecdir]) + AC_MSG_CHECKING([for pkgpyexecdir]) + pkgpyexecdir=`echo $pkgpyexecdir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pkgpyexecdir) + AC_SUBST([pkgpyexecdir]) + ;; + esac + + AC_SUBST([PYTHON_LDFLAGS]) +]) diff --git a/gr-howto-write-a-block/config/gr_require_mc4020.m4 b/gr-howto-write-a-block/config/gr_require_mc4020.m4 new file mode 100644 index 00000000..8a03eeb6 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_require_mc4020.m4 @@ -0,0 +1,33 @@ +dnl +dnl Copyright 2003,2004 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_REQUIRE_MC4020],[ + AC_MSG_CHECKING([for mc4020 A/D driver include file]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + return 0; +} +],[AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([mc4020.h not found.])]) +]) diff --git a/gr-howto-write-a-block/config/gr_scripting.m4 b/gr-howto-write-a-block/config/gr_scripting.m4 new file mode 100644 index 00000000..7f3abdee --- /dev/null +++ b/gr-howto-write-a-block/config/gr_scripting.m4 @@ -0,0 +1,30 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_SCRIPTING],[ + AC_REQUIRE([AC_PROG_LN_S]) + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PROG_LIBTOOL]) + + SWIG_PROG(1.3.23) + SWIG_ENABLE_CXX + SWIG_PYTHON +]) diff --git a/gr-howto-write-a-block/config/gr_set_md_cpu.m4 b/gr-howto-write-a-block/config/gr_set_md_cpu.m4 new file mode 100644 index 00000000..1bb2f341 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_set_md_cpu.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_SET_MD_CPU],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_ARG_WITH(md-cpu, + [ --with-md-cpu=ARCH set machine dependent speedups (auto)], + [cf_with_md_cpu="$withval"], + [cf_with_md_cpu="$host_cpu"]) + + AC_MSG_CHECKING([for machine dependent speedups]) + case "$cf_with_md_cpu" in + x86 | i[[3-7]]86) MD_CPU=x86 MD_SUBCPU=x86 ;; + x86_64) MD_CPU=x86 MD_SUBCPU=x86_64 ;; +# sparc) MD_CPU=sparc ;; + *) MD_CPU=generic ;; + esac + AC_MSG_RESULT($MD_CPU) + AC_SUBST(MD_CPU) + AC_SUBST(MD_SUBCPU) + + AM_CONDITIONAL(MD_CPU_x86, test $MD_CPU = x86) + AM_CONDITIONAL(MD_SUBCPU_x86_64, test $MD_SUBCPU = x86_64) + AM_CONDITIONAL(MD_CPU_generic, test $MD_CPU = generic) +]) + diff --git a/gr-howto-write-a-block/config/gr_swig.m4 b/gr-howto-write-a-block/config/gr_swig.m4 new file mode 100644 index 00000000..a587c6df --- /dev/null +++ b/gr-howto-write-a-block/config/gr_swig.m4 @@ -0,0 +1,85 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# SWIG_PROG([required-version]) +# +# Checks for the SWIG program. If found you can (and should) call SWIG via $(SWIG). +# You can use the optional first argument to check if the version of the available SWIG +# is greater or equal to the value of the argument. It should have the format: +# N[.N[.N]] (N is a number between 0 and 999. Only the first N is mandatory.) +AC_DEFUN([SWIG_PROG],[ + AC_REQUIRE([AC_PROG_MAKE_SET]) + AC_CHECK_PROG(SWIG,swig,[`which swig`]) + if test -z "$SWIG" ; then + AC_MSG_ERROR([Cannot find 'swig' program. SWIG version >= $1 required]) + SWIG=false + elif test -n "$1" ; then + AC_MSG_CHECKING([for SWIG version]) + swig_version=`$SWIG -version 2>&1 | \ + awk '/^SWIG Version [[0-9]+\.[0-9]+\.[0-9]]+.*$/ { split($[3],a,"[[^.0-9]]"); print a[[1]] }'` + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + swig_version=`echo $swig_version | \ + awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null` + swig_required_version=`echo $1 | \ + awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null` + if test $swig_required_version -gt $swig_version ; then + AC_MSG_ERROR([SWIG version >= $1 required]) + fi + else + AC_MSG_ERROR([cannot determine SWIG version]) + fi + fi +]) + +# SWIG_ENABLE_CXX() +# +# Enable swig C++ support. This effects all invocations of $(SWIG). +AC_DEFUN([SWIG_ENABLE_CXX],[ + AC_REQUIRE([SWIG_PROG]) + AC_REQUIRE([AC_PROG_CXX]) + if test "$SWIG" != "false" ; then + SWIG="$SWIG -c++" + fi +]) + +# SWIG_PYTHON([use-shadow-classes]) +# +# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS), +# $(SWIG_PYTHON_LIB) and $(SWIG_PYTHON_OPT) output variables. +# $(SWIG_PYTHON_OPT) contains all necessary swig options to generate +# code for Python. If you need multi module support use +# $(SWIG_PYTHON_LIB) (provided by the SWIG_MULTI_MODULE_SUPPORT() +# macro) to link against the appropriate library. It contains the +# SWIG Python runtime library that is needed by the type check system +# for example. + +AC_DEFUN([SWIG_PYTHON],[ + AC_REQUIRE([SWIG_PROG]) + AC_REQUIRE([PYTHON_DEVEL]) + if test "$SWIG" != "false" ; then + AC_SUBST(SWIG_PYTHON_LIB,[-lswigpy]) +dnl test ! "x$1" = "xno" && swig_shadow=" -shadow" || swig_shadow="" +dnl AC_SUBST(SWIG_PYTHON_OPT,[-python$swig_shadow]) + AC_SUBST(SWIG_PYTHON_OPT,[-python]) + fi + AC_SUBST(SWIG_PYTHON_CPPFLAGS,[$PYTHON_CPPFLAGS]) +]) diff --git a/gr-howto-write-a-block/config/gr_sysv_shm.m4 b/gr-howto-write-a-block/config/gr_sysv_shm.m4 new file mode 100644 index 00000000..5e11e496 --- /dev/null +++ b/gr-howto-write-a-block/config/gr_sysv_shm.m4 @@ -0,0 +1,36 @@ +# Check for IPC System V shm support. -*- Autoconf -*- + +# Copyright 2003 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([GR_SYSV_SHM], +[ + AC_LANG_SAVE + AC_LANG_C + + AC_CHECK_HEADERS([sys/ipc.h sys/shm.h]) + + save_LIBS="$LIBS" + AC_SEARCH_LIBS(shmat, [cygipc ipc], + [ IPC_LIBS="$LIBS" ], + [ AC_MSG_WARN([SystemV IPC support not found. ]) ] + ) + LIBS="$save_LIBS" + + AC_LANG_RESTORE + AC_SUBST(IPC_LIBS) +]) diff --git a/gr-howto-write-a-block/config/gr_x86_64.m4 b/gr-howto-write-a-block/config/gr_x86_64.m4 new file mode 100644 index 00000000..3d6f5eae --- /dev/null +++ b/gr-howto-write-a-block/config/gr_x86_64.m4 @@ -0,0 +1,39 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# GR_X86_64() +# +# Checks to see if we're on a x86_64 machine, and if so, ensure +# that libdir ends in "64" +# +AC_DEFUN([GR_X86_64],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + if test "$host_cpu" = "x86_64"; then + AC_MSG_CHECKING([libdir for lib64 suffix]) + t=${libdir##*/lib} + if test "$t" != 64 && test -d /lib64 && ! test -L /lib64; then + libdir=${libdir}64 + AC_MSG_RESULT([no. Setting libdir to $libdir]) + else + AC_MSG_RESULT([yes]) + fi + fi +]) diff --git a/gr-howto-write-a-block/config/lf_cc.m4 b/gr-howto-write-a-block/config/lf_cc.m4 new file mode 100644 index 00000000..f9bd7155 --- /dev/null +++ b/gr-howto-write-a-block/config/lf_cc.m4 @@ -0,0 +1,42 @@ +dnl Autoconf support for C++ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# ------------------------------------------------------------------------- +# Use this macro to configure your C compiler +# When called the macro does the following things: +# 1. It finds an appropriate C compiler. +# If you passed the flag --with-cc=foo then it uses that +# particular compiler +# 2. Check whether the compiler works. +# 3. Checks whether the compiler accepts the -g +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CONFIGURE_CC],[ + dnl Sing the song + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_CPP])dnl + AC_REQUIRE([AC_AIX])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_MINIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl +]) + diff --git a/gr-howto-write-a-block/config/lf_cxx.m4 b/gr-howto-write-a-block/config/lf_cxx.m4 new file mode 100644 index 00000000..8ade1fb2 --- /dev/null +++ b/gr-howto-write-a-block/config/lf_cxx.m4 @@ -0,0 +1,121 @@ +dnl Autoconf support for C++ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# ----------------------------------------------------------------- +# This macro should be called to configure your C++ compiler. +# When called, the macro does the following things: +# 1. It finds an appropriate C++ compiler +# If you passed the flag --with-cxx=foo, then it uses that +# particular compiler +# 2. Checks whether the compiler accepts the -g +# ------------------------------------------------------------------ + +AC_DEFUN([LF_CONFIGURE_CXX],[ + AC_REQUIRE([AC_PROG_CXX])dnl + AC_REQUIRE([AC_PROG_CXXCPP])dnl + LF_CXX_PORTABILITY +]) + +# ----------------------------------------------------------------------- +# This macro tests the C++ compiler for various portability problem. +# 1. Defines CXX_HAS_NO_BOOL if the compiler does not support the bool +# data type +# 2. Defines CXX_HAS_BUGGY_FOR_LOOPS if the compiler has buggy +# scoping for the for-loop +# 3. Defines USE_ASSERT if the user wants to use assertions +# ----------------------------------------------------------------------- + + +AC_DEFUN([LF_CXX_PORTABILITY],[ + + dnl + dnl Check for common C++ portability problems + dnl + + dnl AC_LANG_PUSH + dnl AC_LANG_CPLUSPLUS + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + dnl Check whether we have bool + AC_MSG_CHECKING(whether C++ has bool) + AC_TRY_RUN([main() { bool b1=true; bool b2=false; }], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + AC_DEFINE(CXX_HAS_NO_BOOL,[],[Define if C++ is missing bool type]) ], + [ AC_MSG_WARN(Don't cross-compile)] + ) + + dnl Test whether C++ has buggy for-loops + AC_MSG_CHECKING(whether C++ has buggy scoping in for-loops) + AC_TRY_COMPILE([#include ], [ + for (int i=0;i<10;i++) { } + for (int i=0;i<10;i++) { } +], [ AC_MSG_RESULT(no) ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(CXX_HAS_BUGGY_FOR_LOOPS,[],[Define if for loop scoping is broken]) ]) + + dnl Test whether the user wants to enable assertions + AC_MSG_CHECKING(whether user wants assertions) + AC_ARG_ENABLE(assert, + [ --disable-assert don't use cpp.h assert], + [ AC_DEFINE(NDEBUG,[],[Define to disable asserts (don't doit!)]) + AC_MSG_RESULT(no) ], + [ AC_MSG_RESULT(yes) ], + ) + + dnl Test whether C++ has std::isnan + AC_MSG_CHECKING(whether C++ has std::isnan) + AC_TRY_COMPILE([#include ], [ + std::isnan(0); +], [ AC_MSG_RESULT(yes) + AC_DEFINE(CXX_HAS_STD_ISNAN,[],[Define if has std::isnan]) ], + [ AC_MSG_RESULT(no) ]) + + dnl Done with the portability checks + dnl AC_LANG_POP([C++]) + AC_LANG_RESTORE +]) + +AH_BOTTOM([// Workaround for compilers with buggy for-loop scoping +// That's quite a few compilers actually including recent versions of +// Dec Alpha cxx, HP-UX CC and SGI CC. +// The trivial "if" statement provides the correct scoping to the +// for loop + +#ifdef CXX_HAS_BUGGY_FOR_LOOPS +#undef for +#define for if(1) for +#endif +]) + +AH_BOTTOM([// If the C++ compiler we use doesn't have bool, then +// the following is a near-perfect work-around. +// You must make sure your code does not depend on "int" and "bool" +// being two different types, in overloading for instance. + +#ifdef CXX_HAS_NO_BOOL +#define bool int +#define true 1 +#define false 0 +#endif +]) diff --git a/gr-howto-write-a-block/config/lf_warnings.m4 b/gr-howto-write-a-block/config/lf_warnings.m4 new file mode 100644 index 00000000..0ebb97ef --- /dev/null +++ b/gr-howto-write-a-block/config/lf_warnings.m4 @@ -0,0 +1,128 @@ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# -------------------------------------------------------------------------- +# Check whether the C++ compiler accepts a certain flag +# If it does it adds the flag to CXXFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_CXX_FLAG],[ + echo 'void f(){}' > conftest.cc + for i in $1 + do + AC_MSG_CHECKING([whether $CXX accepts $i]) + if test -z "`${CXX} $i -c conftest.cc 2>&1`" + then + CXXFLAGS="${CXXFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.cc conftest.o +]) + +# -------------------------------------------------------------------------- +# Check whether the C compiler accepts a certain flag +# If it does it adds the flag to CFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_CC_FLAG],[ + echo 'void f(){}' > conftest.c + for i in $1 + do + AC_MSG_CHECKING([whether $CC accepts $i]) + if test -z "`${CC} $i -c conftest.c 2>&1`" + then + CFLAGS="${CFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.c conftest.o +]) + +# -------------------------------------------------------------------------- +# Check whether the Fortran compiler accepts a certain flag +# If it does it adds the flag to FFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_F77_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_F77_FLAG],[ + cat << EOF > conftest.f +c....:++++++++++++++++++++++++ + PROGRAM MAIN + PRINT*,'Hello World!' + END +EOF + for i in $1 + do + AC_MSG_CHECKING([whether $F77 accepts $i]) + if test -z "`${F77} $i -c conftest.f 2>&1`" + then + FFLAGS="${FFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.f conftest.o +]) + +# ---------------------------------------------------------------------- +# Provide the configure script with an --with-warnings option that +# turns on warnings. Call this command AFTER you have configured ALL your +# compilers. +# ---------------------------------------------------------------------- + +AC_DEFUN([LF_SET_WARNINGS],[ + dnl Check for --with-warnings + AC_MSG_CHECKING([whether user wants warnings]) + AC_ARG_WITH(warnings, + [ --with-warnings Turn on warnings], + [ lf_warnings=yes ], [ lf_warnings=no ]) + lf_warnings=yes # hard code for now -eb + AC_MSG_RESULT($lf_warnings) + + dnl Warnings for the two main compilers + cc_warning_flags="-Wall" + cxx_warning_flags="-Wall -Woverloaded-virtual" + if test $lf_warnings = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_warning_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_warning_flags) + fi + fi +]) diff --git a/gr-howto-write-a-block/config/lf_x11.m4 b/gr-howto-write-a-block/config/lf_x11.m4 new file mode 100644 index 00000000..3bd19f24 --- /dev/null +++ b/gr-howto-write-a-block/config/lf_x11.m4 @@ -0,0 +1,39 @@ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + + +#----------------------------------------------------------------------- +# This macro searches for Xlib and when it finds it it adds the +# appropriate flags to CXXFLAGS and export the link sequence to +# the variable XLIB. +# In your configure.in file add: +# LF_PATH_XLIB +# In your Makefile.am add +# program_LDADD = .... $(XLIB) +#------------------------------------------------------------------------ + +AC_DEFUN([LF_PATH_XLIB],[ + AC_PATH_XTRA + CXXFLAGS="$CXXFLAGS $X_CFLAGS" + XLIB="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" + AC_SUBST(XLIB) +]) + diff --git a/gr-howto-write-a-block/config/mkstemp.m4 b/gr-howto-write-a-block/config/mkstemp.m4 new file mode 100644 index 00000000..4af0f0a9 --- /dev/null +++ b/gr-howto-write-a-block/config/mkstemp.m4 @@ -0,0 +1,89 @@ +#serial 4 + +# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a +# silly limit that it can create no more than 26 files from a given template. +# Other systems lack mkstemp altogether. +# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create +# only 32 files per process. +# On systems like the above, arrange to use the replacement function. +AC_DEFUN([UTILS_FUNC_MKSTEMP], +[dnl + AC_REPLACE_FUNCS(mkstemp) + if test $ac_cv_func_mkstemp = no; then + utils_cv_func_mkstemp_limitations=yes + else + AC_CACHE_CHECK([for mkstemp limitations], + utils_cv_func_mkstemp_limitations, + [ + AC_TRY_RUN([ +# include + int main () + { + int i; + for (i = 0; i < 70; i++) + { + char template[] = "conftestXXXXXX"; + int fd = mkstemp (template); + if (fd == -1) + exit (1); + close (fd); + } + exit (0); + } + ], + utils_cv_func_mkstemp_limitations=no, + utils_cv_func_mkstemp_limitations=yes, + utils_cv_func_mkstemp_limitations=yes + ) + ] + ) + fi + + if test $utils_cv_func_mkstemp_limitations = yes; then + AC_LIBOBJ(mkstemp) + AC_LIBOBJ(tempname) + AC_DEFINE(mkstemp, rpl_mkstemp, + [Define to rpl_mkstemp if the replacement function should be used.]) + gl_PREREQ_MKSTEMP + jm_PREREQ_TEMPNAME + fi +]) + +# Prerequisites of lib/mkstemp.c. +AC_DEFUN([gl_PREREQ_MKSTEMP], +[ + AH_BOTTOM( + [ + #ifndef HAVE_MKSTEMP + #ifdef __cplusplus + extern "C" { + #endif + int rpl_mkstemp (char *templ); + #ifdef __cplusplus + } + #endif + #endif + ]) +]) + +# Prerequisites of lib/tempname.c. +AC_DEFUN([jm_PREREQ_TEMPNAME], +[ + AC_REQUIRE([AC_HEADER_STAT]) + AC_CHECK_HEADERS_ONCE(fcntl.h sys/time.h unistd.h) + AC_CHECK_HEADERS(stdint.h) + AC_CHECK_FUNCS(__secure_getenv gettimeofday lstat) + AC_CHECK_DECLS_ONCE(getenv) + # AC_REQUIRE([jm_AC_TYPE_UINTMAX_T]) + + dnl Under Win32, mkdir prototype in io.h has only one arg + AC_MSG_CHECKING(whether mkdir accepts only one arg) + AC_TRY_COMPILE([#include + #include + #include ], [ + mkdir("") + ], [ AC_MSG_RESULT(yes) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ], + [ AC_MSG_RESULT(no) + ]) +]) diff --git a/gr-howto-write-a-block/config/onceonly.m4 b/gr-howto-write-a-block/config/onceonly.m4 new file mode 100644 index 00000000..f6fec37c --- /dev/null +++ b/gr-howto-write-a-block/config/onceonly.m4 @@ -0,0 +1,63 @@ +# onceonly.m4 serial 3 +dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl This file defines some "once only" variants of standard autoconf macros. +dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS +dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS +dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS +dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC +dnl The advantage is that the check for each of the headers/functions/decls +dnl will be put only once into the 'configure' file. It keeps the size of +dnl the 'configure' file down, and avoids redundant output when 'configure' +dnl is run. +dnl The drawback is that the checks cannot be conditionalized. If you write +dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi +dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to +dnl empty, and the check will be inserted before the body of the AC_DEFUNed +dnl function. + +dnl Autoconf version 2.57 or newer is recommended. +AC_PREREQ(2.54) + +# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of +# AC_CHECK_HEADERS(HEADER1 HEADER2 ...). +AC_DEFUN([AC_CHECK_HEADERS_ONCE], [ + : + AC_FOREACH([gl_HEADER_NAME], [$1], [ + AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(defn([gl_HEADER_NAME]), + [-./], [___])), [ + AC_CHECK_HEADERS(gl_HEADER_NAME) + ]) + AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, + [-./], [___]))) + ]) +]) + +# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of +# AC_CHECK_FUNCS(FUNC1 FUNC2 ...). +AC_DEFUN([AC_CHECK_FUNCS_ONCE], [ + : + AC_FOREACH([gl_FUNC_NAME], [$1], [ + AC_DEFUN([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]), [ + AC_CHECK_FUNCS(defn([gl_FUNC_NAME])) + ]) + AC_REQUIRE([gl_CHECK_FUNC_]defn([gl_FUNC_NAME])) + ]) +]) + +# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of +# AC_CHECK_DECLS(DECL1, DECL2, ...). +AC_DEFUN([AC_CHECK_DECLS_ONCE], [ + : + AC_FOREACH([gl_DECL_NAME], [$1], [ + AC_DEFUN([gl_CHECK_DECL_]defn([gl_DECL_NAME]), [ + AC_CHECK_DECLS(defn([gl_DECL_NAME])) + ]) + AC_REQUIRE([gl_CHECK_DECL_]defn([gl_DECL_NAME])) + ]) +]) diff --git a/gr-howto-write-a-block/config/pkg.m4 b/gr-howto-write-a-block/config/pkg.m4 new file mode 100644 index 00000000..770f0629 --- /dev/null +++ b/gr-howto-write-a-block/config/pkg.m4 @@ -0,0 +1,68 @@ +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN([PKG_CHECK_MODULES], [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + dnl If PKG_CONFIG_PATH is not already set, add /usr/local/lib/pkgconfig. + dnl If it's set, assume the user knows what they're doing. + dnl This should help avoid failures while looking for fftw3f + if test -z "$PKG_CONFIG_PATH"; then + export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" + fi + + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + + AC_MSG_CHECKING($1_INCLUDEDIR) + $1_INCLUDEDIR=`$PKG_CONFIG --variable=includedir "$2"` + AC_MSG_RESULT($$1_INCLUDEDIR) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + AC_SUBST($1_INCLUDEDIR) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + diff --git a/gr-howto-write-a-block/config/usrp_fusb_tech.m4 b/gr-howto-write-a-block/config/usrp_fusb_tech.m4 new file mode 100644 index 00000000..8ebbd7c8 --- /dev/null +++ b/gr-howto-write-a-block/config/usrp_fusb_tech.m4 @@ -0,0 +1,56 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_ARG_WITH(fusb-tech, + [ --with-fusb-tech=OS set fast usb technique (auto)], + [cf_with_fusb_tech="$withval"], + [cf_with_fusb_tech="$host_os"]) + + + AC_CHECK_HEADER([linux/usbdevice_fs.h], + [x_have_usbdevice_fs_h=yes], + [x_have_usbdevice_fs_h=no]) + + AC_MSG_CHECKING([for fast usb technique to use]) + case "$cf_with_fusb_tech" in + linux*) if test x${x_have_usbdevice_fs_h} = xyes; + then + FUSB_TECH=linux + else + FUSB_TECH=generic + fi ;; + + darwin*) FUSB_TECH=darwin ;; + cygwin*|win*|mingw*) FUSB_TECH=win32 ;; + *) FUSB_TECH=generic ;; + esac + + AC_MSG_RESULT($FUSB_TECH) + AC_SUBST(FUSB_TECH) + + AM_CONDITIONAL(FUSB_TECH_darwin, test $FUSB_TECH = darwin) + AM_CONDITIONAL(FUSB_TECH_win32, test $FUSB_TECH = win32) + AM_CONDITIONAL(FUSB_TECH_generic, test $FUSB_TECH = generic) + AM_CONDITIONAL(FUSB_TECH_linux, test $FUSB_TECH = linux) +]) + diff --git a/gr-howto-write-a-block/config/usrp_libusb.m4 b/gr-howto-write-a-block/config/usrp_libusb.m4 new file mode 100644 index 00000000..b1a554e4 --- /dev/null +++ b/gr-howto-write-a-block/config/usrp_libusb.m4 @@ -0,0 +1,43 @@ +# Check for libusb support. -*- Autoconf -*- + +# Copyright 2003 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([USRP_LIBUSB], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_LANG_PUSH(C) + + AC_CHECK_HEADERS([usb.h], + [], + [ AC_MSG_ERROR([USRP requires libusb. usb.h not found, stop. See http://libusb.sf.net]) ] + ) + + save_LIBS="$LIBS" + case "$host_os" in + darwin*) LIBS="$LIBS -lIOKit" ;; + *) ;; + esac + AC_SEARCH_LIBS(usb_bulk_write, [usb], + [ USB_LIBS="$LIBS" ], + [ AC_MSG_ERROR([USRP requires libusb. usb_bulk_write not found, stop. See http://libusb.sf.net]) ] + ) + LIBS="$save_LIBS" + + AC_LANG_POP + AC_SUBST(USB_LIBS) +]) diff --git a/gr-howto-write-a-block/config/usrp_sdcc.m4 b/gr-howto-write-a-block/config/usrp_sdcc.m4 new file mode 100644 index 00000000..81c255a0 --- /dev/null +++ b/gr-howto-write-a-block/config/usrp_sdcc.m4 @@ -0,0 +1,67 @@ +# Check for sdcc support. -*- Autoconf -*- + +# Copyright 2004 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([USRP_SDCC], +[ + AC_CHECK_PROG(XCC, sdcc, sdcc -mmcs51 --no-xinit-opt,no) + AC_CHECK_PROG(XAS, asx8051, asx8051 -plosgff,no) + + if test "$XCC" = "no" -o "$XAS" = "no" ; then + AC_MSG_ERROR([USRP requires sdcc. sdcc not found, stop. See http://sdcc.sf.net]) + fi + + sdcc_version_min=$1 + + sdcc_version=`sdcc --version 2>&1 | \ + sed 's/\(SDCC.* \)\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\)\( .*$\)/\2/'` + + AC_MSG_CHECKING([sdcc_version "$sdcc_version"]) + + sdcc_major_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdcc_minor_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdcc_micro_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + sdcc_major_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdcc_minor_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdcc_micro_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + sdcc_version_proper=`expr \ + "$sdcc_major_version" \> "$sdcc_major_min" \| \ + "$sdcc_major_version" \= "$sdcc_major_min" \& \ + "$sdcc_minor_version" \> "$sdcc_minor_min" \| \ + "$sdcc_major_version" \= "$sdcc_major_min" \& \ + "$sdcc_minor_version" \= "$sdcc_minor_min" \& \ + "$sdcc_micro_version" \>= "$sdcc_micro_min" ` + + if test "$sdcc_version_proper" = "1" ; then + AC_MSG_RESULT([$sdcc_major_version.$sdcc_minor_version.$sdcc_micro_version]) + else + AC_MSG_ERROR([USRP requires sdcc >= $sdcc_version_min. sdcc not found, stop. See http://sdcc.sf.net]) + fi + + AC_SUBST(XCC) + AC_SUBST(XAS) + +]) diff --git a/gr-howto-write-a-block/configure.ac b/gr-howto-write-a-block/configure.ac new file mode 100644 index 00000000..7790c69b --- /dev/null +++ b/gr-howto-write-a-block/configure.ac @@ -0,0 +1,104 @@ +dnl +dnl Copyright 2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_INIT +AC_PREREQ(2.57) +AC_CONFIG_SRCDIR([src/lib/howto.i]) +AM_CONFIG_HEADER(config.h) +AC_CANONICAL_TARGET([]) +AM_INIT_AUTOMAKE(gr-howto-write-a-block,0.6cvs) + +GR_X86_64 +dnl LF_CONFIGURE_CC +LF_CONFIGURE_CXX +LF_SET_WARNINGS +GR_SET_GPROF +GR_SET_PROF +GR_PROG_AS +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_INSTALL + +AC_LIBTOOL_WIN32_DLL +AC_ENABLE_SHARED dnl do build shared libraries +AC_DISABLE_STATIC dnl don't build static libraries +AC_PROG_LIBTOOL + +dnl Locate python, SWIG, etc +GR_NO_UNDEFINED +GR_SCRIPTING + +dnl Checks for libraries. + +dnl check for threads (mandatory) +GR_OMNITHREAD + +CFLAGS="${CFLAGS} $PTHREAD_CFLAGS" +CXXFLAGS="${CXXFLAGS} $PTHREAD_CFLAGS" + +if test "x$CXX_FOR_BUILD" = x +then + CXX_FOR_BUILD=${CXX} +fi +AC_SUBST(CXX_FOR_BUILD) + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h limits.h strings.h sys/ioctl.h sys/time.h unistd.h) +AC_CHECK_HEADERS(sys/mman.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME + +dnl Checks for library functions. +AC_CHECK_FUNCS([]) + +dnl Check for Mingw support +GR_PWIN32 + +PKG_CHECK_MODULES(GNURADIO_CORE, gnuradio-core >= 2) +LIBS="$LIBS $GNURADIO_CORE_LIBS" + +dnl Define where to find boost includes +dnl defines BOOST_CFLAGS +GR_REQUIRE_BOOST_INCLUDES + +STD_DEFINES_AND_INCLUDES="$GNURADIO_CORE_CFLAGS $BOOST_CFLAGS" +AC_SUBST(STD_DEFINES_AND_INCLUDES) + +AC_CONFIG_FILES([\ + Makefile \ + config/Makefile \ + doc/Makefile \ + src/Makefile \ + src/lib/Makefile \ + src/python/Makefile \ + src/python/run_tests \ + ]) + +dnl run_tests is created from run_tests.in. Make it executable. +AC_CONFIG_COMMANDS([run_tests], [chmod +x src/python/run_tests]) + +AC_OUTPUT diff --git a/gr-howto-write-a-block/doc/Makefile.am b/gr-howto-write-a-block/doc/Makefile.am new file mode 100644 index 00000000..33269148 --- /dev/null +++ b/gr-howto-write-a-block/doc/Makefile.am @@ -0,0 +1,81 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +TARGETS = howto-write-a-block.html + + +# To avoid build problems for folks who don't have xmlto installed, we +# don't build the docs by default. + +# html: $(TARGETS) +all: $(TARGETS) + + +EXTRA_DIST = \ + howto-write-a-block.xml \ + howto_1.i \ + make_numbered_listing.py \ + qa_howto_1.py \ + src_lib_Makefile_1.am \ + src_lib_Makefile_2.am + + +BUILT_XML_FILES = \ + gr_block.h.xml \ + howto_1.i.xml \ + howto_square_ff.cc.xml \ + howto_square_ff.h.xml \ + howto_square2_ff.cc.xml \ + howto_square2_ff.h.xml \ + qa_howto_1.py.xml \ + src_lib_Makefile_1.am.xml \ + src_lib_Makefile_2.am.xml + + +howto-write-a-block.html : howto-write-a-block.xml $(BUILT_XML_FILES) + + +gr_block.h.xml: $(GNURADIO_CORE_INCLUDEDIR)/gr_block.h make_numbered_listing.py + ./make_numbered_listing.py $< + +howto_square_ff.cc.xml: $(top_srcdir)/src/lib/howto_square_ff.cc make_numbered_listing.py + ./make_numbered_listing.py $< + +howto_square_ff.h.xml: $(top_srcdir)/src/lib/howto_square_ff.h make_numbered_listing.py + ./make_numbered_listing.py $< + +howto_square2_ff.cc.xml: $(top_srcdir)/src/lib/howto_square2_ff.cc make_numbered_listing.py + ./make_numbered_listing.py $< + +howto_square2_ff.h.xml: $(top_srcdir)/src/lib/howto_square2_ff.h make_numbered_listing.py + ./make_numbered_listing.py $< + + +# ---------------------------------------------------------------- + +clean: + -rm -f $(TARGETS) $(BUILT_XML_FILES) + +%.html : %.xml + xmlto html-nochunks $< + +%.xml : % make_numbered_listing.py + ./make_numbered_listing.py $< diff --git a/gr-howto-write-a-block/doc/howto-write-a-block.xml b/gr-howto-write-a-block/doc/howto-write-a-block.xml new file mode 100644 index 00000000..f8027b45 --- /dev/null +++ b/gr-howto-write-a-block/doc/howto-write-a-block.xml @@ -0,0 +1,959 @@ + +GNU Radio"> + SWIG"> + gr_block"> + howto_square_ff"> + + + + + + + + + + + + + + + + + + +]> + +
+ + +How to Write a Signal Processing Block + + Eric + Blossom + +
+ eb@comsec.com +
+
+
+ + + + 0.1 + 2005-01-20 + + + 0.2 + 2005-02-02 + Updated for SWIG 1.3.24 + + + 0.3 + 2006-07-21 + Clarification of 1:1 fixed rate vs item size + + + + + 2004 + 2005 + Free Software Foundation, Inc. + + +This article explains how to write signal +processing blocks for GNU Radio. + + +
+ +Prerequisites +This article assumes that the reader has basic familiarity with +GNU Radio and has read and understood + +Exploring GNU Radio. + + +There is a tarball of files that accompany this article. It +includes the examples, DocBook source for the article and all the +Makefiles etc it takes to make it work. Grab it at +ftp://ftp.gnu.org/gnu/gnuradio or one of the mirrors. The +file you want is +gr-howto-write-a-block-X.Y.tar.gz. Pick the one +with the highest version number. +See +http://comsec.com/wiki?CvsAccess for CVS Access. + + + + + +Introduction +&gnuradio; provides a framework for building software radios. +Waveforms -- signal processing applications -- are built using a +combination of Python code for high level organization, policy, GUI and +other non performance-critical functions, while performance critical +signal processing blocks are written in C++. + +From the Python point of view, &gnuradio; provides a data flow +abstraction. The fundamental concepts are signal processing +blocks and the connections between them. This abstraction is +implemented by the Python gr.flow_graph class. +Each block has a set of input ports and output ports. Each port has +an associated data type. The most common port types are +float and gr_complex +(equivalent to std::complex<float>), though other types are used, +including those representing structures, arrays or other types of +packetized data. + +From the high level point-of-view, infinite streams of data flow +through the ports. At the C++ level, streams are dealt with in +convenient sized pieces, represented as contiguous arrays of the +underlying type. + + + +The View from 30,000 Feet + +This article will walk through the construction of several +simple signal processing blocks, and explain the techniques and idioms +used. Later sections cover debugging signal processing blocks in the +mixed Python/C++ environment and performance measurement and +optimization. + +The example blocks will be built in the style of all &gnuradio; +extensions. That is, they are built outside of the gnuradio-core build +tree, and are constructed as shared libraries that may be dynamically +loaded into Python using the "import" mechanism. &SWIG;, the +Simplified Wrapper and Interface Generator, is used to generate the +glue that allows our code to be used from Python. + + + + + + +The C++ class &gr_block; is the base of all signal processing +blocks in &gnuradio;. Writing a new signal processing block involves +creating 3 files: The .h and .cc files that define the new class and +the .i file that tells &SWIG; how to generate the glue that binds the +class into Python. The new class must derive from &gr_block; or +one of it's subclasses. + +Our first examples will derive directly from &gr_block;. Later +we will look at some other subclasses that simplify the process for +common cases. + + + + + + + +Autotools, Makefiles, and Directory Layout + +Before we dive into the code, &lets; talk a bit about the +overall build environment and the directory structure that &well; +be using. + +To reduce the amount of Makefile hacking that we have to do, and +to facilitate portability across a variety of systems, we use the GNU +autoconf, +automake, and +libtool tools. These are collectively +referred to as the autotools, and once you get over the initial +shock, they will become your friends. (The good news is that we +provide boilerplate that can be used pretty much as-is.) + + + +automake + +automake and configure work together to generate GNU +compliant Makefiles from a much higher level description contained in +the corresponding Makefile.am file. Makefile.am +specifies the libraries and programs to build and the source files +that compose each. Automake reads Makefile.am +and produces Makefile.in. Configure reads +Makefile.in and produces +Makefile. The resulting Makefile contains a +zillion rules that do the right right thing to build, check and +install your code. It is not uncommon for the the resulting +Makefile to be 5 or 6 times larger than +Makefile.am. + + + + +autoconf +autoconf reads configure.ac +and produces the configure shell +script. configure automatically tests for +features of the underlying system and sets a bunch of variables and +defines that can be used in the Makefiles and your C++ code to +conditionalize the build. If features are required but not found, +configure will output an error message and stop. + + + +libtool +libtool works behind the scenes and provides the magic +to construct shared libraries on a wide variety of systems. + + + + + + shows the directory layout and +common files &well; be using. After renaming the +topdir directory, use it in your projects +too. We'll talk about particular files as they come up later. + + +Directory Layout + + + +File/Dir Name +Comment + + + + + + +topdir/Makefile.am +Top level Makefile.am + + +topdir/Makefile.common +Common fragment included in sub-Makefiles + + +topdir/bootstrap +Runs autoconf, automake, libtool first time through + + +topdir/config +Directory of m4 macros used by configure.ac + + +topdir/configure.ac +Input to autoconf + + +topdir/src + + +topdir/src/lib +C++ code goes here + + +topdir/src/lib/Makefile.am + + +topdir/src/python +Python code goes here + + +topdir/src/python/Makefile.am + + +topdir/src/python/run_tests +Script to run tests in the build tree + + + + +
+ +
+ + + +Naming Conventions + +&gnuradio; uses a set of naming conventions to assist in +comprehending the code base and gluing C++ and Python together. +Please follow them. + +<emphasis>Death to CamelCaseNames!</emphasis> + +We've returned to a kinder, gentler era. We're now using the +"STL style" naming convention with a couple of modifications +since we're not using namespaces. + +With the exception of macros and other constant values, all +identifiers shall be lower case with words_separated_like_this. + +Macros and constant values (e.g., enumerated values, +static const int FOO = 23) shall be in UPPER_CASE. + + + +Global Names + +All globally visible names (types, functions, variables, consts, etc) +shall begin with a "package prefix", followed by an underscore. The bulk of +the code in GNU Radio belongs to the "gr" package, hence +names look like gr_open_file (...). + +Large coherent bodies of code may use other package prefixes, but +let's try to keep them to a well thought out list. See the list +below. + + + +Package Prefixes + +These are the current package prefixes: + + + +gr_ +Almost everything. + + +gri_ + +Implementation primitives. Sometimes we +have both a gr_foo and a gri_foo. In that case, +gr_foo would be derived from gr_block and gri_foo +would be the low level guts of the function. + + +atsc_ +Code related to the Advanced Television Standards Committee HDTV implementation + + + +usrp_ +Universal Software Radio Peripheral. + + +qa_ +Quality Assurance (Test code.) + + + + + + + +Class Data Members (instance variables) + +All class data members shall begin with d_foo. + +The big win is when you're staring at a block of code it's obvious +which of the things being assigned to persist outside of the block. +This also keeps you from having to be creative with parameter names +for methods and constructors. You just use the same name as the +instance variable, without the d_. + + +class gr_wonderfulness { + std::string d_name; + double d_wonderfulness_factor; + +public: + gr_wonderfulness (std::string name, double wonderfulness_factor) + : d_name (name), d_wonderfulness_factor (wonderfulness_factor) + { + ... + } + ... +}; + + + + +Class Static Data Members (class variables) + + +All class static data members shall begin with s_foo. + + + + +File Names + +Each significant class shall be contained in its own file. The +declaration of class gr_foo shall be in +gr_foo.h and the definition in +gr_foo.cc. + + + +Suffixes + +By convention, we encode the input and output types of signal +processing blocks in their name using suffixes. The suffix is +typically one or two characters long. Source and sinks have single +character suffixes. Regular blocks that have both inputs and outputs +have two character suffixes. The first character indicates the type +of the input streams, the second indicates the type of the output +streams. FIR filter blocks have a three character suffix, indicating +the type of the inputs, outputs and taps, respectively. + +These are the suffix characters and their interpretations: + +f - single precision floating point +c - complex<float> +s - short (16-bit integer) +i - integer (32-bit integer) + + + +In addition, for those cases where the block deals with streams +of vectors, we use the character 'v' as the first character of the +suffix. An example of this usage is +gr_fft_vcc. The FFT block takes a vector of +complex numbers on its input and produces a vector of complex +numbers on its output. + + + + + + + + +First Block: □ + +For our first example &well; create a block that computes +the square of its single float input. This block will accept a single +float input stream and produce a single float output stream. + +Following the naming conventions, &well; use +howto as our package prefix, and the block will +be called howto_square_ff. + +We are going to arrange that this block, as well as the others +that we write in this article, end up in the +gnuradio.howto Python module. This will allow us +to access it from Python like this: + +from gnuradio import howto +sqr = howto.square_ff () + + + + +Test Driven Programming + +We could just start banging out the C++ code, but being highly +evolved modern programmers, &were; going to write the test code first. +After all, we do have a good spec for the behavior: take a single +stream of floats as the input and produce a single stream of floats as +the output. The output should be the square of the input. + +How hard could this be? Turns out that this is easy! Check out +. + + +<filename>qa_howto.py</filename> (first version) +&qa_howto_1_listing; + + + +gr_unittest is an extension to the standard +python module unittest. +gr_unittest adds support for checking +approximate equality of tuples of float and complex numbers. +Unittest uses Python's reflection mechanism to find all methods that start with +test_ and runs them. Unittest wraps each call +to test_* with matching calls to +setUp and tearDown. +See the python +unittest documentation for details. + + +When we run the test, +gr_unittest.main is going to invoke +setUp, +test_001_square_ff, and +tearDown. + +test_001_square_ff builds a small graph that +contains three nodes. gr.vector_source_f(src_data) will source the +elements of src_data and then say that &its; finished. howto.square_ff is the block +&were; testing. gr.vector_sink_f gathers the output of +howto.square_ff. + +The run method runs the graph until all +the blocks indicate they are finished. Finally, we check that the +result of executing square_ff on src_data matches what we expect. + + + + +Build Tree vs. Install Tree + +The build tree is everything from topdir +(the one containing configure.ac) down. The path to the install tree is + +prefix/lib/pythonversion/site-packages, +where prefix is the --prefix +argument to configure (default /usr/local) and +version is the installed version of +python. A typical value is +/usr/local/lib/python2.3/site-packages. + + +We normally set our PYTHONPATH environment variable to point at +the install tree, and do this in ~/.bash_profile +or ~/.profile. +This allows our python apps to access all the standard python +libraries, plus our locally installed stuff like GNU Radio. + +We write our applications such that they access the code and +libraries in the install tree. On the other hand, we want our test +code to run on the build tree, where we can detect problems before +installation. + + + +make check + + +We use make check to run our tests. +Make check invokes the run_tests shell script which +sets up the PYTHONPATH environment variable so that +our tests use the build tree versions of our code and libraries. +It then runs all files +which have names of the form qa_*.py and reports +the overall success or failure. + +There is quite a bit of behind-the-scenes action required to use +the non-installed versions of our code (look at +runtest for a cheap thrill.) + +Finally, running make check in the python +directory produces this result: + + [eb@bufo python]$ make check + make check-TESTS + make[1]: Entering directory `/home/eb/gr-build/gr-howto-write-a-block/src/python' + Traceback (most recent call last): + File "./qa_howto.py", line 24, in ? + import howto + ImportError: No module named howto + Traceback (most recent call last): + File "./qa_howto_1.py", line 24, in ? + import howto + ImportError: No module named howto + FAIL: run_tests + =================== + 1 of 1 tests failed + =================== + make[1]: *** [check-TESTS] Error 1 + make[1]: Leaving directory `/home/eb/gr-build/gr-howto-write-a-block/src/python' + make: *** [check-am] Error 2 + [eb@bufo python]$ + +Excellent! Our test failed, just as we expected. The ImportError +indicates that it can't find the module named +howto. No surprise, since we haven't written it yet. + + + + +The C++ code +Now that we've got a test case written that successfully fails, +let's write the C++ code. As we mentioned earlier, all signal +processing blocks are derived from gr_block or +one of its subclasses. Let's take a look at +. + + +<filename>gr_block.h</filename> +&gr_block_listing; + + +A quick scan of gr_block.h reveals that +since general_work is pure virtual, we +definitely need to override that. +general_work is the method that does the +actual signal processing. For our squaring example we'll +need to override general_work and provide a +constructor and destructor and a bit of stuff to take advantage of +the boost + +shared_ptrs. + + + + + +and are the header and c++ +source. + + +<filename>howto_square_ff.h</filename> +&howto_square_ff_h_listing; + + + +<filename>howto_square_ff.cc</filename> +&howto_square_ff_cc_listing; + + +Now we need a Makefile.am to get all this to build. + +is enough to build a shared library from our source file. We'll be +adding additional rules to use &SWIG; in just a bit. If you haven't +already, this is a good time to browse all the Makefile.am's in +the build tree and get an idea for how it all hangs together. + + +<filename>src/lib/Makefile.am</filename> (no &SWIG;) +&src_lib_Makefile_1_am_listing; + + + + + + + + +The &SWIG; .i file + +Now that we've got something that will compile, we need to write +the &SWIG; .i file. This is a pared-down version of the .h file, plus +a bit of magic that has python work with the boost shared_ptr's. +To reduce code bloat, we only declare methods that &well; want to +access from Python. + +We're going to call the .i file +howto.i, and use it to hold the &SWIG; +declarations for all classes from howto that will +be accessible from python. It's quite small: +&howto_1_i_listing; + + + + +Putting it all together + +Now we need to modify src/lib/Makefile.am +to run &SWIG; and to add the glue it generates to the shared library. + + +<filename>src/lib/Makefile.am</filename> (with &SWIG;) +&src_lib_Makefile_2_am_listing; + + +make now builds everything successfully. We get a +few warnings, but &thats; OK. + +Changing directories back to the python directory we try +make check again: + + [eb@bufo python]$ make check + make check-TESTS + make[1]: Entering directory `/home/eb/gr-build/gr-howto-write-a-block/src/python' + . + ---------------------------------------------------------------------- + Ran 1 test in 0.004s + + OK + PASS: run_tests + ================== + All 1 tests passed + ================== + make[1]: Leaving directory `/home/eb/gr-build/gr-howto-write-a-block/src/python' + [eb@bufo python]$ + +Victory! Our new block works! + + + + + + +Additional gr_block methods + +In our howto_square_ff example above, we only +had to override the general_work method to +accomplish our goal. gr_block provides a few other +methods that are sometimes useful. + +forecast + +Looking at general_work you may +have wondered how the system knows how much data it needs to +ensure is valid in each of the input arrays. The +forecast method provides this +information. + +The default implementation of forecast +says there is a 1:1 relationship between noutput_items and the +requirements for each input stream. The size of the items is defined by +gr_io_signatures in the constructor of +gr_block. The sizes of the input and output items +can of course differ; this still qualifies as a 1:1 relationship. + + // default implementation: 1:1 + + void + gr_block::forecast (int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items; + } + + + +Although the 1:1 implementation worked for howto_square_ff, it +wouldn't be appropriate for interpolators, decimators, or blocks +with a more complicated relationship between noutput_items and the +input requirements. That said, by deriving your classes from +gr_sync_block, +gr_sync_interpolator or +gr_sync_decimator instead of +gr_block, you can often avoid +implementing forecast. + + + +set_output_multiple + +When implementing your general_work +routine, &its; occasionally convenient to have the run time system +ensure that you are only asked to produce a number of output items +that is a multiple of some particular value. This might occur if your +algorithm naturally applies to a fixed sized block of data. +Call set_output_multiple in your constructor +to specify this requirement. The default output multiple is 1. + + + + + + + +Subclasses for common patterns + +gr_block allows tremendous flexibility +with regard to the consumption of input streams and the production of +output streams. Adroit use of forecast and +consume allows variable rate blocks to be +built. It is possible to construct blocks that consume data at +different rates on each input, and produce output at a rate that +is a function of the contents of the input data. + +On the other hand, it is very common for signal processing +blocks to have a fixed relationship between the input rate and the +output rate. Many are 1:1, while others have 1:N or N:1 +relationships. + +Another common requirement is the need to examine more than one +input sample to produce a single output sample. This is orthogonal to +the relationship between input and output rate. For example, a +non-decimating, non-interpolating FIR filter needs to examine N input +samples for each output sample it produces, where N is the number of +taps in the filter. However, it only consumes a single input sample +to produce a single output. We call this concept "history", but you +could also think of it as "look-ahead". + +<classname>gr_sync_block</classname> + + + +gr_sync_block +is derived from + +gr_block +and implements a 1:1 block with +optional history. Given that we know the input to output rate, +certain simplifications are possible. From the implementor's +point-of-view, the primary change is that we define a +work method instead of +general_work. work +has a slightly different calling sequence; +It omits the unnecessary ninput_items parameter, and arranges for +consume_each to be called on our +behalf. + + /*! + * \brief Just like gr_block::general_work, only this arranges to + * call consume_each for you. + * + * The user must override work to define the signal processing code + */ + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) = 0; + + +This gives us fewer things to worry about, and less code to +write. If the block requires history greater than 1, call +set_history in the constructor, or any time +the requirement changes. + +gr_sync_block provides a +version of forecast that handles the +history requirement. + + + +<classname>gr_sync_decimator</classname> + + + +gr_sync_decimator +is derived from + +gr_sync_block +and implements a N:1 block with optional history. + + + + +<classname>gr_sync_interpolator</classname> + + + +gr_sync_interpolator +is derived from + +gr_sync_block +and implements a 1:N block with optional history. + + + + + + + + +Second Block: <classname>howto_square2_ff</classname> + +Given that we now know about +gr_sync_block, the way +howto_square_ff should really be implemented is +by subclassing gr_sync_block. + +Here are the revised sources: , +. +The accompanying files contain the additional test code. + + + +<filename>howto_square2_ff.h</filename> +&howto_square2_ff_h_listing; + + + +<filename>howto_square2_ff.cc</filename> +&howto_square2_ff_cc_listing; + + + + +Where to from Here? + +At this point, we've got a basic overview of how the system +goes together. For more insight, I suggest that you look at the code +of the system. The doxygen generated class +hierarchy is a useful way to find things that might interest +you. + + + + +Miscellaneous Tips + +Sources and Sinks + +Sources and sinks are derived from +gr_sync_block. The only thing different about +them is that sources have no inputs and sinks have no outputs. This +is reflected in the gr_io_signatures that are +passed to the gr_sync_block constructor. +Take a look at gr_file_source.{h,cc} and +gr_file_sink.{h,cc} for some very straight-forward examples. + + + + + +Debugging with <application>gdb</application> + +If your block isn't working, and you can't sort it +out through python test cases or a few printfs in the code, you may want to +use gdb to debug it. The trick of course +is that all of &gnuradio;, including your new block, is dynamically +loaded into python for execution. + +Try this: In your python test code, after the relevant imports, +print out the process id and wait for a keystroke. In another +window run gdb and tell it to attach to the python process with the +given process id. At this point you can set breakpoints or whatever +in your code. Go back to the python window and hit Enter so +it'll continue. + + + #!/usr/bin/env python + from gnuradio import gr + from gnuradio import my_buggy_module + + # insert this in your test code... + import os + print 'Blocked waiting for GDB attach (pid = %d)' % (os.getpid(),) + raw_input ('Press Enter to continue: ') + # remainder of your test code follows... + + +Another SNAFU you might run into is that gdb 6.2 isn't +able to set breakpoints in the constructors or destructors generated +by g++ 3.4. In this case, insert a call to the nop function +gri_debugger_hook in the constructor and recompile. Load the code as +before and set a break point on gri_debugger_hook. + + + + +Performance Measurement with <application>oprofile</application> +Oprofile is your friend. +See http://oprofile.sourceforge.net. + + + + + +Coming Attractions + + +Improved Type System + + + +Hierarchical Blocks + + + + + +
diff --git a/gr-howto-write-a-block/doc/howto_1.i b/gr-howto-write-a-block/doc/howto_1.i new file mode 100644 index 00000000..640d0897 --- /dev/null +++ b/gr-howto-write-a-block/doc/howto_1.i @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "howto_square_ff.h" +#include +%} + +// ---------------------------------------------------------------- + +/* + * 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 howto_square_ff from python as howto.square_ff + */ +GR_SWIG_BLOCK_MAGIC(howto,square_ff); + +howto_square_ff_sptr howto_make_square_ff (); + +class howto_square_ff : public gr_block +{ +private: + howto_square_ff (); +}; diff --git a/gr-howto-write-a-block/doc/make_numbered_listing.py b/gr-howto-write-a-block/doc/make_numbered_listing.py new file mode 100755 index 00000000..889c2d78 --- /dev/null +++ b/gr-howto-write-a-block/doc/make_numbered_listing.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import sys +import os, os.path +from optparse import OptionParser + +def quote_line (line): + line = line.replace ('&', '&') + line = line.replace ('<', '<') + line = line.replace ('>', '>') + line = line.replace ("'", ''') + line = line.replace ('"', '"') + return line + +def generate_listing (input_filename, title=None): + inf = open (input_filename, "r") + output_filename = os.path.basename (input_filename) + '.xml' + outf = open (output_filename, "w") + outf.write ('\n') + # outf.write ('\n' % (input_filename,)) + # if not title: + # title = input_filename + # outf.write ('') + # outf.write (title) + # outf.write ('\n') + outf.write ('\n'); + + lineno = 0 + for line in inf: + line = line.expandtabs (8) + line = quote_line (line) + lineno = lineno + 1 + outf.write ('%3d %s' % (lineno, line)) + + outf.write ('\n') + # outf.write ('\n') + + +def main (): + for file in sys.argv[1:]: + generate_listing (file) + +if __name__ == '__main__': + main () + diff --git a/gr-howto-write-a-block/doc/qa_howto_1.py b/gr-howto-write-a-block/doc/qa_howto_1.py new file mode 100755 index 00000000..aa84908d --- /dev/null +++ b/gr-howto-write-a-block/doc/qa_howto_1.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest +import howto + +class qa_howto (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = 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 = howto.square_ff () + dst = gr.vector_sink_f () + self.fg.connect (src, sqr) + self.fg.connect (sqr, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 6) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-howto-write-a-block/doc/src_lib_Makefile_1.am b/gr-howto-write-a-block/doc/src_lib_Makefile_1.am new file mode 100644 index 00000000..846dd7c6 --- /dev/null +++ b/gr-howto-write-a-block/doc/src_lib_Makefile_1.am @@ -0,0 +1,25 @@ +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.howto module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +ourlib_LTLIBRARIES = _howto.la + +# These are the source files that go into the shared library +_howto_la_SOURCES = \ + howto_square_ff.cc + +# magic flags +_howto_la_LDFLAGS = -module -avoid-version + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + howto_square_ff.h + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc diff --git a/gr-howto-write-a-block/doc/src_lib_Makefile_2.am b/gr-howto-write-a-block/doc/src_lib_Makefile_2.am new file mode 100644 index 00000000..a02b40cf --- /dev/null +++ b/gr-howto-write-a-block/doc/src_lib_Makefile_2.am @@ -0,0 +1,86 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.howto module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGCPPPYTHONARGS = -noruntime -c++ -python $(PYTHON_CPPFLAGS) \ + -I$(swigincludedir) -I$(grincludedir) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i + + +LOCAL_IFILES = \ + howto.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _howto shared library +# and knows how to call our extensions. + +BUILT_SOURCES = \ + howto.cc \ + howto.py + +# This gets howto.py installed in the right place +ourpython_PYTHON = \ + howto.py + +ourlib_LTLIBRARIES = _howto.la + +# These are the source files that go into the shared library +_howto_la_SOURCES = \ + howto.cc \ + howto_square_ff.cc + +# magic flags +_howto_la_LDFLAGS = -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library +_howto_la_LIBADD = \ + -lgrswigrunpy \ + -lstdc++ + +howto.cc howto.py: howto.i $(ALL_IFILES) + $(SWIG) $(SWIGCPPPYTHONARGS) -module howto -o howto.cc $< + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + howto_square_ff.h + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc diff --git a/gr-howto-write-a-block/src/Makefile.am b/gr-howto-write-a-block/src/Makefile.am new file mode 100644 index 00000000..122fc72c --- /dev/null +++ b/gr-howto-write-a-block/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib python diff --git a/gr-howto-write-a-block/src/lib/Makefile.am b/gr-howto-write-a-block/src/lib/Makefile.am new file mode 100644 index 00000000..d4c9d35b --- /dev/null +++ b/gr-howto-write-a-block/src/lib/Makefile.am @@ -0,0 +1,94 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.howto module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(SWIGGRFLAGS) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i + + +LOCAL_IFILES = \ + howto.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _howto shared library +# and knows how to call our extensions. + +BUILT_SOURCES = \ + howto.cc \ + howto.py + +# This gets howto.py installed in the right place +ourpython_PYTHON = \ + howto.py + +ourlib_LTLIBRARIES = _howto.la + +# These are the source files that go into the shared library +_howto_la_SOURCES = \ + howto.cc \ + howto_square_ff.cc \ + howto_square2_ff.cc + +# magic flags +_howto_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library +_howto_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +howto.cc howto.py: howto.i $(ALL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module howto -o howto.cc $< + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + howto_square_ff.h \ + howto_square2_ff.h + + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done diff --git a/gr-howto-write-a-block/src/lib/howto.i b/gr-howto-write-a-block/src/lib/howto.i new file mode 100644 index 00000000..3d46ab47 --- /dev/null +++ b/gr-howto-write-a-block/src/lib/howto.i @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ + +%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 "howto_square_ff.h" +#include "howto_square2_ff.h" +#include +%} + +// ---------------------------------------------------------------- + +/* + * 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 howto_square_ff from python as howto.square_ff + */ +GR_SWIG_BLOCK_MAGIC(howto,square_ff); + +howto_square_ff_sptr howto_make_square_ff (); + +class howto_square_ff : public gr_block +{ +private: + howto_square_ff (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(howto,square2_ff); + +howto_square2_ff_sptr howto_make_square2_ff (); + +class howto_square2_ff : public gr_sync_block +{ +private: + howto_square2_ff (); +}; diff --git a/gr-howto-write-a-block/src/lib/howto_square2_ff.cc b/gr-howto-write-a-block/src/lib/howto_square2_ff.cc new file mode 100644 index 00000000..c6a52272 --- /dev/null +++ b/gr-howto-write-a-block/src/lib/howto_square2_ff.cc @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * config.h is generated by configure. It contains the results + * of probing for features, options etc. It should be the first + * file included in your .cc file. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +/* + * Create a new instance of howto_square2_ff and return + * a boost shared_ptr. This is effectively the public constructor. + */ +howto_square2_ff_sptr +howto_make_square2_ff () +{ + return howto_square2_ff_sptr (new howto_square2_ff ()); +} + +/* + * Specify constraints on number of input and output streams. + * This info is used to construct the input and output signatures + * (2nd & 3rd args to gr_block's constructor). The input and + * output signatures are used by the runtime system to + * check that a valid number and type of inputs and outputs + * are connected to this block. In this case, we accept + * only 1 input and 1 output. + */ +static const int MIN_IN = 1; // mininum number of input streams +static const int MAX_IN = 1; // maximum number of input streams +static const int MIN_OUT = 1; // minimum number of output streams +static const int MAX_OUT = 1; // maximum number of output streams + +/* + * The private constructor + */ +howto_square2_ff::howto_square2_ff () + : gr_sync_block ("square2_ff", + gr_make_io_signature (MIN_IN, MAX_IN, sizeof (float)), + gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (float))) +{ + // nothing else required in this example +} + +/* + * Our virtual destructor. + */ +howto_square2_ff::~howto_square2_ff () +{ + // nothing else required in this example +} + +int +howto_square2_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + out[i] = in[i] * in[i]; + } + + // Tell runtime system how many output items we produced. + return noutput_items; +} diff --git a/gr-howto-write-a-block/src/lib/howto_square2_ff.h b/gr-howto-write-a-block/src/lib/howto_square2_ff.h new file mode 100644 index 00000000..2d5af203 --- /dev/null +++ b/gr-howto-write-a-block/src/lib/howto_square2_ff.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_HOWTO_SQUARE2_FF_H +#define INCLUDED_HOWTO_SQUARE2_FF_H + +#include + +class howto_square2_ff; + +/* + * We use boost::shared_ptr's instead of raw pointers for all access + * to gr_blocks (and many other data structures). The shared_ptr gets + * us transparent reference counting, which greatly simplifies storage + * management issues. This is especially helpful in our hybrid + * C++ / Python system. + * + * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + * + * As a convention, the _sptr suffix indicates a boost::shared_ptr + */ +typedef boost::shared_ptr howto_square2_ff_sptr; + +/*! + * \brief Return a shared_ptr to a new instance of howto_square2_ff. + * + * To avoid accidental use of raw pointers, howto_square2_ff's + * constructor is private. howto_make_square2_ff is the public + * interface for creating new instances. + */ +howto_square2_ff_sptr howto_make_square2_ff (); + +/*! + * \brief square2 a stream of floats. + * \ingroup block + * + * This uses the preferred technique: subclassing gr_sync_block. + */ +class howto_square2_ff : public gr_sync_block +{ +private: + // The friend declaration allows howto_make_square2_ff to + // access the private constructor. + + friend howto_square2_ff_sptr howto_make_square2_ff (); + + howto_square2_ff (); // private constructor + + public: + ~howto_square2_ff (); // public destructor + + // Where all the action really happens + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_HOWTO_SQUARE2_FF_H */ diff --git a/gr-howto-write-a-block/src/lib/howto_square_ff.cc b/gr-howto-write-a-block/src/lib/howto_square_ff.cc new file mode 100644 index 00000000..a580abcb --- /dev/null +++ b/gr-howto-write-a-block/src/lib/howto_square_ff.cc @@ -0,0 +1,98 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * config.h is generated by configure. It contains the results + * of probing for features, options etc. It should be the first + * file included in your .cc file. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +/* + * Create a new instance of howto_square_ff and return + * a boost shared_ptr. This is effectively the public constructor. + */ +howto_square_ff_sptr +howto_make_square_ff () +{ + return howto_square_ff_sptr (new howto_square_ff ()); +} + +/* + * Specify constraints on number of input and output streams. + * This info is used to construct the input and output signatures + * (2nd & 3rd args to gr_block's constructor). The input and + * output signatures are used by the runtime system to + * check that a valid number and type of inputs and outputs + * are connected to this block. In this case, we accept + * only 1 input and 1 output. + */ +static const int MIN_IN = 1; // mininum number of input streams +static const int MAX_IN = 1; // maximum number of input streams +static const int MIN_OUT = 1; // minimum number of output streams +static const int MAX_OUT = 1; // maximum number of output streams + +/* + * The private constructor + */ +howto_square_ff::howto_square_ff () + : gr_block ("square_ff", + gr_make_io_signature (MIN_IN, MAX_IN, sizeof (float)), + gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (float))) +{ + // nothing else required in this example +} + +/* + * Our virtual destructor. + */ +howto_square_ff::~howto_square_ff () +{ + // nothing else required in this example +} + +int +howto_square_ff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + out[i] = in[i] * in[i]; + } + + // Tell runtime system how many input items we consumed on + // each input stream. + + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; +} diff --git a/gr-howto-write-a-block/src/lib/howto_square_ff.h b/gr-howto-write-a-block/src/lib/howto_square_ff.h new file mode 100644 index 00000000..e3709295 --- /dev/null +++ b/gr-howto-write-a-block/src/lib/howto_square_ff.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_HOWTO_SQUARE_FF_H +#define INCLUDED_HOWTO_SQUARE_FF_H + +#include + +class howto_square_ff; + +/* + * We use boost::shared_ptr's instead of raw pointers for all access + * to gr_blocks (and many other data structures). The shared_ptr gets + * us transparent reference counting, which greatly simplifies storage + * management issues. This is especially helpful in our hybrid + * C++ / Python system. + * + * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + * + * As a convention, the _sptr suffix indicates a boost::shared_ptr + */ +typedef boost::shared_ptr howto_square_ff_sptr; + +/*! + * \brief Return a shared_ptr to a new instance of howto_square_ff. + * + * To avoid accidental use of raw pointers, howto_square_ff's + * constructor is private. howto_make_square_ff is the public + * interface for creating new instances. + */ +howto_square_ff_sptr howto_make_square_ff (); + +/*! + * \brief square a stream of floats. + * \ingroup block + * + * \sa howto_square2_ff for a version that subclasses gr_sync_block. + */ +class howto_square_ff : public gr_block +{ +private: + // The friend declaration allows howto_make_square_ff to + // access the private constructor. + + friend howto_square_ff_sptr howto_make_square_ff (); + + howto_square_ff (); // private constructor + + public: + ~howto_square_ff (); // public destructor + + // Where all the action really happens + + 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_HOWTO_SQUARE_FF_H */ diff --git a/gr-howto-write-a-block/src/python/Makefile.am b/gr-howto-write-a-block/src/python/Makefile.am new file mode 100644 index 00000000..c06f34ea --- /dev/null +++ b/gr-howto-write-a-block/src/python/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +noinst_PYTHON = \ + qa_howto.py diff --git a/gr-howto-write-a-block/src/python/qa_howto.py b/gr-howto-write-a-block/src/python/qa_howto.py new file mode 100755 index 00000000..7d96d313 --- /dev/null +++ b/gr-howto-write-a-block/src/python/qa_howto.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import howto + +class qa_howto (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = 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 = howto.square_ff () + dst = gr.vector_sink_f () + self.fg.connect (src, sqr) + self.fg.connect (sqr, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 6) + + def test_002_square2_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 = howto.square2_ff () + dst = gr.vector_sink_f () + self.fg.connect (src, sqr) + self.fg.connect (sqr, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 6) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-howto-write-a-block/src/python/run_tests.in b/gr-howto-write-a-block/src/python/run_tests.in new file mode 100644 index 00000000..6e4b83ea --- /dev/null +++ b/gr-howto-write-a-block/src/python/run_tests.in @@ -0,0 +1,50 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/src/lib +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/src/lib +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/src/python + +# Where to look for installed GNU Radio python modules +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +installed_pythondir=@pythondir@ +installed_pyexecdir=@pyexecdir@ + +PYTHONPATH="$libbld:$libbld/.libs:$libsrc:$py:$installed_pythondir:$installed_pyexecdir:$PYTHONPATH" +#PYTHONPATH="$libbld:$libbld/.libs:$libsrc:$py:$installed_pythondir:$installed_pyexecdir" + +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-radar/AUTHORS b/gr-radar/AUTHORS new file mode 100644 index 00000000..ee4560a5 --- /dev/null +++ b/gr-radar/AUTHORS @@ -0,0 +1 @@ +Eric Blossom diff --git a/gr-radar/ChangeLog b/gr-radar/ChangeLog new file mode 100644 index 00000000..dde84141 --- /dev/null +++ b/gr-radar/ChangeLog @@ -0,0 +1,20 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-radar/Makefile.am b/gr-radar/Makefile.am new file mode 100644 index 00000000..9e88fe15 --- /dev/null +++ b/gr-radar/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src doc +DIST_SUBDIRS = src doc diff --git a/gr-radar/doc/Makefile.am b/gr-radar/doc/Makefile.am new file mode 100644 index 00000000..e69de29b diff --git a/gr-radar/src/Makefile.am b/gr-radar/src/Makefile.am new file mode 100644 index 00000000..122fc72c --- /dev/null +++ b/gr-radar/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib python diff --git a/gr-radar/src/lib/Makefile.am b/gr-radar/src/lib/Makefile.am new file mode 100644 index 00000000..8ea52aab --- /dev/null +++ b/gr-radar/src/lib/Makefile.am @@ -0,0 +1,118 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +LIBS += $(GNURADIO_CORE_LIBS) + +# Install this stuff so that it ends up as the gnuradio.radar module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(top_srcdr)/gnuradio-core/src/lib/swig/gnuradio.i + + +LOCAL_IFILES = + + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _howto shared library +# and knows how to call our extensions. + +BUILT_SOURCES = + +lib_LTLIBRARIES = libradar.la + +libradar_la_SOURCES = \ + time_series.h \ + time_series.cc \ + simulation.h \ + simulation.cc + +bin_PROGRAMS = \ + xambi \ + eb-xambi \ + sim-airplane \ + sim-airplane2 + +xambi_SOURCES = xambi.cc +xambi_LDADD = libradar.la + +eb_xambi_SOURCES = eb-xambi.cc +eb_xambi_LDADD = libradar.la + +sim_airplane_SOURCES = sim-airplane.cc +sim_airplane_LDADD = libradar.la + +sim_airplane2_SOURCES = sim-airplane2.cc +sim_airplane2_LDADD = libradar.la + +# This gets howto.py installed in the right place +# ourpython_PYTHON = + +#ourlib_LTLIBRARIES = _howto.la + +# These are the source files that go into the shared library +#_howto_la_SOURCES = \ +# howto.cc \ +# howto_square_ff.cc \ +# howto_square2_ff.cc + +# magic flags +#_howto_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library +#_howto_la_LIBADD = \ +# $(PYTHON_LDFLAGS) \ +# -lstdc++ + +#howto.cc howto.py: howto.i $(ALL_IFILES) +# $(SWIG) $(SWIGPYTHONARGS) -module howto -o howto.cc $< + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = + + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc + + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done diff --git a/gr-radar/src/lib/eb-xambi.cc b/gr-radar/src/lib/eb-xambi.cc new file mode 100644 index 00000000..c3c01953 --- /dev/null +++ b/gr-radar/src/lib/eb-xambi.cc @@ -0,0 +1,291 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "time_series.h" + + +gr_complex +complex_conj_dotprod(const gr_complex *a, const gr_complex *b, unsigned n) +{ + gr_complex acc = 0; + for (unsigned i = 0; i < n; i++) + acc += a[i] * conj(b[i]); + + return acc; +} + +/*! + * \brief frequency translate src by normalized_freq + * + * \param dst destination + * \param src source + * \param n length of src and dst in samples + * \param normalized_freq [-1/2, +1/2] + */ +void +freq_xlate(gr_complex *dst, const gr_complex *src, unsigned n, float normalized_freq) +{ + gr_fxpt_nco nco; + nco.set_freq(2 * M_PI * normalized_freq); + + for (unsigned int i = 0; i < n; i++){ + gr_complex phasor(nco.cos(), nco.sin()); + dst[i] = src[i] * phasor; + nco.step(); + } +} + +inline void +write_float(FILE *output, float x) +{ + fwrite(&x, sizeof(x), 1, output); +} + + +// write 8-float header +static void +write_header (FILE *output, float ndoppler_bins, float min_doppler, float max_doppler) +{ + write_float(output, ndoppler_bins); + write_float(output, min_doppler); + write_float(output, max_doppler); + write_float(output, 0); + write_float(output, 0); + write_float(output, 0); + write_float(output, 0); + write_float(output, 0); +} + + +void +main_loop(FILE *output, time_series &ref_ts, time_series &scat0_ts, + unsigned nranges, unsigned correlation_window_size, + float min_doppler, float max_doppler, int ndoppler_bins) +{ + fprintf(stderr, "ndoppler_bins = %10d\n", ndoppler_bins); + fprintf(stderr, "min_doppler = %10f\n", min_doppler); + fprintf(stderr, "max_doppler = %10f\n", max_doppler); + + // float scale_factor = 1.0/correlation_window_size; // FIXME, not sure this is right + float scale_factor = 1.0; // FIXME, not sure this is right + + boost::scoped_array shifted(new gr_complex[correlation_window_size]); + + // gr_complex shifted[correlation_window_size]; // doppler shifted reference + + float doppler_incr = 0; + if (ndoppler_bins == 1){ + min_doppler = 0; + max_doppler = 0; + } + else + doppler_incr = (max_doppler - min_doppler) / (ndoppler_bins - 1); + + write_header(output, ndoppler_bins, min_doppler, max_doppler); + + unsigned long long ro = 0; // reference offset + unsigned long long so = 0; // scatter offset + + for (unsigned int n = 0; n < nranges; n++){ + if (0){ + fprintf(stdout, "n = %6d\n", n); + fprintf(stdout, "ro = %6lld\n", ro); + fprintf(stdout, "so = %6lld\n", so); + } + const gr_complex *ref = (const gr_complex *) ref_ts.seek(ro, correlation_window_size); + const gr_complex *scat0 = (const gr_complex *) scat0_ts.seek(so, correlation_window_size); + if (ref == 0 || scat0 == 0) + return; + + for (int nd = 0; nd < ndoppler_bins; nd++){ + float fdop = min_doppler + doppler_incr * nd; + //fprintf(stderr, "fdop = %10g\n", fdop); + freq_xlate(&shifted[0], ref, correlation_window_size, fdop); // generated doppler shifted reference + + gr_complex ccor = complex_conj_dotprod(&shifted[0], scat0, correlation_window_size); + float out = norm(ccor) * scale_factor; + + // fprintf(output, "%12g\n", out); + write_float(output, out); + } + + so += 1; + } +} + +static void +usage(const char *argv0) +{ + const char *progname; + const char *t = std::strrchr(argv0, '/'); + if (t != 0) + progname = t + 1; + else + progname = argv0; + + fprintf(stderr, "usage: %s [options] ref_file scatter_file\n", progname); + fprintf(stderr, " -o OUTPUT_FILENAME [default=eb-xambi.out]\n"); + fprintf(stderr, " -m MIN_RANGE [default=0]\n"); + fprintf(stderr, " -M MAX_RANGE [default=300]\n"); + fprintf(stderr, " -w CORRELATION_WINDOW_SIZE [default=2500]\n"); + fprintf(stderr, " -s NSAMPLES_TO_SKIP [default=0]\n"); + fprintf(stderr, " -d max_doppler (normalized: [0, +1/2)) [default=.0012]\n"); + fprintf(stderr, " -n ndoppler_bins [default=31]\n"); +} + +int +main(int argc, char **argv) +{ + int ch; + int min_range = 0; + int max_range = 300; + const char *ref_filename = 0; + const char *scatter_filename = 0; + const char *output_filename = "eb-xambi.out"; + unsigned int correlation_window_size = 2500; + long long int nsamples_to_skip = 0; + double max_doppler = 0.0012; + int ndoppler_bins = 31; + + + while ((ch = getopt(argc, argv, "m:M:ho:w:s:d:n:")) != -1){ + switch (ch){ + case 'm': + min_range = strtol(optarg, 0, 0); + break; + + case 'M': + max_range = strtol(optarg, 0, 0); + break; + + case 'w': + correlation_window_size = strtol(optarg, 0, 0); + if (correlation_window_size <= 1){ + usage(argv[0]); + fprintf(stderr, " correlation_window_size must be >= 1\n"); + exit(1); + } + break; + + case 'o': + output_filename = optarg; + break; + + case 's': + nsamples_to_skip = (long long) strtof(optarg, 0); + if (nsamples_to_skip < 0){ + usage(argv[0]); + fprintf(stderr, " nsamples_to_skip must be >= 0\n"); + exit(1); + } + break; + + case 'd': + max_doppler = strtof(optarg, 0); + if (max_doppler < 0 || max_doppler >= 0.5){ + usage(argv[0]); + fprintf(stderr, " max_doppler must be in [0, 0.5)\n"); + exit(1); + } + break; + + case 'n': + ndoppler_bins = strtol(optarg, 0, 0); + if (ndoppler_bins < 1){ + usage(argv[0]); + fprintf(stderr, " ndoppler_bins must >= 1\n"); + exit(1); + } + break; + + case '?': + case 'h': + default: + usage(argv[0]); + exit(1); + } + } // while getopt + + if (argc - optind != 2){ + usage(argv[0]); + exit(1); + } + + if (max_range < min_range){ + usage(argv[0]); + fprintf(stderr, " max_range must be >= min_range\n"); + exit(1); + } + unsigned int nranges = max_range - min_range + 1; + + ref_filename = argv[optind++]; + scatter_filename = argv[optind++]; + + FILE *output = fopen(output_filename, "wb"); + if (output == 0){ + perror(output_filename); + exit(1); + } + + unsigned long long ref_starting_offset = 0; + unsigned long long scatter_starting_offset = 0; + + if (min_range < 0){ + ref_starting_offset = -min_range; + scatter_starting_offset = 0; + } + else { + ref_starting_offset = 0; + scatter_starting_offset = min_range; + } + + ref_starting_offset += nsamples_to_skip; + scatter_starting_offset += nsamples_to_skip; + + try { + time_series ref(sizeof(gr_complex), ref_filename, ref_starting_offset, 0); + time_series scat0(sizeof(gr_complex), scatter_filename, scatter_starting_offset, 0); + + main_loop(output, ref, scat0, nranges, correlation_window_size, + -max_doppler, max_doppler, ndoppler_bins); + } + catch (std::string &s){ + std::cerr << s << std::endl; + exit(1); + } + + return 0; +} + diff --git a/gr-radar/src/lib/gen_run b/gr-radar/src/lib/gen_run new file mode 100755 index 00000000..8b9549e7 --- /dev/null +++ b/gr-radar/src/lib/gen_run @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +import sys + +def main(): + window = 25000 + #window = 250000 + max_range = 99 + gifs = [] + for t in range(0, 241, 5): + sim_fn = "sim.%04d" % (t,) + xref_fn = "xref.%04d" % (t,) + ppm_fn = "i.%04d.ppm" % (t,) + gif_fn = "i.%04d.gif" % (t,) + gifs.append(gif_fn) + + sys.stdout.write("./sim-airplane2 rfm -o %s -S %d\n" % (sim_fn, t)) + sys.stdout.write("./eb-xambi -o %s -M %d -w %d -d 0.0002 rfm %s\n" % ( + xref_fn, max_range, window, sim_fn)) + sys.stdout.write("./plot_xambi_tool.m %s %s\n" % (xref_fn, ppm_fn)) + sys.stdout.write("convert -resize 800%% %s %s\n" % (ppm_fn, gif_fn)) + + sys.stdout.write("gifsicle -d 50 %s >animated.gif\n" % (' '.join(gifs))) + +if __name__ == '__main__': + main() diff --git a/gr-radar/src/lib/plot_rd.m b/gr-radar/src/lib/plot_rd.m new file mode 100644 index 00000000..166da020 --- /dev/null +++ b/gr-radar/src/lib/plot_rd.m @@ -0,0 +1,38 @@ +filename="xambi.out" + +ambdata=read_float_binary(filename); + +fftsize=512 +nranges = prod(size(ambdata))/fftsize + +ambdata=reshape(ambdata,fftsize,nranges); +% ambdata=fftshift(ambdata,1); + +% colormap(cool(256)); +colormap(rainbow(256)); + +d = 10*log10(ambdata); +min(min(d)) +max(max(d)) +imagesc(d, 2.0); + + + + + + + + + + + + + + + + + + + + + diff --git a/gr-radar/src/lib/plot_xambi.m b/gr-radar/src/lib/plot_xambi.m new file mode 100755 index 00000000..62088597 --- /dev/null +++ b/gr-radar/src/lib/plot_xambi.m @@ -0,0 +1,15 @@ +function plot_xambi(amb) + [nr, nc] = size(amb); + ndoppler_bins = nr + nranges = nc + + %colormap(cool(256)); + %colormap(rainbow(256)); + colormap(gray(1024)); + + %d = 10*log10(amb); + d = amb; + min(min(d)) + max(max(d)) + imagesc(d, 4.0); +endfunction; diff --git a/gr-radar/src/lib/plot_xambi_to_file.m b/gr-radar/src/lib/plot_xambi_to_file.m new file mode 100755 index 00000000..973d112a --- /dev/null +++ b/gr-radar/src/lib/plot_xambi_to_file.m @@ -0,0 +1,17 @@ +function plot_xambi_to_file(amb, filename) + [nr, nc] = size(amb); + ndoppler_bins = nr + nranges = nc + + %colormap(cool(256)); + %colormap(rainbow(256)); + colormap(gray(1024)); + + %d = 10*log10(amb); + d = amb; + min(min(d)) + max(max(d)) + b = imagesc(d, 4.0); + saveimage(filename, b, "ppm") + +endfunction; diff --git a/gr-radar/src/lib/plot_xambi_tool.m b/gr-radar/src/lib/plot_xambi_tool.m new file mode 100755 index 00000000..508db286 --- /dev/null +++ b/gr-radar/src/lib/plot_xambi_tool.m @@ -0,0 +1,8 @@ +#!/usr/bin/env octave + +xambi_filename = argv{1}; +ppm_filename = argv{2}; + +a = read_xambi(xambi_filename); +plot_xambi_to_file(a, ppm_filename); + diff --git a/gr-radar/src/lib/sim-airplane.cc b/gr-radar/src/lib/sim-airplane.cc new file mode 100644 index 00000000..9b27ff00 --- /dev/null +++ b/gr-radar/src/lib/sim-airplane.cc @@ -0,0 +1,296 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "time_series.h" +#include "simulation.h" + +static const double C = 3e8; // sped of light, m/s + + +// ------------------------------------------------------------------------ + +class delay_line { + std::vector d_z; + const int d_mask; + int d_newest; +public: + delay_line(unsigned int max_delay) + : d_z(gr_rounduppow2(max_delay)), d_mask(d_z.size()-1), d_newest(0) + { + } + + void + push_item(gr_complex x) + { + d_newest = (d_newest - 1) & d_mask; + d_z[d_newest] = x; + } + + gr_complex + ref_item(int delay) const + { + return d_z[(d_newest + delay) & d_mask]; + } +}; + +// ------------------------------------------------------------------------ + +class my_sim : public simulation +{ + FILE *d_output; + time_series &d_ref; + unsigned long long d_pos; // position in time series + delay_line d_z; + dyn_object *d_tx; // transmitter (not moving) + dyn_object *d_rx0; // receiver (not moving) + dyn_object *d_ac0; // aircraft (linear motion) + gr_fxpt_nco d_nco0; + + double d_baseline; // length of baseline in meters + double d_last_slant_range; + double d_range_bin; // meters/range_bin + float d_tx_lambda; // wavelength of tx signals in meters + float d_sample_rate; + float d_gain; // linear scale factor + +public: + my_sim(FILE *output, time_series &ref, double timestep, float sample_rate, + double tx_freq, double gain_db); + ~my_sim(); + + bool update(); + bool run(long long nsteps); + + bool write_output(gr_complex x) + { + return fwrite(&x, sizeof(x), 1, d_output) == 1; + } +}; + +my_sim::my_sim(FILE *output, time_series &ref, double timestep, + float sample_rate, double tx_freq, double gain_db) + : simulation(timestep), + d_output(output), d_ref(ref), d_pos(0), d_z(1024), + d_range_bin(C * timestep), d_tx_lambda(C/tx_freq), + d_sample_rate(sample_rate), d_gain(exp10(gain_db/10)) +{ + d_tx = new dyn_object(point(0,0), point(0,0), "Tx"); + d_rx0 = new dyn_object(point(45e3,0), point(0,0), "Rx0"); + + //float aircraft_speed = 135; // meters/sec (~ 300 miles/hr) + float aircraft_speed = 350; // meters/sec (~ 750 miles/hr) + float aircraft_angle = 250 * M_PI/180; + //point aircraft_pos = point(55e3, 20e3); + point aircraft_pos = point(55e3-5.54e3, 20e3-15.23e3); + d_ac0 = new dyn_object(aircraft_pos, + point(aircraft_speed * cos(aircraft_angle), + aircraft_speed * sin(aircraft_angle)), + "Ac0"); + add_object(d_tx); + add_object(d_rx0); + add_object(d_ac0); + + d_baseline = dyn_object::distance(*d_tx, *d_rx0); + d_last_slant_range = + dyn_object::distance(*d_tx, *d_ac0) + dyn_object::distance(*d_ac0, *d_rx0); +} + +my_sim::~my_sim() +{ +} + +bool +my_sim::update() +{ + // std::cout << *d_ac0 << std::endl; + + // compute slant_range and slant_range' + double slant_range = + dyn_object::distance(*d_tx, *d_ac0) + dyn_object::distance(*d_ac0, *d_rx0); // meters + double delta_slant_range = slant_range - d_last_slant_range; + d_last_slant_range = slant_range; + double deriv_slant_range_wrt_time = delta_slant_range / timestep(); // m/sec + + // fprintf(stdout, "%10.3f\t%10.3f\n", slant_range, deriv_slant_range_wrt_time); + + // grab new item from input and insert it into delay line + const gr_complex *in = (const gr_complex *) d_ref.seek(d_pos++, 1); + if (in == 0) + return false; + d_z.push_item(*in); + + // FIXME, may want to interpolate between two bins. + int int_delay = lrint((slant_range - d_baseline) / d_range_bin); + + gr_complex x = d_z.ref_item(int_delay); + + x = x * d_gain; // scale amplitude (this includes everything: RCS, antenna gain, losses, etc...) + + // compute doppler and apply it + float f_doppler = -deriv_slant_range_wrt_time / d_tx_lambda; + fprintf(stdout, "f_dop: %10.3f\n", f_doppler); + + d_nco0.set_freq(f_doppler / d_sample_rate); + gr_complex phasor(d_nco0.cos(), d_nco0.sin()); + // x = x * phasor; + d_nco0.step(); + + write_output(x); + + return simulation::update(); // run generic update +} + +bool +my_sim::run(long long nsteps) +{ + //fprintf(stdout, "<%12.2f, %12.2f>\n", d_ac0->pos().x(), d_ac0->pos().y()); + //std::cout << *d_ac0 << std::endl; + bool ok = simulation::run(nsteps); + //std::cout << *d_ac0 << std::endl; + //fprintf(stdout, "<%12.2f, %12.2f>\n", d_ac0->pos().x(), d_ac0->pos().y()); + return ok; +} + +// ------------------------------------------------------------------------ + +static void +usage(const char *argv0) +{ + const char *progname; + const char *t = std::strrchr(argv0, '/'); + if (t != 0) + progname = t + 1; + else + progname = argv0; + + fprintf(stderr, "usage: %s [options] ref_file\n", progname); + fprintf(stderr, " -o OUTPUT_FILENAME [default=sim.dat]\n"); + fprintf(stderr, " -n NSAMPLES_TO_PRODUCE [default=+inf]\n"); + fprintf(stderr, " -s NSAMPLES_TO_SKIP [default=0]\n"); + fprintf(stderr, " -g reflection gain in dB (should be <= 0) [default=0]\n"); + fprintf(stderr, " -f transmitter freq in Hz [default=100MHz]\n"); + fprintf(stderr, " -r sample rate in Hz [default=250kHz]\n"); +} + +int +main(int argc, char **argv) +{ + int ch; + const char *output_filename = "sim.dat"; + const char *ref_filename = 0; + long long int nsamples_to_skip = 0; + long long int nsamples_to_produce = std::numeric_limits::max(); + double sample_rate = 250e3; + double gain_db = 0; + double tx_freq = 100e6; + + while ((ch = getopt(argc, argv, "o:s:n:g:f:")) != -1){ + switch (ch){ + case 'o': + output_filename = optarg; + break; + + case 's': + nsamples_to_skip = (long long) strtof(optarg, 0); + if (nsamples_to_skip < 0){ + usage(argv[0]); + fprintf(stderr, " nsamples_to_skip must be >= 0\n"); + exit(1); + } + break; + + case 'n': + nsamples_to_produce = (long long) strtof(optarg, 0); + if (nsamples_to_produce < 0){ + usage(argv[0]); + fprintf(stderr, " nsamples_to_produce must be >= 0\n"); + exit(1); + } + break; + + case 'g': + gain_db = strtof(optarg, 0); + break; + + case 'f': + tx_freq = strtof(optarg, 0); + break; + + case 'r': + sample_rate = strtof(optarg, 0); + break; + + case '?': + case 'h': + default: + usage(argv[0]); + exit(1); + } + } // while getopt + + if (argc - optind != 1){ + usage(argv[0]); + exit(1); + } + + ref_filename = argv[optind++]; + + double timestep = 1.0/sample_rate; + + + FILE *output = fopen(output_filename, "wb"); + if (output == 0){ + perror(output_filename); + exit(1); + } + + unsigned long long ref_starting_offset = 0; + ref_starting_offset += nsamples_to_skip; + + try { + time_series ref(sizeof(gr_complex), ref_filename, ref_starting_offset, 0); + + my_sim simulator(output, ref, timestep, sample_rate, tx_freq, gain_db); + simulator.run(nsamples_to_produce); + } + catch (std::string &s){ + std::cerr << s << std::endl; + exit(1); + } + + return 0; +} + diff --git a/gr-radar/src/lib/sim-airplane2.cc b/gr-radar/src/lib/sim-airplane2.cc new file mode 100644 index 00000000..a8948a7b --- /dev/null +++ b/gr-radar/src/lib/sim-airplane2.cc @@ -0,0 +1,372 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "time_series.h" +#include "simulation.h" + +static const double C = 3e8; // sped of light, m/s + + +// ------------------------------------------------------------------------ + +class delay_line { + std::vector d_z; + const int d_mask; + int d_newest; +public: + delay_line(unsigned int max_delay) + : d_z(gr_rounduppow2(max_delay)), d_mask(d_z.size()-1), d_newest(0) + { + } + + void + push_item(gr_complex x) + { + d_newest = (d_newest - 1) & d_mask; + d_z[d_newest] = x; + } + + gr_complex + ref_item(int delay) const + { + return d_z[(d_newest + delay) & d_mask]; + } +}; + +// ------------------------------------------------------------------------ + +class aux_state { +public: + dyn_object *d_obj; + double d_last_slant_range; + gr_fxpt_nco d_nco; + + aux_state(dyn_object *obj) : d_obj(obj) {} +}; + +// ------------------------------------------------------------------------ + +class my_sim : public simulation +{ + FILE *d_output; + time_series &d_ref; + unsigned long long d_pos; // position in time series + delay_line d_z; + dyn_object *d_tx; // transmitter (not moving) + dyn_object *d_rx0; // receiver (not moving) + std::vector d_target; + + double d_baseline; // length of baseline in meters + double d_range_bin; // meters/range_bin + float d_tx_lambda; // wavelength of tx signals in meters + float d_sample_rate; + float d_gain; // linear scale factor + + void adjust_for_start_time(double start_time); + + bool write_output(gr_complex x) + { + return fwrite(&x, sizeof(x), 1, d_output) == 1; + } + +public: + my_sim(FILE *output, time_series &ref, double timestep, float sample_rate, + double start_time, double tx_freq, double gain_db); + ~my_sim(); + + bool update(); + bool run(long long nsteps); +}; + + +my_sim::my_sim(FILE *output, time_series &ref, double timestep, + float sample_rate, double start_time, + double tx_freq, double gain_db) + : simulation(timestep), + d_output(output), d_ref(ref), d_pos(0), d_z(1024), + d_range_bin(C * timestep), d_tx_lambda(C/tx_freq), + d_sample_rate(sample_rate), d_gain(exp10(gain_db/10)) +{ + d_tx = new dyn_object(point(0,0), point(0,0), "Tx"); + d_rx0 = new dyn_object(point(45e3,0), point(0,0), "Rx0"); + + add_object(d_tx); + add_object(d_rx0); + d_baseline = dyn_object::distance(*d_tx, *d_rx0); + + { + // add targets + float aircraft_speed; + float aircraft_angle; + point aircraft_pos; + dyn_object *ac; + + // target 1 + aircraft_speed = 135; // m/s + aircraft_angle = 240 * M_PI/180; + aircraft_pos = point(55e3, 20e3); + + ac = new dyn_object(aircraft_pos, + point(aircraft_speed * cos(aircraft_angle), + aircraft_speed * sin(aircraft_angle)), + "Ac0"); + add_object(ac); + d_target.push_back(new aux_state(ac)); + + // target 2 + aircraft_speed = 350; // m/s + aircraft_angle = 0 * M_PI/180; + aircraft_pos = point(-20e3, 60e3); + + ac = new dyn_object(aircraft_pos, + point(aircraft_speed * cos(aircraft_angle), + aircraft_speed * sin(aircraft_angle)), + "Ac1"); + add_object(ac); + d_target.push_back(new aux_state(ac)); + } + + adjust_for_start_time(start_time); + + for (unsigned i = 0; i < d_target.size(); i++) + d_target[i]->d_last_slant_range = + (dyn_object::distance(*d_tx, *d_target[i]->d_obj) + + dyn_object::distance(*d_target[i]->d_obj, *d_rx0)); + +} + +my_sim::~my_sim() +{ +} + +void +my_sim::adjust_for_start_time(double start_time) +{ + for (unsigned i = 0; i < d_obj.size(); i++){ + // Adjust initial starting positions depending on simulation + // start time. FIXME Assumes velocity is constant + point p = d_obj[i]->pos(); + point v = d_obj[i]->vel(); + p.set_x(p.x() + v.x() * start_time); + p.set_y(p.y() + v.y() * start_time); + d_obj[i]->set_pos(p); + } +} + +bool +my_sim::update() +{ + // std::cout << *d_ac0 << std::endl; + + // grab new item from input and insert it into delay line + const gr_complex *in = (const gr_complex *) d_ref.seek(d_pos++, 1); + if (in == 0) + return false; + d_z.push_item(*in); + + gr_complex s = 0; // output sample + // FIXME ought to add in attenuated direct path input + + + // for each target, compute slant_range and slant_range' + + for (unsigned i = 0; i < d_target.size(); i++){ + aux_state *t = d_target[i]; + + double slant_range = + (dyn_object::distance(*d_tx, *t->d_obj) + + dyn_object::distance(*t->d_obj, *d_rx0)); // meters + + double delta_slant_range = slant_range - t->d_last_slant_range; + t->d_last_slant_range = slant_range; + double deriv_slant_range_wrt_time = delta_slant_range / timestep(); // m/sec + + //fprintf(stdout, "%10.3f\t%10.3f\n", slant_range, deriv_slant_range_wrt_time); + + // FIXME, may want to interpolate between two bins. + int int_delay = lrint((slant_range - d_baseline) / d_range_bin); + + gr_complex x = d_z.ref_item(int_delay); + + // scale amplitude (this includes everything: RCS, antenna gain, losses, etc...) + x = x * d_gain; + + if (1){ + // compute doppler and apply it + float f_doppler = -deriv_slant_range_wrt_time / d_tx_lambda; + + t->d_nco.set_freq(f_doppler / d_sample_rate); + gr_complex phasor(t->d_nco.cos(), t->d_nco.sin()); + x = x * phasor; + t->d_nco.step(); + } + + s += x; // add in this target's contribution + } + + write_output(s); + + return simulation::update(); // run generic update +} + +bool +my_sim::run(long long nsteps) +{ + //fprintf(stdout, "<%12.2f, %12.2f>\n", d_ac0->pos().x(), d_ac0->pos().y()); + //std::cout << *d_ac0 << std::endl; + bool ok = simulation::run(nsteps); + //std::cout << *d_ac0 << std::endl; + //fprintf(stdout, "<%12.2f, %12.2f>\n", d_ac0->pos().x(), d_ac0->pos().y()); + return ok; +} + +// ------------------------------------------------------------------------ + +static void +usage(const char *argv0) +{ + const char *progname; + const char *t = std::strrchr(argv0, '/'); + if (t != 0) + progname = t + 1; + else + progname = argv0; + + fprintf(stderr, "usage: %s [options] ref_file\n", progname); + fprintf(stderr, " -o OUTPUT_FILENAME [default=sim.dat]\n"); + fprintf(stderr, " -n NSAMPLES_TO_PRODUCE [default=+inf]\n"); + fprintf(stderr, " -s NSAMPLES_TO_SKIP [default=0]\n"); + fprintf(stderr, " -g reflection gain in dB (should be <= 0) [default=0]\n"); + fprintf(stderr, " -f transmitter freq in Hz [default=100MHz]\n"); + fprintf(stderr, " -r sample rate in Hz [default=250kHz]\n"); + fprintf(stderr, " -S simulation start time in seconds [default=0]\n"); +} + +int +main(int argc, char **argv) +{ + int ch; + const char *output_filename = "sim.dat"; + const char *ref_filename = 0; + long long int nsamples_to_skip = 0; + long long int nsamples_to_produce = std::numeric_limits::max(); + double sample_rate = 250e3; + double gain_db = 0; + double tx_freq = 100e6; + double start_time = 0; + + while ((ch = getopt(argc, argv, "o:s:n:g:f:S:")) != -1){ + switch (ch){ + case 'o': + output_filename = optarg; + break; + + case 's': + nsamples_to_skip = (long long) strtof(optarg, 0); + if (nsamples_to_skip < 0){ + usage(argv[0]); + fprintf(stderr, " nsamples_to_skip must be >= 0\n"); + exit(1); + } + break; + + case 'n': + nsamples_to_produce = (long long) strtof(optarg, 0); + if (nsamples_to_produce < 0){ + usage(argv[0]); + fprintf(stderr, " nsamples_to_produce must be >= 0\n"); + exit(1); + } + break; + + case 'g': + gain_db = strtof(optarg, 0); + break; + + case 'f': + tx_freq = strtof(optarg, 0); + break; + + case 'r': + sample_rate = strtof(optarg, 0); + break; + + case 'S': + start_time = strtof(optarg, 0); + break; + + case '?': + case 'h': + default: + usage(argv[0]); + exit(1); + } + } // while getopt + + if (argc - optind != 1){ + usage(argv[0]); + exit(1); + } + + ref_filename = argv[optind++]; + + double timestep = 1.0/sample_rate; + + + FILE *output = fopen(output_filename, "wb"); + if (output == 0){ + perror(output_filename); + exit(1); + } + + unsigned long long ref_starting_offset = 0; + ref_starting_offset += nsamples_to_skip; + + try { + time_series ref(sizeof(gr_complex), ref_filename, ref_starting_offset, 0); + + my_sim simulator(output, ref, timestep, sample_rate, start_time, + tx_freq, gain_db); + simulator.run(nsamples_to_produce); + } + catch (std::string &s){ + std::cerr << s << std::endl; + exit(1); + } + + return 0; +} + diff --git a/gr-radar/src/lib/simulation.cc b/gr-radar/src/lib/simulation.cc new file mode 100644 index 00000000..4ebc7f1f --- /dev/null +++ b/gr-radar/src/lib/simulation.cc @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "simulation.h" + +bool +dyn_object::update(double delta_t) +{ + double new_x = pos().x() + delta_t * vel().x(); + double new_y = pos().y() + delta_t * vel().y(); + set_pos(point(new_x, new_y)); + return true; +} + +simulation::~simulation() +{ + for (unsigned i = 0; i < d_obj.size(); i++){ + delete d_obj[i]; + d_obj[i] = 0; + } +} + +bool +simulation::update() +{ + bool ok = true; + for (unsigned i = 0; i < d_obj.size(); i++){ + ok &= d_obj[i]->update(d_timestep); + } + d_now += d_timestep; + return ok; +} + +bool +simulation::run(long long nsteps) +{ + for (long long i = 0; i < nsteps; i++) + if (!update()) + return false; + + return true; +} + +void +simulation::add_object(dyn_object *obj) +{ + d_obj.push_back(obj); +} + +// ---------------------------------------------------------------- + +std::ostream& operator<<(std::ostream& out, const dyn_object& o) +{ + out << "<" << o.name() + << " pos: " << o.pos() + << " vel: " << o.vel() + << ">"; + return out; +} + +std::ostream& operator<<(std::ostream& out, const point& p) +{ + out << "(" << p.x() << ", " << p.y() << ")"; + return out; +} + diff --git a/gr-radar/src/lib/simulation.h b/gr-radar/src/lib/simulation.h new file mode 100644 index 00000000..ff32484e --- /dev/null +++ b/gr-radar/src/lib/simulation.h @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_SIMULATION_H +#define INCLUDED_SIMULATION_H + +#include +#include +#include +#include + + +class point { + double d_x, d_y; +public: + point(double x = 0, double y = 0) : d_x(x), d_y(y) {} + + double x() const { return d_x; } + double y() const { return d_y; } + + void set_x(double x) { d_x = x; } + void set_y(double y) { d_y = y; } + + static point + add(const point &p1, const point &p2) + { + return point(p1.x() + p2.x(), + p1.y() + p2.y()); + } + + static point + sub(const point &p1, const point &p2) + { + return point(p1.x() - p2.x(), p1.y() - p2.y()); + } + + static double + distance(const point &p1, const point &p2) + { + point d = point::sub(p1, p2); + return std::sqrt(d.x()*d.x() + d.y()*d.y()); + } + +}; + + +class dyn_object { + point d_pos; + point d_vel; + std::string d_name; +public: + dyn_object(point pos=point(0,0), point vel=point(0,0), const std::string name="") + : d_pos(pos), d_vel(vel), d_name(name) {} + + virtual ~dyn_object() {} + + point pos() const { return d_pos; } + point vel() const { return d_vel; } + std::string name() const { return d_name; } + + void set_pos(point pos) { d_pos = pos; } + void set_vel(point vel) { d_vel = vel; } + + virtual bool update(double delta_t); + + static double + distance(const dyn_object &o1, const dyn_object &o2) + { + return point::distance(o1.pos(), o2.pos()); + } + +}; + + +class simulation { + double d_timestep; + double d_now; +protected: + std::vector d_obj; + +public: + simulation(double timestep = 1.0, double now = 0.0) + : d_timestep(timestep), d_now(now) {} + virtual ~simulation(); + virtual bool update(); + virtual bool run(long long nsteps); + + void add_object(dyn_object *obj); + double now() const { return d_now; } + double timestep() const { return d_timestep; } +}; + +std::ostream& operator<<(std::ostream& out, const dyn_object& o); +std::ostream& operator<<(std::ostream& out, const point& p); + +#endif /* INCLUDED_SIMULATION_H */ + diff --git a/gr-radar/src/lib/time_series.cc b/gr-radar/src/lib/time_series.cc new file mode 100644 index 00000000..2767165d --- /dev/null +++ b/gr-radar/src/lib/time_series.cc @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "time_series.h" +#include +#include +#include +#include +#include +#include + + +time_series::time_series(size_t itemsize, const std::string filename, + unsigned long long starting_offset, + long long nsamples_to_process) + : d_itemsize(itemsize), d_filename(filename), d_fd(-1), + d_start(starting_offset), d_buffer(0) +{ + if ((d_fd = open(d_filename.c_str(), O_RDONLY | O_LARGEFILE, 0660)) == -1){ + perror(d_filename.c_str()); + throw std::string("open failed: ") + d_filename; + } + + struct stat statbuf; + if (fstat(d_fd, &statbuf) == -1){ + perror(d_filename.c_str()); + throw std::string("fstat failed: ") + d_filename; + } + d_filesize = statbuf.st_size; + d_limit = d_filesize / d_itemsize; + + if (d_start > d_limit){ + std::string s = std::string("d_start > filesize: ") + d_filename; + std::cerr << s + << " d_start " << d_start + << " d_limit " << d_limit << std::endl; + throw s; + } + + if (nsamples_to_process > 0) + if ((d_start + nsamples_to_process) < d_limit) + d_limit = d_start + nsamples_to_process; + + d_buffer = mmap(0, d_filesize, PROT_READ, MAP_SHARED, d_fd, 0); + if (d_buffer == MAP_FAILED){ + perror("mmap"); + throw std::string("mmap failed: ") + d_filename; + } +} + +time_series::~time_series() +{ + munmap(d_buffer, d_filesize); + close(d_fd); +} + +const void * +time_series::seek(unsigned long long pos, unsigned long long blocksize) const +{ + if ((d_start + pos + blocksize) >= d_limit) + return 0; + + return (const void *)((char *)d_buffer + ((d_start + pos) * d_itemsize)); +} + +long long +time_series::nsamples_available(unsigned long long pos) const +{ + if ((d_start + pos) >= d_limit) + return 0; + + return d_limit - (d_start + pos); +} diff --git a/gr-radar/src/lib/time_series.h b/gr-radar/src/lib/time_series.h new file mode 100644 index 00000000..3764ba50 --- /dev/null +++ b/gr-radar/src/lib/time_series.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_TIME_SERIES_H +#define INCLUDED_TIME_SERIES_H + +#include + +/*! + * \brief Memory mapped input for complex time series data + * + * Inspired by "iqts" by John Sahr, Univ of Washington + */ + +class time_series { + size_t d_itemsize; // user specified item size + std::string d_filename; + int d_fd; // file descriptor + unsigned long long d_filesize; // in bytes + unsigned long long d_start; // in items + unsigned long long d_limit; // in items + void *d_buffer; // points to base of file + +public: + /*! + * \brief Create read-only mapped file accessor. + * \param item_size size of item in bytes + * \param filename name of file to open + * \param starting_offset offset in file in item_size units at which to start + * \param nsamples_to_process maximum number of samples to map in starting at \p start. -1 implies no limit. + * + * \throws string on error opening file, etc. + */ + time_series(size_t item_size, const std::string filename, + unsigned long long starting_offset=0, + long long nsamples_to_process=-1); + ~time_series(); + + /*! + * \brief Return a pointer to a buffer of data at file offset pos. + * + * \param pos offset from beginning of file in itemsize units. + * \param blocksize minimum size of returned buffer in itemsize units. + * + * "Seek" to pos in file and return a pointer to the data at that + * location. The returned pointer will have at least blocksize valid + * elements. Return 0 if pos is out of bounds, or if there isn't + * at least blocksize units available in the file. + */ + const void *seek(unsigned long long pos, unsigned long long blocksize) const; + + long long nsamples_available(unsigned long long pos) const; +}; + +#endif /* INCLUDED_TIME_SERIES_H */ diff --git a/gr-radar/src/lib/xambi.cc b/gr-radar/src/lib/xambi.cc new file mode 100644 index 00000000..e5d4a9a9 --- /dev/null +++ b/gr-radar/src/lib/xambi.cc @@ -0,0 +1,259 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include +#include +#include "time_series.h" + + +using namespace std; + +/*! + * \file xambi.cc driver for computation of cross ambiguity + * + * Based on ideas liberally lifted from a version of xambi.cc + * obtained from John Sahr, that identified these people as authors: + * John Sahr jdsahr@u.washington.edu + * Frank Lind flind@haystack.mit.edu + * Chucai "Cliff" Zhou + * Melissa Meyer mgmeyer@ee.washington.edu + * + * Extensively revised since then. + */ + +static int default_decimation = 40; +static int default_fftsize = 256; +static int default_naverages = 1000000; // infinite + +/// usage for the xambi program + +static void usage(char *argv0) +{ + cerr << "usage: xambi [opts] scatterfile" << endl; + cerr << " where [opts] are" << endl; + cerr << " -x reffilename : Required" << endl; + cerr << " -o outputfilename[=xambi.out] : create or overwrite" << endl; + cerr << " -a averages[=100000] : restart accumulation; 100000 = infinite" << endl; + cerr << " -d decimationfactor[=40]" << endl; + cerr << " -f fftsize[=256]" << endl; + cerr << " -r range[=0] : first range" << endl; + cerr << " -n nranges[=1] : range count" << endl; + cerr << " -S start[=0] : starting offset in file" << endl; + cerr << " -N nsamples[=inf] : # of samples to process" << endl; + cerr << " -v : increment verbosity" << endl; + cerr << " -h : be helpful" << endl; + cerr << endl; + cerr << "The reffile and scatterfile are native-endian binary complex" << endl; + cerr << "and must be sampled at the same rate." << endl; + + exit(0); +} + +gr_complex +complex_dot_product(const gr_complex *xx, const gr_complex *yy, int nterms) +{ + gr_complex sum(0); + + for (int i = 0; i < nterms; i++) + sum += xx[i] * yy[i]; // FIXME? conj(yy[i]) + + return sum; +} + + +/// the main driver + +int +main(int argc, char *argv[]) +{ + char *ref_fname = 0; //< holds name of reference signal source + char *out_fname = 0; //< holds name of processed output + int decimation = default_decimation; + int range = 0; //< first range of range block + int nranges = 1; //< number of ranges of range block + int fftsize = default_fftsize; + int naverages = default_naverages; + int verbosity = 0; + int blocksize = 0; + int offset = 0; + unsigned long long starting_file_offset = 0; + unsigned long long nsamples_to_process = (unsigned long long) -1; + + int f; + + const gr_complex *x, *y; + const gr_complex *xx, *yy; + + int c; // used to process the command line + int r; // an index to count over ranges + int i; // an index to count through the time series + int a; + + while((c = getopt(argc,argv,"a:o:x:y:r:d:f:n:hvS:N:")) != EOF) { + switch(c) { + case 'x': ref_fname = optarg; break; + case 'o': out_fname = optarg; break; + case 'a': naverages = atoi(optarg); break; + case 'd': decimation = atoi(optarg); break; + case 'r': range = atoi(optarg); break; + case 'n': nranges = atoi(optarg); break; + case 'f': fftsize = atoi(optarg); break; + case 'S': starting_file_offset = strtoll(optarg, 0, 0); break; + case 'N': nsamples_to_process = strtoll(optarg, 0, 0); break; + case 'v': verbosity++; break; + case 'h': usage(argv[0]); break; + default: usage(argv[0]); break; + } + } + + // Wrapper for FFTW 1d forward FFT. N.B. output is not scaled by 1/fftsize + gri_fft_complex fft(fftsize, true); + gr_complex *fft_input = fft.get_inbuf(); + gr_complex *fft_output = fft.get_outbuf(); + + if(range < 0) { + cerr << "you specified -r " << range << "; must be non-negative (exit)" << endl; + exit(1); + } + + if(nranges < 1) { + cerr << "you specified -n " << nranges << "; must be positive (exit)" << endl; + exit(1); + } + + if(decimation < 1) { + cerr << "you specified -d " << decimation << "; must be positive (exit)" << endl; + exit(1); + } + + if(naverages < 1) { + cerr << "you specified -a " << naverages << "; must be positive (exit)" << endl; + exit(1); + } + + if(ref_fname == 0) { + cerr << "you must specify a reference signal with the -x option" << endl; + usage(argv[0]); + } + + if (optind >= argc) { + cerr << "you must specify a scattering signal after all other options" << endl; + usage(argv[0]); + } + + time_series X(sizeof(gr_complex), ref_fname, + starting_file_offset, nsamples_to_process); + + time_series Y(sizeof(gr_complex), argv[optind], + starting_file_offset, nsamples_to_process); // add more for interferometry ... + + float psd[fftsize*nranges]; + + if(out_fname == 0) { + char fname[200]; + snprintf(fname, sizeof(fname), "%s.out", "xambi"); + out_fname = fname; + } + + ofstream Z(out_fname); + + blocksize = fftsize*decimation + nranges; + offset = 0; + a = 0; + + // the fftsize is squared because we're using norm, not abs, + // when computing the psd + float scale_factor = 1.0 / (fftsize * fftsize); + + for(i = 0; i < nranges*fftsize; i++) + psd[i] = 0.0; + + + while(1){ // loop over data until exhausted. + if(verbosity > 1) { + cerr << " " << a; // write out the number of completed averages + cerr.flush(); + } + + x = (const gr_complex *) X.seek(offset, blocksize); + y = (const gr_complex *) Y.seek(offset + range, blocksize); + + if(!x || !y) // ran out of data; stop integrating + break; + + for(r = 0; r < nranges; r++) { // For Each Range ... + xx = x; + yy = y + r; + + for(f = 0; f < fftsize; f++) { // and for each Doppler bin ... + + // cross correlate and do a boxcar decimation + + fft_input[f] = complex_dot_product(xx, yy, decimation); + xx += decimation; + yy += decimation; + } + + fft.execute(); // input: fft_input; output: fft_output + + for(f = 0; f < fftsize; f++) { + psd[r*fftsize + f] += norm(fft_output[f]); + } + } // end range + + a++; + offset += fftsize * decimation; + + if(a >= naverages) { + if(verbosity > 0) + cerr << " dumping " << endl; + + for(i = 0; i < nranges*fftsize; i++) // normalize + psd[i] *= scale_factor; + + Z.write((const char *) psd, nranges*fftsize*sizeof(float)); + + for(i = 0; i < nranges*fftsize; i++) + psd[i] = 0.0; + + a = 0; + } + } + + if(verbosity > 1) + printf("\n"); + + if(a > 0) { + for(i = 0; i < nranges*fftsize; i++) // normalize + psd[i] *= scale_factor; + + Z.write((const char *) psd, nranges*fftsize*sizeof(float)); + } + + return 0; +} + diff --git a/gr-radar/src/python/Makefile.am b/gr-radar/src/python/Makefile.am new file mode 100644 index 00000000..da81410f --- /dev/null +++ b/gr-radar/src/python/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +noinst_PYTHON = \ + qa_nothing.py \ + usrp_rx_radar.py diff --git a/gr-radar/src/python/complex_to_short.py b/gr-radar/src/python/complex_to_short.py new file mode 100755 index 00000000..9c229d85 --- /dev/null +++ b/gr-radar/src/python/complex_to_short.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os.path +import re + +class my_graph(gr.flow_graph): + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] input_file output_file" + parser = OptionParser (option_class=eng_option, usage=usage) + (options, args) = parser.parse_args() + if len(args) != 2: + parser.print_help() + raise SystemExit, 1 + + input_filename = args[0] + output_filename = args[1] + + inf = gr.file_source(gr.sizeof_gr_complex, input_filename) + c2s = gr.complex_to_interleaved_short() + outf = gr.file_sink(gr.sizeof_short, output_filename) + self.connect(inf, c2s, outf) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gr-radar/src/python/fm_demod_file.py b/gr-radar/src/python/fm_demod_file.py new file mode 100755 index 00000000..9d430a89 --- /dev/null +++ b/gr-radar/src/python/fm_demod_file.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Demod FM signal in data collected for radar. +Input samples are complex baseband, 250kS/sec. +""" + +from gnuradio import gr, gru, blks, eng_notation +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + + +class my_graph(gr.flow_graph): + def __init__(self, input_filename, repeat): + gr.flow_graph.__init__(self) + + baseband_rate = 250e3 + audio_decim = 8 + audio_rate = int(baseband_rate // audio_decim) # output is at 31250 S/s + + src = gr.file_source(gr.sizeof_gr_complex, input_filename, repeat) + guts = blks.wfm_rcv(self, baseband_rate, audio_decim) + sink = audio.sink(audio_rate, "plughw:0,0") + self.connect(src, guts, sink) + +def main (): + usage = "usage: %prog [options] filename" + parser = OptionParser (option_class=eng_option, usage=usage) + parser.add_option ("-r", "--repeat", action="store_true", default=False) + (options, args) = parser.parse_args () + + if len (args) != 1: + parser.print_help () + sys.exit (1) + + try: + my_graph(args[0], options.repeat).run() + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main () diff --git a/gr-radar/src/python/gen_fm_signal.py b/gr-radar/src/python/gen_fm_signal.py new file mode 100755 index 00000000..cd0834aa --- /dev/null +++ b/gr-radar/src/python/gen_fm_signal.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks, eng_notation +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + + +class my_graph(gr.flow_graph): + def __init__(self, output_filename, tx_gain, nsamples): + gr.flow_graph.__init__(self) + + audio_rate = 31250 + baseband_rate = 250e3 + + src = gr.noise_source_f(gr.GR_GAUSSIAN, 1.0) + #src = gr.noise_source_f(gr.GR_GAUSSIAN, 0.5) + guts = blks.wfm_tx(self, audio_rate, baseband_rate) + amp = gr.multiply_const_cc(tx_gain) + head = gr.head(gr.sizeof_gr_complex, nsamples) + sink = gr.file_sink(gr.sizeof_gr_complex, output_filename) + self.connect(src, guts, amp, head, sink) + +def main (): + usage = "usage: %prog [options] output_filename" + parser = OptionParser (option_class=eng_option, usage=usage) + parser.add_option("-N", "--nsamples", type="eng_float", default=250000, + help="specify number of output samples to generate[=250000]") + parser.add_option("-g", "--tx-gain", type="eng_float", default=1.0, + help="specify transmitter gain[=1]") + (options, args) = parser.parse_args () + + if len (args) != 1: + parser.print_help () + sys.exit (1) + + try: + my_graph(args[0], options.tx_gain, int(options.nsamples)).run() + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main () diff --git a/gr-radar/src/python/gen_random_signal.py b/gr-radar/src/python/gen_random_signal.py new file mode 100755 index 00000000..87a531c6 --- /dev/null +++ b/gr-radar/src/python/gen_random_signal.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, blks, eng_notation +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + + +class my_graph(gr.flow_graph): + def __init__(self, output_filename, tx_gain, nsamples): + gr.flow_graph.__init__(self) + + audio_rate = 31250 + baseband_rate = 250e3 + + src = gr.noise_source_c(gr.GR_GAUSSIAN, 1.0) + #src = gr.noise_source_f(gr.GR_GAUSSIAN, 0.5) + #guts = blks.wfm_tx(self, audio_rate, baseband_rate) + amp = gr.multiply_const_cc(tx_gain) + head = gr.head(gr.sizeof_gr_complex, nsamples) + sink = gr.file_sink(gr.sizeof_gr_complex, output_filename) + self.connect(src, amp, head, sink) + +def main (): + usage = "usage: %prog [options] output_filename" + parser = OptionParser (option_class=eng_option, usage=usage) + parser.add_option("-N", "--nsamples", type="eng_float", default=250000, + help="specify number of output samples to generate[=250000]") + parser.add_option("-g", "--tx-gain", type="eng_float", default=1.0, + help="specify transmitter gain[=1]") + (options, args) = parser.parse_args () + + if len (args) != 1: + parser.print_help () + sys.exit (1) + + try: + my_graph(args[0], options.tx_gain, int(options.nsamples)).run() + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main () diff --git a/gr-radar/src/python/qa_nothing.py b/gr-radar/src/python/qa_nothing.py new file mode 100755 index 00000000..e69de29b diff --git a/gr-radar/src/python/run_tests.in b/gr-radar/src/python/run_tests.in new file mode 100644 index 00000000..fd0a43ab --- /dev/null +++ b/gr-radar/src/python/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@gr-radar/src/lib +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-radar/src/lib +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-radar/src/python + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-radar/src/python/signal_levels.py b/gr-radar/src/python/signal_levels.py new file mode 100755 index 00000000..f21f7f8b --- /dev/null +++ b/gr-radar/src/python/signal_levels.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import sys +from math import pi, log10 +from gnuradio.eng_notation import num_to_str + +def power_density(transmitted_power, distance): + """ + Estimate power density in Watts/meter. + Assume isotropic radiator (spherical radiation pattern). + + @param transmitted_power: Watts + @param distance: distance from transmitter in meters + + """ + return transmitted_power / (4 * pi * distance * distance) + + +def ratio_of_target_return_to_direct(Rl, Rt, Rr, rcs): + """ + Estimate relative strength of signal levels for direct and reflected + path in bistatic radar. Assume all antenna factors are constant, + and hence 'wash out'. Also assume that the antennas are isotropic + radiators (spherical radiation pattern). + + @param Rl: distance between Tx and Rx in meters + @param Rt: distance between Tx and target in meters + @param Rr: distance between Rx and target in meters + @param rcs: radar cross section in meters^2 + + @returns: ratio of reflected to direct in decibels + """ + Tx_power = 1 + direct_path_power_density = power_density(Tx_power, Rl) + power_at_target = power_density(Tx_power, Rt) * rcs + reflected_path_power_density = power_density(power_at_target, Rr) + return 10*log10(reflected_path_power_density / direct_path_power_density) + + +def print_header(f): + f.write(" Rl Rt Rr rcs dB\n") + f.write("-----------------------------------------\n") + +def print_result(f, Rl, Rt, Rr, rcs, dB): + f.write("%6sm %6sm %6sm %6s %6s\n" % tuple([num_to_str(x) for x in [Rl, Rt, Rr, rcs, dB]])) + +def calc_print(f, Rl, Rt, Rr, rcs): + print_result(f, Rl, Rt, Rr, rcs, ratio_of_target_return_to_direct(Rl, Rt, Rr, rcs)) + +def main(): + f = sys.stdout + print_header(f) + calc_print(f, 40e3, 100e3, 100e3, 10.0) + calc_print(f, 40e3, 80e3, 80e3, 10.0) + calc_print(f, 40e3, 40e3, 40e3, 10.0) + calc_print(f, 40e3, 40e3, 8e3, 10.0) + calc_print(f, 40e3, 60e3, 20e3, 10.0) + calc_print(f, 40e3, 20e3, 60e3, 10.0) + + +if __name__ == '__main__': + main() diff --git a/gr-radar/src/python/split_files.py b/gr-radar/src/python/split_files.py new file mode 100755 index 00000000..a604c077 --- /dev/null +++ b/gr-radar/src/python/split_files.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os.path +import re + +plot = None + +def split_filename(src_filename): + s = os.path.splitext(src_filename)[0] # drop extension + date, time, freq, dec, nchan = s.split('-') + return (date, time, freq, int(dec), int(nchan)) + + +def make_filename(date, time, freq, n, short_output): + if short_output: + return '-'.join((date, time, freq)) + '.s%02d' % (n,) + else: + return '-'.join((date, time, freq)) + '.c%02d' % (n,) + +class my_graph(gr.flow_graph): + + def __init__(self, src_filename, short_output): + """ + Deinterleave file, filter and decimate by 4, and write out + a separate file for each input channel. + + The input file is the raw output of nchannels of short USRP data. + That is, they are interleaved short I&Q for each channel. + """ + global plot + + gr.flow_graph.__init__(self) + + decim = 4 + + (date, time, freq, dec, nchan) = split_filename(src_filename) + + src = gr.file_source(gr.sizeof_short, src_filename) + + # convert stream of interleaved shorts to a stream of complex + s2c = gr.interleaved_short_to_complex() + + # deinterleave complexes into separate streams + deint = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(src, s2c, deint) + + taps = optfir.low_pass(1, # gain + 1, # sampling rate + 0.100, # passband cutoff + 0.125, # stopband cutoff + 0.01, # passband ripple (dB) + 70) # stopband atten (dB) + + print "len(taps) =", len(taps) + + #plot = gru.gnuplot_freqz(gru.freqz(taps, 1), 1) + #raw_input('Press Enter to continue: ') + + for n in xrange(nchan): + #df = gr.fft_filter_ccc(decim, taps) + df = gr.fir_filter_ccf(decim, taps) + self.connect((deint, n), df) + dst_filename = make_filename(date, time, freq, n, short_output) + if short_output: + c2s = gr.complex_to_interleaved_short() + dst = gr.file_sink(gr.sizeof_short, dst_filename) + self.connect(df, c2s, dst) + else: + dst = gr.file_sink(gr.sizeof_gr_complex, dst_filename) + self.connect(df, dst) + + +def split_1_file(filename, short_output): + my_graph(filename, short_output).run() + + +def main(): + usage="%prog: [options] file_to_split..." + parser = OptionParser (option_class=eng_option, usage=usage) + parser.add_option("-s", "--short", action="store_true", default=False, + help="short output if set, else complex") + (options, args) = parser.parse_args() + + for filename in args: + split_1_file(filename, options.short) + + +if __name__ == '__main__': + main() diff --git a/gr-radar/src/python/usrp_rx_radar.py b/gr-radar/src/python/usrp_rx_radar.py new file mode 100755 index 00000000..e7c2da2c --- /dev/null +++ b/gr-radar/src/python/usrp_rx_radar.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import usrp_dbid +import time +import os.path + + +def make_filename(dir, freq, decim, nchan, suffix): + t = time.strftime('%Y%m%d-%H%M%S') + f = 'R%s-%s-%d-%d.%s' % ( + t, eng_notation.num_to_str(freq), decim, nchan, suffix) + return os.path.join(dir, f) + +class radar_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=64, + help="set fgpa decimation rate to DECIM (default=64)") + parser.add_option("-f", "--freq", type="eng_float", default=104.5e6, + help="set frequency to FREQ (default=104.5M)", metavar="FREQ") + parser.add_option("", "--gain0", type="eng_float", default=0, + help="set gain in dB (default 0)") + parser.add_option("", "--gain1", type="eng_float", default=11, + help="set gain in dB (default 11)") + parser.add_option("-F", "--filename", default=None) + parser.add_option("-D", "--dir", default=None) + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.filename is None and options.dir is None: + sys.stderr.write('Must specify either -F FILENAME or -D DIR\n') + parser.print_help() + sys.exit(1) + + nchan = 2 + + # if filename was given, use it, otherwise build one. + if options.filename is None: + options.filename = make_filename(options.dir, options.freq, + options.decim, nchan, 'srd') + + self.u = usrp.source_s(0, options.decim, nchan, 0, 0) + self.subdev = self.u.db[0] + + if self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX: + sys.stderr.write('This code requires a Basic Rx board on Side A\n') + sys.exit(1) + + # self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.subdev)) + self.u.set_mux(gru.hexint(0xf0f0f1f0)) + + dst = gr.file_sink (gr.sizeof_short, options.filename) + self.connect (self.u, dst) + + self.subdev[0].set_gain(options.gain0) + self.subdev[1].set_gain(options.gain1) + self.set_freq(options.freq) + + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + +if __name__ == '__main__': + fg = radar_graph() + try: + fg.run() + except KeyboardInterrupt: + pass diff --git a/gr-radio-astronomy/AUTHORS b/gr-radio-astronomy/AUTHORS new file mode 100644 index 00000000..b3ab4148 --- /dev/null +++ b/gr-radio-astronomy/AUTHORS @@ -0,0 +1,2 @@ +Marcus Leech +Eric Blossom diff --git a/gr-radio-astronomy/ChangeLog b/gr-radio-astronomy/ChangeLog new file mode 100644 index 00000000..4cc5ffa9 --- /dev/null +++ b/gr-radio-astronomy/ChangeLog @@ -0,0 +1,30 @@ +2006-06-29 Eric Blossom + + * src/python/Makefile.am: modfied to install part under gnuradio + and part under gnuradio/wxgui. + +2006-05-28 Eric Blossom + + * src/python/Makefile.am (bin_SCRIPTS): changed bin_PYTHON to + bin_SCRIPTS. + +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-radio-astronomy/Makefile.am b/gr-radio-astronomy/Makefile.am new file mode 100644 index 00000000..ed5e7524 --- /dev/null +++ b/gr-radio-astronomy/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src diff --git a/gr-radio-astronomy/README b/gr-radio-astronomy/README new file mode 100644 index 00000000..5abbac41 --- /dev/null +++ b/gr-radio-astronomy/README @@ -0,0 +1,38 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This tarball contains a build tree with examples, Makefiles, etc +for radio astronomy related applications. + +To build the examples from the tarball use the normal recipe: + + $ ./configure + $ make + $ make check + +If you're building from CVS, you'll need to use this sequence, since +CVS doesn't contain configure or the generated Makefiles. + + $ ./bootstrap + $ ./configure + $ make + $ make check + diff --git a/gr-radio-astronomy/src/Makefile.am b/gr-radio-astronomy/src/Makefile.am new file mode 100644 index 00000000..122fc72c --- /dev/null +++ b/gr-radio-astronomy/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib python diff --git a/gr-radio-astronomy/src/lib/Makefile.am b/gr-radio-astronomy/src/lib/Makefile.am new file mode 100644 index 00000000..b1d01738 --- /dev/null +++ b/gr-radio-astronomy/src/lib/Makefile.am @@ -0,0 +1,90 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.ra module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(STD_DEFINES_AND_INCLUDES) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + + +LOCAL_IFILES = \ + ra.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _howto shared library +# and knows how to call our extensions. + +BUILT_SOURCES = \ + ra.cc \ + ra.py + +# This gets ra.py installed in the right place +ourpython_PYTHON = \ + ra.py + +ourlib_LTLIBRARIES = _ra.la + +# These are the source files that go into the shared library +_ra_la_SOURCES = \ + ra.cc + +# magic flags +_ra_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library +_ra_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + $(GNURADIO_CORE_LIBS) \ + -lstdc++ + +ra.cc ra.py: ra.i $(ALL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module ra -o ra.cc $< + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = + +# These swig headers get installed in ${prefix}/include/gnuradio/swig +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done diff --git a/gr-radio-astronomy/src/lib/ra.i b/gr-radio-astronomy/src/lib/ra.i new file mode 100644 index 00000000..15cfbfb3 --- /dev/null +++ b/gr-radio-astronomy/src/lib/ra.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ + +%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 +%} + +// We'll need something like this if we add C++ blocks... +// See the gr-howto-write-a-block tarball for examples + +// ---------------------------------------------------------------- + +/* + * 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 ra_square_ff from python as ra.square_ff + */ +// GR_SWIG_BLOCK_MAGIC(ra,square_ff); + +// ra_square_ff_sptr ra_make_square_ff (); +// +// class ra_square_ff : public gr_block +// { +// private: +// ra_square_ff (); +// }; +// +// // ---------------------------------------------------------------- +// +// GR_SWIG_BLOCK_MAGIC(ra,square2_ff); +// +// ra_square2_ff_sptr ra_make_square2_ff (); +// +// class ra_square2_ff : public gr_sync_block +// { +// private: +// ra_square2_ff (); +// }; diff --git a/gr-radio-astronomy/src/python/Makefile.am b/gr-radio-astronomy/src/python/Makefile.am new file mode 100644 index 00000000..62706fce --- /dev/null +++ b/gr-radio-astronomy/src/python/Makefile.am @@ -0,0 +1,56 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.ra module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +# wxgui stuff here +wxguipythondir = $(grpythondir)/wxgui +wxguilibdir = $(grpyexecdir)/wxgui + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +noinst_PYTHON = \ + qa_ra.py + +ourpython_PYTHON = \ + local_calibrator.py + +wxguipython_PYTHON = \ + ra_stripchartsink.py \ + ra_fftsink.py + + +# and here for applications you want installed in prefix/bin +bin_SCRIPTS = \ + usrp_ra_receiver.py \ + usrp_psr_receiver.py diff --git a/gr-radio-astronomy/src/python/local_calibrator.py b/gr-radio-astronomy/src/python/local_calibrator.py new file mode 100755 index 00000000..6c5fb4f1 --- /dev/null +++ b/gr-radio-astronomy/src/python/local_calibrator.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import Numeric +import math +import ephem +import time + +# +# Simple class for allowing local definition of a calibration function +# for raw samples coming from the RA detector chain. Each observatory +# is different, and rather than hacking up the main code in usrp_ra_receiver +# we define the appropriate function here. +# +# For example, one could calibrate the output in Janskys, rather than +# dB. +# +# + +def calib_default_total_power(data): + r = 10.0*math.log10(data) + return(r) + +def calib_numogate_ridge_observatory_total_power(data): + + me = ephem.Observer() + + # + # PyEphem wants lat/long as strings, rather than floats--took me quite + # a long time to figure that out. If they don't arrive as strings, + # the calculations for sidereal time are complete garbage + # + me.long = str(-76.043) + me.lat = str(44.967) + + me.date = ephem.now() + sidtime = me.sidereal_time() + + foo = time.localtime() + if not "calib_prefix" in globals(): + pfx = "./" + else: + pfx = globals()["calib_prefix"] + filenamestr = "%s/%04d%02d%02d%02d" % (pfx, foo.tm_year, + foo.tm_mon, foo.tm_mday, foo.tm_hour) + + rainbow_file = open (filenamestr+".tpdat","a") + + r = (math.sqrt(data) / 2048) * 1000.0 + #r = calib_default_total_power(data) + inter = globals()["calib_decln"] + rainbow_file.write(str(ephem.hours(sidtime))+" "+str(r)+" "+str(inter)+"\n") + rainbow_file.close() + return(r) + +def calib_numogate_ridge_observatory_fft(data,l): + + me = ephem.Observer() + + # + # PyEphem wants lat/long as strings, rather than floats--took me quite + # a long time to figure that out. If they don't arrive as strings, + # the calculations for sidereal time are complete garbage + # + me.long = str(-76.043) + me.lat = str(44.967) + + me.date = ephem.now() + sidtime = me.sidereal_time() + + foo = time.localtime() + + if not "calib_prefix" in globals(): + pfx = "./" + else: + pfx = globals()["calib_prefix"] + filenamestr = "%s/%04d%02d%02d%02d" % (pfx, foo.tm_year, + foo.tm_mon, foo.tm_mday, foo.tm_hour) + + now = time.time() + + if not "calib_then" in globals(): + globals()["calib_then"] = now + + delta = 5 + + if (now - globals()["calib_then"]) >= delta: + + globals()["calib_then"] = now + rainbow_file = open (filenamestr+".sdat","a") + + r = calib_default_fft(data,l) + inter = globals()["calib_decln"] + rainbow_file.write("data:"+str(ephem.hours(sidtime))+" "+str(inter)+" "+str(r)+"\n") + rainbow_file.close() + return(r) + + return(data) + +def calib_default_fft(db,l): + return(db) + +# +# We capture various parameters from the receive chain here, because +# they can affect the calibration equations. +# +# +def calib_set_gain(gain): + globals()["calib_gain_setting"] = gain + +def calib_set_integ(integ): + globals()["calib_integ_setting"] = integ + +def calib_set_bw(bw): + globals()["calib_bw_setting"] = bw + +def calib_set_freq(freq): + globals()["calib_freq_setting"] = freq + +def calib_set_avg_alpha(alpha): + globals()["calib_avg_alpha"] = alpha + +def calib_set_interesting(inter): + globals()["calib_is_interesting"] = inter + +def calib_set_decln(dec): + globals()["calib_decln"] = dec + +def calib_set_prefix(pfx): + globals()["calib_prefix"] = pfx diff --git a/gr-radio-astronomy/src/python/qa_ra.py b/gr-radio-astronomy/src/python/qa_ra.py new file mode 100755 index 00000000..4b24a1eb --- /dev/null +++ b/gr-radio-astronomy/src/python/qa_ra.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import ra + +class qa_ra (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_(self): # ensure that we can load the module + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-radio-astronomy/src/python/ra_fftsink.py b/gr-radio-astronomy/src/python/ra_fftsink.py new file mode 100755 index 00000000..213f4a72 --- /dev/null +++ b/gr-radio-astronomy/src/python/ra_fftsink.py @@ -0,0 +1,520 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, window +from gnuradio.wxgui import stdgui +import wx +import gnuradio.wxgui.plot as plot +import Numeric +import threading +import math +import random + +default_ra_fftsink_size = (640,140) + + +def default_cfunc(db,l): + return(db) + + +class ra_fft_sink_base(object): + def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, sc_y_per_div=0.5, ref_level=50, sc_ref_level=20, + sample_rate=1, fft_size=512, fft_rate=15, + average=False, avg_alpha=None, title='', peak_hold=False, cfunc=default_cfunc, xydfunc=None, interfunc=None): + + # initialize common attributes + self.baseband_freq = baseband_freq + self.y_divs = 8 + self.y_per_div=y_per_div + self.sc_y_per_div=sc_y_per_div + self.ref_level = ref_level + self.autoscale = False + self.sc_ref_level = sc_ref_level + self.sample_rate = sample_rate + self.fft_size = fft_size + self.fft_rate = fft_rate + self.binwidth = float(sample_rate/fft_size) + self.average = average + self.cfunc = cfunc + self.xydfunc = xydfunc + self.interfunc = interfunc + if avg_alpha is None: + self.avg_alpha = 2.0 / fft_rate + else: + self.avg_alpha = avg_alpha + self.title = title + self.peak_hold = peak_hold + self.input_is_real = input_is_real + self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages + + def set_y_per_div(self, y_per_div): + self.y_per_div = y_per_div + + + def set_ref_level(self, ref_level): + self.ref_level = ref_level + + def set_average(self, average): + self.average = average + if average: + self.avg.set_taps(self.avg_alpha) + self.set_peak_hold(False) + else: + self.avg.set_taps(1.0) + + def set_peak_hold(self, enable): + self.peak_hold = enable + if enable: + self.set_average(False) + self.win.set_peak_hold(enable) + + def set_autoscale(self, auto): + self.autoscale = auto + + def set_avg_alpha(self, avg_alpha): + self.avg_alpha = avg_alpha + + def set_baseband_freq(self, baseband_freq): + self.baseband_freq = baseband_freq + + +class ra_fft_sink_f(gr.hier_block, ra_fft_sink_base): + def __init__(self, fg, parent, baseband_freq=0, + y_per_div=10, sc_y_per_div=0.5, sc_ref_level=40, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=15, average=False, avg_alpha=None, title='', + size=default_ra_fftsink_size, peak_hold=False, cfunc=default_cfunc, xydfunc=None, interfunc=None): + + ra_fft_sink_base.__init__(self, input_is_real=True, baseband_freq=baseband_freq, + y_per_div=y_per_div, sc_y_per_div=sc_y_per_div, + sc_ref_level=sc_ref_level, ref_level=ref_level, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title, + peak_hold=peak_hold, cfunc=cfunc, + xydfunc=xydfunc, interfunc=interfunc) + + self.binwidth = float(sample_rate/2.0)/float(fft_size) + s2p = gr.serial_to_parallel(gr.sizeof_float, fft_size) + one_in_n = gr.keep_one_in_n(gr.sizeof_float * fft_size, + max(1, int(sample_rate/fft_size/fft_rate))) + mywindow = window.blackmanharris(fft_size) + fft = gr.fft_vfc(fft_size, True, mywindow) + c2mag = gr.complex_to_mag(fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, fft_size) + log = gr.nlog10_ff(20, fft_size, -20*math.log10(fft_size)) + sink = gr.message_sink(gr.sizeof_float * fft_size, self.msgq, True) + + fg.connect (s2p, one_in_n, fft, c2mag, self.avg, log, sink) + gr.hier_block.__init__(self, fg, s2p, sink) + + self.win = fft_window(self, parent, size=size) + self.set_average(self.average) + +class ra_fft_sink_c(gr.hier_block, ra_fft_sink_base): + def __init__(self, fg, parent, baseband_freq=0, + y_per_div=10, sc_y_per_div=0.5, sc_ref_level=40, + ref_level=50, sample_rate=1, fft_size=512, + fft_rate=15, average=False, avg_alpha=None, title='', + size=default_ra_fftsink_size, peak_hold=False, cfunc=default_cfunc, xydfunc=None, interfunc=None): + + ra_fft_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq, + y_per_div=y_per_div, sc_y_per_div=sc_y_per_div, + sc_ref_level=sc_ref_level, ref_level=ref_level, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, + title=title, + peak_hold=peak_hold, cfunc=cfunc, + xydfunc=xydfunc, interfunc=interfunc) + + s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, fft_size) + one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * fft_size, + max(1, int(sample_rate/fft_size/fft_rate))) + mywindow = window.blackmanharris(fft_size) + fft = gr.fft_vcc(fft_size, True, mywindow) + c2mag = gr.complex_to_mag(fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, fft_size) + log = gr.nlog10_ff(20, fft_size, -20*math.log10(fft_size)) + sink = gr.message_sink(gr.sizeof_float * fft_size, self.msgq, True) + + fg.connect(s2p, one_in_n, fft, c2mag, self.avg, log, sink) + gr.hier_block.__init__(self, fg, s2p, sink) + + self.win = fft_window(self, parent, size=size) + self.set_average(self.average) + + +# ------------------------------------------------------------------------ + +myDATA_EVENT = wx.NewEventType() +EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0) + + +class DataEvent(wx.PyEvent): + def __init__(self, data): + wx.PyEvent.__init__(self) + self.SetEventType (myDATA_EVENT) + self.data = data + + def Clone (self): + self.__class__ (self.GetId()) + + +class input_watcher (threading.Thread): + def __init__ (self, msgq, fft_size, event_receiver, **kwds): + threading.Thread.__init__ (self, **kwds) + self.setDaemon (1) + self.msgq = msgq + self.fft_size = fft_size + self.event_receiver = event_receiver + self.keep_running = True + self.start () + + def run (self): + while (self.keep_running): + msg = self.msgq.delete_head() # blocking read of message queue + itemsize = int(msg.arg1()) + nitems = int(msg.arg2()) + + s = msg.to_string() # get the body of the msg as a string + + # There may be more than one FFT frame in the message. + # If so, we take only the last one + if nitems > 1: + start = itemsize * (nitems - 1) + s = s[start:start+itemsize] + + complex_data = Numeric.fromstring (s, Numeric.Float32) + de = DataEvent (complex_data) + wx.PostEvent (self.event_receiver, de) + del de + + +class fft_window (plot.PlotCanvas): + def __init__ (self, ra_fftsink, parent, id = -1, + pos = wx.DefaultPosition, size = wx.DefaultSize, + style = wx.DEFAULT_FRAME_STYLE, name = ""): + plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name) + + self.y_range = None + self.ra_fftsink = ra_fftsink + self.peak_hold = False + self.peak_vals = None + + self.SetEnableGrid (True) + # self.SetEnableZoom (True) + # self.SetBackgroundColour ('black') + + self.build_popup_menu() + + EVT_DATA_EVENT (self, self.set_data) + wx.EVT_CLOSE (self, self.on_close_window) + self.Bind(wx.EVT_RIGHT_UP, self.on_right_click) + self.Bind(wx.EVT_MOTION, self.on_motion) + self.Bind(wx.EVT_LEFT_UP, self.on_left_click) + + self.input_watcher = input_watcher(ra_fftsink.msgq, ra_fftsink.fft_size, self) + + + def on_close_window (self, event): + print "fft_window:on_close_window" + self.keep_running = False + + + def set_data (self, evt): + calc_min = 99e10 + calc_max = -99e10 + dB = evt.data + L = len (dB) + + calc_min = min(dB) + calc_max = max(dB) + + dB = self.ra_fftsink.cfunc(dB, L) + + if self.peak_hold: + if self.peak_vals is None: + self.peak_vals = dB + else: + self.peak_vals = Numeric.maximum(dB, self.peak_vals) + dB = self.peak_vals + + x = max(abs(self.ra_fftsink.sample_rate), abs(self.ra_fftsink.baseband_freq)) + if x >= 1e9: + sf = 1e-9 + units = "GHz" + elif x >= 1e6: + sf = 1e-6 + units = "MHz" + elif x >= 1e3: + sf = 1e-3 + units = "kHz" + else: + sf = 1.0 + units = "Hz" + + if self.ra_fftsink.input_is_real: # only plot 1/2 the points + x_vals = ((Numeric.arrayrange (L/2) + * (self.ra_fftsink.sample_rate * sf / L)) + + self.ra_fftsink.baseband_freq * sf) + points = Numeric.zeros((len(x_vals), 2), Numeric.Float64) + points[:,0] = x_vals + points[:,1] = dB[0:L/2] + else: + # the "negative freqs" are in the second half of the array + x_vals = ((Numeric.arrayrange (-L/2, L/2) + * (self.ra_fftsink.sample_rate * sf / L)) + + self.ra_fftsink.baseband_freq * sf) + points = Numeric.zeros((len(x_vals), 2), Numeric.Float64) + points[:,0] = x_vals + points[:,1] = Numeric.concatenate ((dB[L/2:], dB[0:L/2])) + + lines = plot.PolyLine (points, colour='BLUE') + graphics = plot.PlotGraphics ([lines], + title=self.ra_fftsink.title, + xLabel = units, yLabel = "dB") + + self.Draw (graphics, xAxis=None, yAxis=self.y_range) + d = calc_max - calc_min + d *= 0.1 + if self.ra_fftsink.autoscale == True: + self.y_range = self._axisInterval ('min', calc_min-d, calc_max+d) + else: + self.update_y_range () + + def set_peak_hold(self, enable): + self.peak_hold = enable + self.peak_vals = None + + def update_y_range (self): + ymax = self.ra_fftsink.ref_level + ymin = self.ra_fftsink.ref_level - self.ra_fftsink.y_per_div * self.ra_fftsink.y_divs + self.y_range = self._axisInterval ('min', ymin, ymax) + + def on_average(self, evt): + # print "on_average" + self.ra_fftsink.set_average(evt.IsChecked()) + + def on_peak_hold(self, evt): + # print "on_peak_hold" + self.ra_fftsink.set_peak_hold(evt.IsChecked()) + + def on_autoscale(self, evt): + self.ra_fftsink.set_autoscale(evt.IsChecked()) + + def on_incr_ref_level(self, evt): + # print "on_incr_ref_level" + self.ra_fftsink.set_ref_level(self.ra_fftsink.ref_level + + self.ra_fftsink.y_per_div) + + def on_decr_ref_level(self, evt): + # print "on_decr_ref_level" + self.ra_fftsink.set_ref_level(self.ra_fftsink.ref_level + - self.ra_fftsink.y_per_div) + + def on_incr_y_per_div(self, evt): + # print "on_incr_y_per_div" + self.ra_fftsink.set_y_per_div(next_up(self.ra_fftsink.y_per_div, (0.5,1,2,5,10))) + + def on_decr_y_per_div(self, evt): + # print "on_decr_y_per_div" + self.ra_fftsink.set_y_per_div(next_down(self.ra_fftsink.y_per_div, (0.5,1,2,5,10))) + + def on_y_per_div(self, evt): + # print "on_y_per_div" + Id = evt.GetId() + if Id == self.id_y_per_div_1: + self.ra_fftsink.set_y_per_div(0.5) + elif Id == self.id_y_per_div_2: + self.ra_fftsink.set_y_per_div(1.0) + elif Id == self.id_y_per_div_5: + self.ra_fftsink.set_y_per_div(2.0) + elif Id == self.id_y_per_div_10: + self.ra_fftsink.set_y_per_div(5.0) + elif Id == self.id_y_per_div_20: + self.ra_fftsink.set_y_per_div(10) + + + def on_right_click(self, event): + menu = self.popup_menu + for id, pred in self.checkmarks.items(): + item = menu.FindItemById(id) + item.Check(pred()) + self.PopupMenu(menu, event.GetPosition()) + + def on_motion(self, event): + if not self.ra_fftsink.xydfunc == None: + xy = self.GetXY(event) + self.ra_fftsink.xydfunc (xy) + + def on_left_click(self, event): + if not self.ra_fftsink.interfunc == None: + xy = self.GetXY(event) + self.ra_fftsink.interfunc (xy[0]) + + def build_popup_menu(self): + self.id_incr_ref_level = wx.NewId() + self.id_decr_ref_level = wx.NewId() + self.id_autoscale = wx.NewId() + self.id_incr_y_per_div = wx.NewId() + self.id_decr_y_per_div = wx.NewId() + self.id_y_per_div_1 = wx.NewId() + self.id_y_per_div_2 = wx.NewId() + self.id_y_per_div_5 = wx.NewId() + self.id_y_per_div_10 = wx.NewId() + self.id_y_per_div_20 = wx.NewId() + self.id_average = wx.NewId() + self.id_peak_hold = wx.NewId() + + self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) + self.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) + self.Bind(wx.EVT_MENU, self.on_autoscale, id=self.id_autoscale) + self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) + self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) + self.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) + self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) + + + # make a menu + menu = wx.Menu() + self.popup_menu = menu + menu.AppendCheckItem(self.id_average, "Average") + menu.AppendCheckItem(self.id_peak_hold, "Peak Hold") + menu.Append(self.id_incr_ref_level, "Incr Ref Level") + menu.Append(self.id_decr_ref_level, "Decr Ref Level") + # menu.Append(self.id_incr_y_per_div, "Incr dB/div") + # menu.Append(self.id_decr_y_per_div, "Decr dB/div") + menu.AppendSeparator() + # we'd use RadioItems for these, but they're not supported on Mac + menu.AppendCheckItem(self.id_autoscale, "Autoscale") + menu.AppendCheckItem(self.id_y_per_div_1, "0.5 dB/div") + menu.AppendCheckItem(self.id_y_per_div_2, "1.0 dB/div") + menu.AppendCheckItem(self.id_y_per_div_5, "2.0 dB/div") + menu.AppendCheckItem(self.id_y_per_div_10, "5.0 dB/div") + menu.AppendCheckItem(self.id_y_per_div_20, "10.0 dB/div") + + self.checkmarks = { + self.id_average : lambda : self.ra_fftsink.average, + self.id_peak_hold : lambda : self.ra_fftsink.peak_hold, + self.id_autoscale : lambda : self.ra_fftsink.autoscale, + self.id_y_per_div_1 : lambda : self.ra_fftsink.y_per_div == 0.5, + self.id_y_per_div_2 : lambda : self.ra_fftsink.y_per_div == 1.0, + self.id_y_per_div_5 : lambda : self.ra_fftsink.y_per_div == 2.0, + self.id_y_per_div_10 : lambda : self.ra_fftsink.y_per_div == 5.0, + self.id_y_per_div_20 : lambda : self.ra_fftsink.y_per_div == 10.0, + } + + +def next_up(v, seq): + """ + Return the first item in seq that is > v. + """ + for s in seq: + if s > v: + return s + return v + +def next_down(v, seq): + """ + Return the last item in seq that is < v. + """ + rseq = list(seq[:]) + rseq.reverse() + + for s in rseq: + if s < v: + return s + return v + + +# ---------------------------------------------------------------- +# Deprecated interfaces +# ---------------------------------------------------------------- + +# returns (block, win). +# block requires a single input stream of float +# win is a subclass of wxWindow + +def make_ra_fft_sink_f(fg, parent, title, fft_size, input_rate, ymin = 0, ymax=50): + + block = ra_fft_sink_f(fg, parent, title=title, fft_size=fft_size, sample_rate=input_rate, + y_per_div=(ymax - ymin)/8, ref_level=ymax) + return (block, block.win) + +# returns (block, win). +# block requires a single input stream of gr_complex +# win is a subclass of wxWindow + +def make_ra_fft_sink_c(fg, parent, title, fft_size, input_rate, ymin=0, ymax=50): + block = ra_fft_sink_c(fg, parent, title=title, fft_size=fft_size, sample_rate=input_rate, + y_per_div=(ymax - ymin)/8, ref_level=ymax) + return (block, block.win) + + +# ---------------------------------------------------------------- +# Standalone test app +# ---------------------------------------------------------------- + +class test_app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + fft_size = 256 + + # build our flow graph + input_rate = 20.000e3 + + # Generate a complex sinusoid + src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 5.75e3, 1000) + #src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1000) + + # We add these throttle blocks so that this demo doesn't + # suck down all the CPU available. Normally you wouldn't use these. + thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate) + + sink1 = ra_fft_sink_c (self, panel, title="Complex Data", fft_size=fft_size, + sample_rate=input_rate, baseband_freq=100e3, + ref_level=60, y_per_div=10) + vbox.Add (sink1.win, 1, wx.EXPAND) + self.connect (src1, thr1, sink1) + + src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 5.75e3, 1000) + #src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1000) + thr2 = gr.throttle(gr.sizeof_float, input_rate) + sink2 = ra_fft_sink_f (self, panel, title="Real Data", fft_size=fft_size*2, + sample_rate=input_rate, baseband_freq=100e3, + ref_level=60, y_per_div=10) + vbox.Add (sink2.win, 1, wx.EXPAND) + self.connect (src2, thr2, sink2) + +def main (): + app = stdgui.stdapp (test_app_flow_graph, + "FFT Sink Test App") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gr-radio-astronomy/src/python/ra_stripchartsink.py b/gr-radio-astronomy/src/python/ra_stripchartsink.py new file mode 100755 index 00000000..112a0d69 --- /dev/null +++ b/gr-radio-astronomy/src/python/ra_stripchartsink.py @@ -0,0 +1,399 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio.wxgui import stdgui +import wx +import gnuradio.wxgui.plot as plot +import Numeric +import threading +import math +import ephem +import time + +default_stripchartsink_size = (640,140) +global_yvalues = [] + +def default_cfunc(datum): + return(datum) + +class stripchart_sink_base(object): + def __init__(self, input_is_real=False, y_per_div=10, ref_level=50, + sample_rate=1, stripsize=4, + title='',xlabel="X", ylabel="Y", divbase=0.025, + cfunc=default_cfunc, parallel=False, scaling=1.0, autoscale=False): + + # initialize common attributes + self.y_divs = 8 + self.y_per_div=y_per_div + self.ref_level = ref_level + self.autoscale = autoscale + self.sample_rate = sample_rate + self.parallel = parallel + self.title = title + self.xlabel = xlabel + self.ylabel = ylabel + self.divbase = divbase + self.scaling = scaling + self.cfunc = cfunc + self.input_is_real = input_is_real + self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages + self.vector=Numeric.zeros(stripsize,Numeric.Float64) + self.wcnt = 0 + self.timecnt = 0 + self.stripsize=stripsize + + def set_y_per_div(self, y_per_div): + self.y_per_div = y_per_div + + def set_ref_level(self, ref_level): + self.ref_level = ref_level + + def set_autoscale(self, auto): + self.autoscale = auto + +class stripchart_sink_f(gr.hier_block, stripchart_sink_base): + def __init__(self, fg, parent, + y_per_div=10, ref_level=50, sample_rate=1, + title='', stripsize=4, + size=default_stripchartsink_size,xlabel="X", + ylabel="Y", divbase=0.025, cfunc=default_cfunc, + parallel=False, scaling=1.0, autoscale=False): + + stripchart_sink_base.__init__(self, input_is_real=True, + y_per_div=y_per_div, ref_level=ref_level, + sample_rate=sample_rate, + stripsize=stripsize, + xlabel=xlabel, ylabel=ylabel, + divbase=divbase, title=title, + cfunc=cfunc, parallel=parallel, + scaling=scaling, autoscale=autoscale) + + if (parallel == True): + one = gr.keep_one_in_n (gr.sizeof_float*stripsize, 1) + sink = gr.message_sink(gr.sizeof_float*stripsize, self.msgq, True) + else: + one = gr.keep_one_in_n (gr.sizeof_float, 1) + sink = gr.message_sink(gr.sizeof_float, self.msgq, True) + fg.connect (one, sink) + + gr.hier_block.__init__(self, fg, one, sink) + + self.win = stripchart_window(self, parent, size=size) + + + +# ------------------------------------------------------------------------ + +myDATA_EVENT = wx.NewEventType() +EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0) + + +class DataEvent(wx.PyEvent): + def __init__(self, data): + wx.PyEvent.__init__(self) + self.SetEventType (myDATA_EVENT) + self.data = data + + def Clone (self): + self.__class__ (self.GetId()) + + +class input_watcher (threading.Thread): + def __init__ (self, msgq, evsize, event_receiver, **kwds): + threading.Thread.__init__ (self, **kwds) + self.setDaemon (1) + self.msgq = msgq + self.evsize = evsize + self.event_receiver = event_receiver + self.keep_running = True + self.start () + + def run (self): + while (self.keep_running): + msg = self.msgq.delete_head() # blocking read of message queue + itemsize = int(msg.arg1()) + nitems = int(msg.arg2()) + + s = msg.to_string() # get the body of the msg as a string + + # There may be more than one frame in the message. + # If so, we take only the last one + if nitems > 1: + start = itemsize * (nitems - 1) + s = s[start:start+itemsize] + + complex_data = Numeric.fromstring (s, Numeric.Float32) + de = DataEvent (complex_data) + wx.PostEvent (self.event_receiver, de) + del de + +class stripchart_window(plot.PlotCanvas): + def __init__ (self, stripchartsink, parent, id = -1, + pos = wx.DefaultPosition, size = wx.DefaultSize, + style = wx.DEFAULT_FRAME_STYLE, name = ""): + plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name) + + self.y_range = None + self.stripchartsink = stripchartsink + + self.SetEnableGrid (True) + # self.SetEnableZoom (True) + # self.SetBackgroundColour ('black') + + self.build_popup_menu() + + EVT_DATA_EVENT (self, self.set_data) + + wx.EVT_CLOSE (self, self.on_close_window) + self.Bind(wx.EVT_RIGHT_UP, self.on_right_click) + + self.input_watcher = input_watcher(stripchartsink.msgq, 1, self) + + + def on_close_window (self, event): + print "stripchart_window:on_close_window" + self.keep_running = False + + + def set_data (self, evt): + indata = evt.data + L = len (indata) + + calc_min = min(indata) + calc_max = max(indata) + d = calc_max - calc_min + d *= 0.1 + if self.stripchartsink.autoscale == True and self.stripchartsink.parallel == True: + self.y_range = self._axisInterval ('min', calc_min-d, calc_max+d) + + if (self.stripchartsink.parallel != True): + indata = self.stripchartsink.cfunc(indata) + + N = self.stripchartsink.stripsize + if self.stripchartsink.parallel != True: + for i in range(1,N): + pooey = N-i + self.stripchartsink.vector[pooey] = self.stripchartsink.vector[pooey-1] + + self.stripchartsink.vector[0] = indata + + else: + self.stripchartsink.vector = indata + + if self.stripchartsink.parallel == True: + avg = 0 + for i in range(0,self.stripchartsink.stripsize): + if self.stripchartsink.vector[i] > 0: + avg += self.stripchartsink.vector[i] + if self.stripchartsink.vector[i] < calc_min: + calc_min = self.stripchartsink.vector[i] + if self.stripchartsink.vector[i] > calc_max: + calc_max = self.stripchartsink.vector[i] + + avg /= self.stripchartsink.stripsize + markers = [] + placedmarkers = 0 + for i in range(0,self.stripchartsink.stripsize): + if (self.stripchartsink.vector[i] > 0 and + self.stripchartsink.vector[i] > (avg*5)): + markers.append((i*self.stripchartsink.scaling, + self.stripchartsink.vector[i])) + placedmarkers += 1 + + points = Numeric.zeros((N,2), Numeric.Float64) + for i in range(0,N): + if self.stripchartsink.scaling == 1.0: + points[i,0] = i + else: + points[i,0] = i * self.stripchartsink.scaling + points[i,1] = self.stripchartsink.vector[i] + + if self.stripchartsink.parallel == True and placedmarkers > 1: + for i in range(0,N): + self.stripchartsink.vector[i] = 0 + + marks = plot.PolyMarker(markers, colour='BLACK', marker='triangle_down') + + lines = plot.PolyLine (points, colour='RED') + + # Temporary--I'm find the markers distracting + placedmarkers = 0 + xlab = self.stripchartsink.xlabel + ylab = self.stripchartsink.ylabel + if (self.stripchartsink.parallel == False) or (placedmarkers <= 1): + graphics = plot.PlotGraphics ([lines], + title=self.stripchartsink.title, + xLabel = xlab, yLabel = ylab) + + else: + graphics = plot.PlotGraphics ([lines,marks], + title=self.stripchartsink.title, + xLabel = xlab, yLabel = ylab) + + self.Draw (graphics, xAxis=None, yAxis=self.y_range) + + if self.stripchartsink.autoscale == False or self.stripchartsink.parallel == False: + self.update_y_range () + + + def update_y_range (self): + ymax = self.stripchartsink.ref_level + ymin = self.stripchartsink.ref_level - self.stripchartsink.y_per_div * self.stripchartsink.y_divs + self.y_range = self._axisInterval ('min', ymin, ymax) + + def on_incr_ref_level(self, evt): + # print "on_incr_ref_level" + self.stripchartsink.set_ref_level(self.stripchartsink.ref_level + + self.stripchartsink.y_per_div) + + def on_decr_ref_level(self, evt): + # print "on_decr_ref_level" + self.stripchartsink.set_ref_level(self.stripchartsink.ref_level + - self.stripchartsink.y_per_div) + + def on_autoscale(self, evt): + self.stripchartsink.set_autoscale(evt.IsChecked()) + + def on_incr_y_per_div(self, evt): + divbase = self.stripchartsink.divbase + x1 = 1 * divbase + x2 = 2 * divbase + x4 = 4 * divbase + x10 = 10 * divbase + x20 = 20 * divbase + # print "on_incr_y_per_div" + self.stripchartsink.set_y_per_div(next_up(self.stripchartsink.y_per_div, (x1,x2,x4,x10,x20))) + + def on_decr_y_per_div(self, evt): + # print "on_decr_y_per_div" + divbase = self.stripchartsink.divbase + x1 = 1 * divbase + x2 = 2 * divbase + x4 = 4 * divbase + x10 = 10 * divbase + x20 = 20 * divbase + self.stripchartsink.set_y_per_div(next_down(self.stripchartsink.y_per_div, (x1,x2,x4,x10,x20))) + + def on_y_per_div(self, evt): + # print "on_y_per_div" + divbase=self.stripchartsink.divbase + Id = evt.GetId() + if Id == self.id_y_per_div_1: + self.stripchartsink.set_y_per_div(1*divbase) + elif Id == self.id_y_per_div_2: + self.stripchartsink.set_y_per_div(2*divbase) + elif Id == self.id_y_per_div_5: + self.stripchartsink.set_y_per_div(4*divbase) + elif Id == self.id_y_per_div_10: + self.stripchartsink.set_y_per_div(10*divbase) + elif Id == self.id_y_per_div_20: + self.stripchartsink.set_y_per_div(20*divbase) + + + def on_right_click(self, event): + menu = self.popup_menu + for id, pred in self.checkmarks.items(): + item = menu.FindItemById(id) + item.Check(pred()) + self.PopupMenu(menu, event.GetPosition()) + + + def build_popup_menu(self): + divbase=self.stripchartsink.divbase + self.id_incr_ref_level = wx.NewId() + self.id_decr_ref_level = wx.NewId() + self.id_autoscale = wx.NewId() + self.id_incr_y_per_div = wx.NewId() + self.id_decr_y_per_div = wx.NewId() + self.id_y_per_div_1 = wx.NewId() + self.id_y_per_div_2 = wx.NewId() + self.id_y_per_div_5 = wx.NewId() + self.id_y_per_div_10 = wx.NewId() + self.id_y_per_div_20 = wx.NewId() + + self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) + self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) + self.Bind(wx.EVT_MENU, self.on_autoscale, id=self.id_autoscale) + self.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) + self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) + + + # make a menu + menu = wx.Menu() + self.popup_menu = menu + menu.Append(self.id_incr_ref_level, "Incr Ref Level") + menu.Append(self.id_decr_ref_level, "Decr Ref Level") + menu.AppendSeparator() + menu.AppendCheckItem(self.id_autoscale, "Auto Scale") + # we'd use RadioItems for these, but they're not supported on Mac + v = 1.0*divbase + s = "%.3f" % v + menu.AppendCheckItem(self.id_y_per_div_1, s) + v = 2.0*divbase + s = "%.3f" % v + menu.AppendCheckItem(self.id_y_per_div_2, s) + v = 4.0*divbase + s = "%.3f" % v + menu.AppendCheckItem(self.id_y_per_div_5, s) + v = 10*divbase + s = "%.3f" % v + menu.AppendCheckItem(self.id_y_per_div_10, s) + v = 20*divbase + s = "%.3f" % v + menu.AppendCheckItem(self.id_y_per_div_20, s) + + self.checkmarks = { + self.id_autoscale : lambda : self.stripchartsink.autoscale, + self.id_y_per_div_1 : lambda : self.stripchartsink.y_per_div == 1*divbase, + self.id_y_per_div_2 : lambda : self.stripchartsink.y_per_div == 2*divbase, + self.id_y_per_div_5 : lambda : self.stripchartsink.y_per_div == 4*divbase, + self.id_y_per_div_10 : lambda : self.stripchartsink.y_per_div == 10*divbase, + self.id_y_per_div_20 : lambda : self.stripchartsink.y_per_div == 20*divbase, + } + + +def next_up(v, seq): + """ + Return the first item in seq that is > v. + """ + for s in seq: + if s > v: + return s + return v + +def next_down(v, seq): + """ + Return the last item in seq that is < v. + """ + rseq = list(seq[:]) + rseq.reverse() + + for s in rseq: + if s < v: + return s + return v diff --git a/gr-radio-astronomy/src/python/run_tests.in b/gr-radio-astronomy/src/python/run_tests.in new file mode 100644 index 00000000..51568827 --- /dev/null +++ b/gr-radio-astronomy/src/python/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-radio-astronomy/src/lib +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-radio-astronomy/src/lib +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-radio-astronomy/src/python + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-radio-astronomy/src/python/usrp_psr_receiver.help b/gr-radio-astronomy/src/python/usrp_psr_receiver.help new file mode 100644 index 00000000..5801f3fb --- /dev/null +++ b/gr-radio-astronomy/src/python/usrp_psr_receiver.help @@ -0,0 +1,111 @@ +This program is used to analyse pulsars of known parameters. It contains + both a post-detector spectral display, and a "pulse profile" display. + It has a built-in de-dispersion filter that will work up to DM=100 for + 21cm observing, and up to DM=5 for 327Mhz observing. + +The program takes the following options: + + --rx-subdev-spec which USRP Rx side? A or B + + --decim USRP decimation rate use either 64 or 128 + + --freq USRP daughtercard frequency + + --observing Actual observing frequency (default is to use the + setting for --freq) + + --avg Averaging setting for spectral display--higher numbers + equal more averaging. 25 to 40 is typical. + + --favg Pulse folding averaging. 2 to 5 is typical. + + --gain USRP daughtercard gain control + + --reflevel Reference level on pulse profile display + + --lowest Lowest spectral bin that is considered valid, in Hz + + --longitude Observer longitude: West is negative + + --latitude Observer latitude: South is negative + + --fft_size Size of FFT for post-detector spectrum: default is 1024 + + --threshold Threshold (dB) to be considered a spectral "peak" + This is relative to the average spectral level + + --lowpass Low pass frequency for post-detector spectral display + 20-100 is typical + + --prefix Filename prefix to use for recording files + Default is ./ + + --pulsefreq The frequency of the expected pulses + For sentimental reasons, this defaults to 0.748Hz + + --dm The DM + + --doppler The doppler shift, as a ratio + + --divbase The base of the Y/Div menu in pulsar display + + --division The initial Y/Div in pulsar display + +DM, Doppler, Gain, Frequency, and the averaging parameters can all be + changed using the GUI at runtime. + +If latitude and longitude are set correctly, and the system time is + correct, then the current LMST is displayed below the frequency + input, updated once per second. + +Moving the mouse in the post-detector spectrum display shows you that + point in the post-detector spectrum, both frequency and signal level. + +The post-detector spectrum is analysed, with results shown below + "Best freq". It shows the spectral peaks, and computes their relationship. + It shows the harmonic compliance among the peaks, as well as the average + peak-to-peak distance. + + +Here's a complete example for observing a pulsar with a frequency of + 1.35Hz, at 431.5Mhz, using an IF of 10.7Mhz, and a DM of 12.431, using + 1Mhz observing bandwidth: + +./usrp_psr_receiver.py --freq 10.7e6 --decim 64 --dm 12.431 --avg 35 \ + --pulsefreq 1.35 --fft_size 2048 --lowest 1.00 --gain 75 --threshold 11.5 \ + --observing 431.5e6 --reflevel 200 --division 100 --divbase 10 --favg 3 \ + --lowpass 20 --longitude -76.02 --latitude 44.95 + +Since the observed pulsar is at 1.35Hz, a lowpass cutoff for the + post-detector spectral display of 20Hz will be adequate. We + tell the spectral analyser to use a threshold of 11.5dB above + average when analysing spectral data, and set the epoch folder + averager (pulse profile display) to use an average from 3 samples. + Notice that our actual USRP/Daughtercard frequency is 10.7Mhz, while + our observing frequency is 431.5Mhz--this is important in order for + the DM de-dispersion calculations to be correct. We also set our + latitude and longitude, so that logfiles and the LMST display + will have the correct LMST in them. + +The entire complex baseband can be recorded, if the "Recording baseband" + button is pressed. Filenames are generated dynamically, and a header + file is produced giving observation parameters. The baseband data are + recorded as octet pairs: one for I and one for Q. Pressing the button again + turns off baseband recording. This baseband is "raw", so it will + not have been de-dispersed. The data rate will be whatever the + USRP was programmed to at the time (based on --decim). + + The files are: YYYYMMDDHHMM.pdat and YYYYMMDDHHMM.phdr + + The .phdr file contains ASCII header information describing the + contents of the .pdat file. + +Similarly the raw, pre-folded, band-limited post-detector "audio" data can be + recorded using the "Record Pulses" button. The data rate for these is + currently 20Khz, recorded as short integers. Just like baseband recording, + pressing the button again turns off pulse recording. + + The files are: YYYYMMDDHHMM.padat and YYMMDDHHMM.pahdr + + The .pahdr file is ascii text providing information about the contents + of the corresponding .padat file. diff --git a/gr-radio-astronomy/src/python/usrp_psr_receiver.py b/gr-radio-astronomy/src/python/usrp_psr_receiver.py new file mode 100755 index 00000000..8a559370 --- /dev/null +++ b/gr-radio-astronomy/src/python/usrp_psr_receiver.py @@ -0,0 +1,1101 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# +# +# Pulsar receiver application +# +# Performs both harmonic folding analysis +# and epoch folding analysis +# +# +from gnuradio import gr, gru, blks, audio +from gnuradio import usrp, optfir +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, ra_fftsink, ra_stripchartsink, form, slider +from optparse import OptionParser +import wx +import sys +import Numeric +import FFT +import ephem +import time +import os +import math + + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-Q", "--observing", type="eng_float", default=0.0, + help="set observing frequency to FREQ") + parser.add_option("-a", "--avg", type="eng_float", default=1.0, + help="set spectral averaging alpha") + parser.add_option("-V", "--favg", type="eng_float", default=2.0, + help="set folder averaging alpha") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-l", "--reflevel", type="eng_float", default=30.0, + help="Set pulse display reference level") + parser.add_option("-L", "--lowest", type="eng_float", default=1.5, + help="Lowest valid frequency bin") + parser.add_option("-e", "--longitude", type="eng_float", default=-76.02, help="Set Observer Longitude") + parser.add_option("-c", "--latitude", type="eng_float", default=44.85, help="Set Observer Latitude") + parser.add_option("-F", "--fft_size", type="eng_float", default=1024, help="Size of FFT") + + parser.add_option ("-t", "--threshold", type="eng_float", default=2.5, help="pulsar threshold") + parser.add_option("-p", "--lowpass", type="eng_float", default=100, help="Pulse spectra cutoff freq") + parser.add_option("-P", "--prefix", default="./", help="File prefix") + parser.add_option("-u", "--pulsefreq", type="eng_float", default=0.748, help="Observation pulse rate") + parser.add_option("-D", "--dm", type="eng_float", default=1.0e-5, help="Dispersion Measure") + parser.add_option("-O", "--doppler", type="eng_float", default=1.0, help="Doppler ratio") + parser.add_option("-B", "--divbase", type="eng_float", default=20, help="Y/Div menu base") + parser.add_option("-I", "--division", type="eng_float", default=100, help="Y/Div") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + self.reflevel = options.reflevel + self.divbase = options.divbase + self.division = options.division + + # Low-pass cutoff for post-detector filter + # Set to 100Hz usually, since lots of pulsars fit in this + # range + self.lowpass = options.lowpass + + # What is lowest valid frequency bin in post-detector FFT? + # There's some pollution very close to DC + self.lowest_freq = options.lowest + + # What (dB) threshold to use in determining spectral candidates + self.threshold = options.threshold + + # Filename prefix for recording file + self.prefix = options.prefix + + # Dispersion Measure (DM) + self.dm = options.dm + + # Doppler shift, as a ratio + # 1.0 == no doppler shift + # 1.005 == a little negative shift + # 0.995 == a little positive shift + self.doppler = options.doppler + + # + # Input frequency and observing frequency--not necessarily the + # same thing, if we're looking at the IF of some downconverter + # that's ahead of the USRP and daughtercard. This distinction + # is important in computing the correct de-dispersion filter. + # + self.frequency = options.freq + if options.observing <= 0: + self.observing_freq = options.freq + else: + self.observing_freq = options.observing + + # build the graph + self.u = usrp.source_c(decim_rate=options.decim) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + + # + # Recording file, in case we ever need to record baseband data + # + self.recording = gr.file_sink(gr.sizeof_char, "/dev/null") + self.recording_state = False + + self.pulse_recording = gr.file_sink(gr.sizeof_short, "/dev/null") + self.pulse_recording_state = False + + # + # We come up with recording turned off, but the user may + # request recording later on + self.recording.close() + self.pulse_recording.close() + + # + # Need these two for converting 12-bit baseband signals to 8-bit + # + self.tofloat = gr.complex_to_float() + self.tochar = gr.float_to_char() + + # Need this for recording pulses (post-detector) + self.toshort = gr.float_to_short() + + + # + # The spectral measurer sets this when it has a valid + # average spectral peak-to-peak distance + # We can then use this to program the parameters for the epoch folder + # + # We set a sentimental value here + self.pulse_freq = options.pulsefreq + + # Folder runs at this raw sample rate + self.folder_input_rate = 20000 + + # Each pulse in the epoch folder is sampled at 128 times the nominal + # pulse rate + self.folding = 128 + + + # + # Try to find candidate parameters for rational resampler + # + save_i = 0 + candidates = [] + for i in range(20,300): + input_rate = self.folder_input_rate + output_rate = int(self.pulse_freq * i) + interp = gru.lcm(input_rate, output_rate) / input_rate + decim = gru.lcm(input_rate, output_rate) / output_rate + if (interp < 500 and decim < 250000): + candidates.append(i) + + # We didn't find anything, bail! + if (len(candidates) < 1): + print "Couldn't converge on resampler parameters" + sys.exit(1) + + # + # Now try to find candidate with the least sampling error + # + mindiff = 999.999 + for i in candidates: + diff = self.pulse_freq * i + diff = diff - int(diff) + if (diff < mindiff): + mindiff = diff + save_i = i + + # Recompute rates + input_rate = self.folder_input_rate + output_rate = int(self.pulse_freq * save_i) + + # Compute new interp and decim, based on best candidate + interp = gru.lcm(input_rate, output_rate) / input_rate + decim = gru.lcm(input_rate, output_rate) / output_rate + + # Save optimized folding parameters, used later + self.folding = save_i + self.interp = int(interp) + self.decim = int(decim) + + # So that we can view 4 pulses in the pulse viewer window + FOLD_MULT=4 + + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + + # Compute raw input rate + input_rate = self.u.adc_freq() / self.u.decim_rate() + + # BW==input_rate for complex data + self.bw = input_rate + + # + # We use this as a crude volume control for the audio output + # + self.volume = gr.multiply_const_ff(10**(-1)) + + + # + # Create location data for ephem package + # + self.locality = ephem.Observer() + self.locality.long = str(options.longitude) + self.locality.lat = str(options.latitude) + + # + # What is the post-detector LPF cutoff for the FFT? + # + PULSAR_MAX_FREQ=int(options.lowpass) + + # First low-pass filters down to input_rate/FIRST_FACTOR + # and decimates appropriately + FIRST_FACTOR=int(input_rate/(self.folder_input_rate/2)) + first_filter = gr.firdes.low_pass (1.0, + input_rate, + input_rate/FIRST_FACTOR, + input_rate/(FIRST_FACTOR*20), + gr.firdes.WIN_HAMMING) + + # Second filter runs at the output rate of the first filter, + # And low-pass filters down to PULSAR_MAX_FREQ*10 + # + second_input_rate = int(input_rate/(FIRST_FACTOR/2)) + second_filter = gr.firdes.band_pass(1.0, second_input_rate, + 0.10, + PULSAR_MAX_FREQ*10, + PULSAR_MAX_FREQ*1.5, + gr.firdes.WIN_HAMMING) + + # Third filter runs at PULSAR_MAX_FREQ*20 + # and filters down to PULSAR_MAX_FREQ + # + third_input_rate = PULSAR_MAX_FREQ*20 + third_filter = gr.firdes_band_pass(1.0, third_input_rate, + 0.10, PULSAR_MAX_FREQ, + PULSAR_MAX_FREQ/10.0, + gr.firdes.WIN_HAMMING) + + + # + # Create the appropriate FFT scope + # + self.scope = ra_fftsink.ra_fft_sink_f (self, panel, + fft_size=int(options.fft_size), sample_rate=PULSAR_MAX_FREQ*2, + title="Post-detector spectrum", + cfunc=self.pulsarfunc, xydfunc=self.xydfunc, fft_rate=200) + + # + # Tell scope we're looking from DC to PULSAR_MAX_FREQ + # + self.scope.set_baseband_freq (0.0) + + + # + # Setup stripchart for showing pulse profiles + # + hz = "%5.3fHz " % self.pulse_freq + per = "(%5.3f sec)" % (1.0/self.pulse_freq) + sr = "%d sps" % (int(self.pulse_freq*self.folding)) + self.chart = ra_stripchartsink.stripchart_sink_f (self, panel, + sample_rate=1, + stripsize=self.folding*FOLD_MULT, parallel=True, title="Pulse Profiles: "+hz+per, + xlabel="Seconds @ "+sr, ylabel="Level", autoscale=True, + divbase=self.divbase, scaling=1.0/(self.folding*self.pulse_freq)) + self.chart.set_ref_level(self.reflevel) + self.chart.set_y_per_div(self.division) + + # De-dispersion filter setup + # + # Do this here, just before creating the filter + # that will use the taps. + # + ntaps = self.compute_disp_ntaps(self.dm,self.bw,self.observing_freq) + + # Taps for the de-dispersion filter + self.disp_taps = Numeric.zeros(ntaps,Numeric.Complex64) + + # Compute the de-dispersion filter now + self.compute_dispfilter(self.dm,self.doppler, + self.bw,self.observing_freq) + + # + # Call constructors for receive chains + # + + # + # Now create the FFT filter using the computed taps + self.dispfilt = gr.fft_filter_ccc(1, self.disp_taps) + + # + # Audio sink + # + self.audio = audio.sink(second_input_rate, "plughw:0,0") + + # + # The three post-detector filters + # Done this way to allow an audio path (up to 10Khz) + # ...and also because going from xMhz down to ~100Hz + # In a single filter doesn't seem to work. + # + self.first = gr.fir_filter_fff (FIRST_FACTOR/2, first_filter) + + p = second_input_rate / (PULSAR_MAX_FREQ*20) + self.second = gr.fir_filter_fff (int(p), second_filter) + self.third = gr.fir_filter_fff (10, third_filter) + + # Split complex USRP stream into a pair of floats + self.splitter = gr.complex_to_float (1); + + # I squarer (detector) + self.multI = gr.multiply_ff(); + + # Q squarer (detector) + self.multQ = gr.multiply_ff(); + + # Adding squared I and Q to produce instantaneous signal power + self.adder = gr.add_ff(); + + self.enable_comb_filter = False + # Epoch folder comb filter + if self.enable_comb_filter == True: + bogtaps = Numeric.zeros(512, Numeric.Float64) + self.folder_comb = gr.fft_filter_ccc(1,bogtaps) + + # Rational resampler + self.folder_rr = blks.rational_resampler_fff(self, self.interp, self.decim) + + # Epoch folder bandpass + bogtaps = Numeric.zeros(1, Numeric.Float64) + self.folder_bandpass = gr.fir_filter_fff (1, bogtaps) + + # Epoch folder F2C/C2F + self.folder_f2c = gr.float_to_complex() + self.folder_c2f = gr.complex_to_float() + + # Epoch folder S2P + self.folder_s2p = gr.serial_to_parallel (gr.sizeof_float, + self.folding*FOLD_MULT) + + # Epoch folder IIR Filter (produces average pulse profiles) + self.folder_iir = gr.single_pole_iir_filter_ff(1.0/options.favg, + self.folding*FOLD_MULT) + + # + # Set all the epoch-folder goop up + # + self.set_folding_params() + + # + # Start connecting configured modules in the receive chain + # + + # Connect raw USRP to de-dispersion filter, complex->float splitter + self.connect(self.u, self.dispfilt, self.splitter) + + # Connect splitter outputs to multipliers + # First do I^2 + self.connect((self.splitter, 0), (self.multI,0)) + self.connect((self.splitter, 0), (self.multI,1)) + + # Then do Q^2 + self.connect((self.splitter, 1), (self.multQ,0)) + self.connect((self.splitter, 1), (self.multQ,1)) + + # Then sum the squares + self.connect(self.multI, (self.adder,0)) + self.connect(self.multQ, (self.adder,1)) + + # Connect detector/adder output to FIR LPF + # in two stages, followed by the FFT scope + self.connect(self.adder, self.first, + self.second, self.third, self.scope) + + # Connect audio output + self.connect(self.first, self.volume) + self.connect(self.volume, (self.audio, 0)) + self.connect(self.volume, (self.audio, 1)) + + # Connect epoch folder + if self.enable_comb_filter == True: + self.connect (self.first, self.folder_bandpass, self.folder_rr, + self.folder_f2c, + self.folder_comb, self.folder_c2f, + self.folder_s2p, self.folder_iir, + self.chart) + + else: + self.connect (self.first, self.folder_bandpass, self.folder_rr, + self.folder_s2p, self.folder_iir, self.chart) + + # Connect baseband recording file (initially /dev/null) + self.connect(self.u, self.tofloat, self.tochar, self.recording) + + # Connect pulse recording file (initially /dev/null) + self.connect(self.first, self.toshort, self.pulse_recording) + + # + # Build the GUI elements + # + self._build_gui(vbox) + + # Make GUI agree with command-line + self.myform['average'].set_value(int(options.avg)) + self.myform['foldavg'].set_value(int(options.favg)) + + + # Make spectral averager agree with command line + if options.avg != 1.0: + self.scope.set_avg_alpha(float(1.0/options.avg)) + self.scope.set_average(True) + + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdev.freq_range() + options.freq = float(r[0]+r[1])/2 + + self.set_gain(options.gain) + self.set_volume(-10.0) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + self.myform['dbname'].set_value(self.subdev.name()) + self.myform['DM'].set_value(self.dm) + self.myform['Doppler'].set_value(self.doppler) + + # + # Start the timer that shows current LMST on the GUI + # + self.lmst_timer.Start(1000) + + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + def _form_set_dm(kv): + return self.set_dm(kv['DM']) + + def _form_set_doppler(kv): + return self.set_doppler(kv['Doppler']) + + # Position the FFT or Waterfall + vbox.Add(self.scope.win, 5, wx.EXPAND) + vbox.Add(self.chart.win, 5, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((7,0), 0, wx.EXPAND) + vbox1 = wx.BoxSizer(wx.VERTICAL) + myform['freq'] = form.float_field( + parent=self.panel, sizer=vbox1, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + vbox1.Add((3,0), 0, 0) + + # To show current Local Mean Sidereal Time + myform['lmst_high'] = form.static_text_field( + parent=self.panel, sizer=vbox1, label="Current LMST", weight=1) + vbox1.Add((3,0), 0, 0) + + # To show current spectral cursor data + myform['spec_data'] = form.static_text_field( + parent=self.panel, sizer=vbox1, label="Pulse Freq", weight=1) + vbox1.Add((3,0), 0, 0) + + # To show best pulses found in FFT output + myform['best_pulse'] = form.static_text_field( + parent=self.panel, sizer=vbox1, label="Best freq", weight=1) + vbox1.Add((3,0), 0, 0) + + vboxBogus = wx.BoxSizer(wx.VERTICAL) + vboxBogus.Add ((2,0), 0, wx.EXPAND) + vbox2 = wx.BoxSizer(wx.VERTICAL) + g = self.subdev.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=vbox2, label="RF Gain", + weight=1, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + vbox2.Add((6,0), 0, 0) + myform['average'] = form.slider_field(parent=self.panel, sizer=vbox2, + label="Spectral Averaging", weight=1, min=1, max=200, callback=self.set_averaging) + vbox2.Add((6,0), 0, 0) + myform['foldavg'] = form.slider_field(parent=self.panel, sizer=vbox2, + label="Folder Averaging", weight=1, min=1, max=20, callback=self.set_folder_averaging) + vbox2.Add((6,0), 0, 0) + myform['volume'] = form.quantized_slider_field(parent=self.panel, sizer=vbox2, + label="Audio Volume", weight=1, range=(-20, 0, 0.5), callback=self.set_volume) + vbox2.Add((6,0), 0, 0) + myform['DM'] = form.float_field( + parent=self.panel, sizer=vbox2, label="DM", weight=1, + callback=myform.check_input_and_call(_form_set_dm)) + vbox2.Add((6,0), 0, 0) + myform['Doppler'] = form.float_field( + parent=self.panel, sizer=vbox2, label="Doppler", weight=1, + callback=myform.check_input_and_call(_form_set_doppler)) + vbox2.Add((6,0), 0, 0) + + + # Baseband recording control + buttonbox = wx.BoxSizer(wx.HORIZONTAL) + self.record_control = form.button_with_callback(self.panel, + label="Recording baseband: Off ", + callback=self.toggle_recording) + self.record_pulse_control = form.button_with_callback(self.panel, + label="Recording pulses: Off ", + callback=self.toggle_pulse_recording) + + buttonbox.Add(self.record_control, 0, wx.CENTER) + buttonbox.Add(self.record_pulse_control, 0, wx.CENTER) + vbox.Add(buttonbox, 0, wx.CENTER) + hbox.Add(vbox1, 0, 0) + hbox.Add(vboxBogus, 0, 0) + hbox.Add(vbox2, wx.ALIGN_RIGHT, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + self.lmst_timer = wx.PyTimer(self.lmst_timeout) + self.lmst_timeout() + + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['decim'] = form.static_float_field( + parent=panel, sizer=hbox, label="Decim") + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = usrp.tune(self.u, 0, self.subdev, target_freq) + + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + # Adjust self.frequency, and self.observing_freq + # We pick up the difference between the current self.frequency + # and the just-programmed one, and use this to adjust + # self.observing_freq. We have to do it this way to + # make the dedispersion filtering work out properly. + delta = target_freq - self.frequency + self.frequency = target_freq + self.observing_freq += delta + + # Now that we're adjusted, compute a new dispfilter, and + # set the taps for the FFT filter. + ntaps = self.compute_disp_ntaps(self.dm, self.bw, self.observing_freq) + self.disp_taps = Numeric.zeros(ntaps, Numeric.Complex64) + self.compute_dispfilter(self.dm,self.doppler,self.bw, + self.observing_freq) + self.dispfilt.set_taps(self.disp_taps) + + return True + + return False + + # Callback for gain-setting slider + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + + def set_volume(self, vol): + self.myform['volume'].set_value(vol) + self.volume.set_k((10**(vol/10))/8192) + + # Callback for spectral-averaging slider + def set_averaging(self, avval): + self.myform['average'].set_value(avval) + self.scope.set_avg_alpha(1.0/(avval)) + self.scope.set_average(True) + + def set_folder_averaging(self, avval): + self.myform['foldavg'].set_value(avval) + self.folder_iir.set_taps(1.0/avval) + + # Timer callback to update LMST display + def lmst_timeout(self): + self.locality.date = ephem.now() + sidtime = self.locality.sidereal_time() + self.myform['lmst_high'].set_value(str(ephem.hours(sidtime))) + + # + # Turn recording on/off + # Called-back by "Recording" button + # + def toggle_recording(self): + # Pick up current LMST + self.locality.date = ephem.now() + sidtime = self.locality.sidereal_time() + + # Pick up localtime, for generating filenames + foo = time.localtime() + + # Generate filenames for both data and header file + filename = "%04d%02d%02d%02d%02d.pdat" % (foo.tm_year, foo.tm_mon, + foo.tm_mday, foo.tm_hour, foo.tm_min) + hdrfilename = "%04d%02d%02d%02d%02d.phdr" % (foo.tm_year, foo.tm_mon, + foo.tm_mday, foo.tm_hour, foo.tm_min) + + # Current recording? Flip state + if (self.recording_state == True): + self.recording_state = False + self.record_control.SetLabel("Recording baseband: Off ") + self.recording.close() + # Not recording? + else: + self.recording_state = True + self.record_control.SetLabel("Recording baseband to: "+filename) + + # Cause gr_file_sink object to accept new filename + # note use of self.prefix--filename prefix from + # command line (defaults to ./) + # + self.recording.open (self.prefix+filename) + + # + # We open the header file as a regular file, write header data, + # then close + hdrf = open(self.prefix+hdrfilename, "w") + hdrf.write("receiver center frequency: "+str(self.frequency)+"\n") + hdrf.write("observing frequency: "+str(self.observing_freq)+"\n") + hdrf.write("DM: "+str(self.dm)+"\n") + hdrf.write("doppler: "+str(self.doppler)+"\n") + + hdrf.write("sidereal: "+str(ephem.hours(sidtime))+"\n") + hdrf.write("bandwidth: "+str(self.u.adc_freq() / self.u.decim_rate())+"\n") + hdrf.write("sample type: complex_char\n") + hdrf.write("sample size: "+str(gr.sizeof_char*2)+"\n") + hdrf.close() + # + # Turn recording on/off + # Called-back by "Recording" button + # + def toggle_pulse_recording(self): + # Pick up current LMST + self.locality.date = ephem.now() + sidtime = self.locality.sidereal_time() + + # Pick up localtime, for generating filenames + foo = time.localtime() + + # Generate filenames for both data and header file + filename = "%04d%02d%02d%02d%02d.padat" % (foo.tm_year, foo.tm_mon, + foo.tm_mday, foo.tm_hour, foo.tm_min) + hdrfilename = "%04d%02d%02d%02d%02d.pahdr" % (foo.tm_year, foo.tm_mon, + foo.tm_mday, foo.tm_hour, foo.tm_min) + + # Current recording? Flip state + if (self.pulse_recording_state == True): + self.pulse_recording_state = False + self.record_pulse_control.SetLabel("Recording pulses: Off ") + self.pulse_recording.close() + # Not recording? + else: + self.pulse_recording_state = True + self.record_pulse_control.SetLabel("Recording pulses to: "+filename) + + # Cause gr_file_sink object to accept new filename + # note use of self.prefix--filename prefix from + # command line (defaults to ./) + # + self.pulse_recording.open (self.prefix+filename) + + # + # We open the header file as a regular file, write header data, + # then close + hdrf = open(self.prefix+hdrfilename, "w") + hdrf.write("receiver center frequency: "+str(self.frequency)+"\n") + hdrf.write("observing frequency: "+str(self.observing_freq)+"\n") + hdrf.write("DM: "+str(self.dm)+"\n") + hdrf.write("doppler: "+str(self.doppler)+"\n") + hdrf.write("pulse rate: "+str(self.pulse_freq)+"\n") + hdrf.write("pulse sps: "+str(self.pulse_freq*self.folding)+"\n") + hdrf.write("file sps: "+str(self.folder_input_rate)+"\n") + + hdrf.write("sidereal: "+str(ephem.hours(sidtime))+"\n") + hdrf.write("bandwidth: "+str(self.u.adc_freq() / self.u.decim_rate())+"\n") + hdrf.write("sample type: short\n") + hdrf.write("sample size: 1\n") + hdrf.close() + + # We get called at startup, and whenever the GUI "Set Folding params" + # button is pressed + # + def set_folding_params(self): + if (self.pulse_freq <= 0): + return + + # Compute required sample rate + self.sample_rate = int(self.pulse_freq*self.folding) + + # And the implied decimation rate + required_decimation = int(self.folder_input_rate / self.sample_rate) + + # We also compute a new FFT comb filter, based on the expected + # spectral profile of our pulse parameters + # + # FFT-based comb filter + # + N_COMB_TAPS=int(self.sample_rate*4) + if N_COMB_TAPS > 2000: + N_COMB_TAPS = 2000 + self.folder_comb_taps = Numeric.zeros(N_COMB_TAPS,Numeric.Complex64) + fincr = (self.sample_rate)/float(N_COMB_TAPS) + for i in range(0,len(self.folder_comb_taps)): + self.folder_comb_taps[i] = complex(0.0, 0.0) + + freq = 0.0 + harmonics = [1.0,2.0,3.0,4.0,5.0,6.0,7.0] + for i in range(0,len(self.folder_comb_taps)/2): + for j in range(0,len(harmonics)): + if abs(freq - harmonics[j]*self.pulse_freq) <= fincr: + self.folder_comb_taps[i] = complex(4.0, 0.0) + if harmonics[j] == 1.0: + self.folder_comb_taps[i] = complex(8.0, 0.0) + freq += fincr + + if self.enable_comb_filter == True: + # Set the just-computed FFT comb filter taps + self.folder_comb.set_taps(self.folder_comb_taps) + + # And compute a new decimated bandpass filter, to go in front + # of the comb. Primary function is to decimate and filter down + # to an exact-ish multiple of the target pulse rate + # + self.folding_taps = gr.firdes_band_pass (1.0, self.folder_input_rate, + 0.10, self.sample_rate/2, 10, + gr.firdes.WIN_HAMMING) + + # Set the computed taps for the bandpass/decimate filter + self.folder_bandpass.set_taps (self.folding_taps) + # + # Record a spectral "hit" of a possible pulsar spectral profile + # + def record_hit(self,hits, hcavg, hcmax): + # Pick up current LMST + self.locality.date = ephem.now() + sidtime = self.locality.sidereal_time() + + # Pick up localtime, for generating filenames + foo = time.localtime() + + # Generate filenames for both data and header file + hitfilename = "%04d%02d%02d%02d.phit" % (foo.tm_year, foo.tm_mon, + foo.tm_mday, foo.tm_hour) + + hitf = open(self.prefix+hitfilename, "a") + hitf.write("receiver center frequency: "+str(self.frequency)+"\n") + hitf.write("observing frequency: "+str(self.observing_freq)+"\n") + hitf.write("DM: "+str(self.dm)+"\n") + hitf.write("doppler: "+str(self.doppler)+"\n") + + hitf.write("sidereal: "+str(ephem.hours(sidtime))+"\n") + hitf.write("bandwidth: "+str(self.u.adc_freq() / self.u.decim_rate())+"\n") + hitf.write("spectral peaks: "+str(hits)+"\n") + hitf.write("HCM: "+str(hcavg)+" "+str(hcmax)+"\n") + hitf.close() + + # This is a callback used by ra_fftsink.py (passed on creation of + # ra_fftsink) + # Whenever the user moves the cursor within the FFT display, this + # shows the coordinate data + # + def xydfunc(self,xyv): + s = "%.6fHz\n%.3fdB" % (xyv[0], xyv[1]) + if self.lowpass >= 500: + s = "%.6fHz\n%.3fdB" % (xyv[0]*1000, xyv[1]) + + self.myform['spec_data'].set_value(s) + + # This is another callback used by ra_fftsink.py (passed on creation + # of ra_fftsink). We pass this as our "calibrator" function, but + # we create interesting side-effects in the GUI. + # + # This function finds peaks in the FFT output data, and reports + # on them through the "Best" text object in the GUI + # It also computes the Harmonic Compliance Measure (HCM), and displays + # that also. + # + def pulsarfunc(self,d,l): + x = range(0,l) + incr = float(self.lowpass)/float(l) + incr = incr * 2.0 + bestdb = -50.0 + bestfreq = 0.0 + avg = 0 + dcnt = 0 + # + # First, we need to find the average signal level + # + for i in x: + if (i * incr) > self.lowest_freq and (i*incr) < (self.lowpass-2): + avg += d[i] + dcnt += 1 + # Set average signal level + avg /= dcnt + s2=" " + findcnt = 0 + # + # Then we find candidates that are greater than the user-supplied + # threshold. + # + # We try to cluster "hits" whose whole-number frequency is the + # same, and compute an average "hit" frequency. + # + lastint = 0 + hits=[] + intcnt = 0 + freqavg = 0 + for i in x: + freq = i*incr + # If frequency within bounds, and the (dB-avg) value is above our + # threshold + if freq > self.lowest_freq and freq < self.lowpass-2 and (d[i] - avg) > self.threshold: + # If we're finding a new whole-number frequency + if lastint != int(freq): + # Record "center" of this hit, if this is a new hit + if lastint != 0: + s2 += "%5.3fHz " % (freqavg/intcnt) + hits.append(freqavg/intcnt) + findcnt += 1 + lastint = int(freq) + intcnt = 1 + freqavg = freq + else: + intcnt += 1 + freqavg += freq + if (findcnt >= 14): + break + + if intcnt > 1: + s2 += "%5.3fHz " % (freqavg/intcnt) + hits.append(freqavg/intcnt) + + # + # Compute the HCM, by dividing each of the "hits" by each of the + # other hits, and comparing the difference between a "perfect" + # harmonic, and the observed frequency ratio. + # + measure = 0 + max_measure=0 + mcnt = 0 + avg_dist = 0 + acnt = 0 + for i in range(1,len(hits)): + meas = hits[i]/hits[0] - int(hits[i]/hits[0]) + if abs((hits[i]-hits[i-1])-hits[0]) < 0.1: + avg_dist += hits[i]-hits[i-1] + acnt += 1 + if meas > 0.98 and meas < 1.0: + meas = 1.0 - meas + meas *= hits[0] + if meas >= max_measure: + max_measure = meas + measure += meas + mcnt += 1 + if mcnt > 0: + measure /= mcnt + if acnt > 0: + avg_dist /= acnt + if len(hits) > 1: + measure /= mcnt + s3="\nHCM: Avg %5.3fHz(%d) Max %5.3fHz Dist %5.3fHz(%d)" % (measure,mcnt,max_measure, avg_dist, acnt) + if max_measure < 0.5 and len(hits) >= 2: + self.record_hit(hits, measure, max_measure) + self.avg_dist = avg_dist + else: + s3="\nHCM: --" + s4="\nAvg dB: %4.2f" % avg + self.myform['best_pulse'].set_value("("+s2+")"+s3+s4) + + # Since we are nominally a calibrator function for ra_fftsink, we + # simply return what they sent us, untouched. A "real" calibrator + # function could monkey with the data before returning it to the + # FFT display function. + return(d) + + # + # Callback for the "DM" gui object + # + # We call compute_dispfilter() as appropriate to compute a new filter, + # and then set that new filter into self.dispfilt. + # + def set_dm(self,dm): + self.dm = dm + + ntaps = self.compute_disp_ntaps (self.dm, self.bw, self.observing_freq) + self.disp_taps = Numeric.zeros(ntaps, Numeric.Complex64) + self.compute_dispfilter(self.dm,self.doppler,self.bw,self.observing_freq) + self.dispfilt.set_taps(self.disp_taps) + self.myform['DM'].set_value(dm) + return(dm) + + # + # Callback for the "Doppler" gui object + # + # We call compute_dispfilter() as appropriate to compute a new filter, + # and then set that new filter into self.dispfilt. + # + def set_doppler(self,doppler): + self.doppler = doppler + + ntaps = self.compute_disp_ntaps (self.dm, self.bw, self.observing_freq) + self.disp_taps = Numeric.zeros(ntaps, Numeric.Complex64) + self.compute_dispfilter(self.dm,self.doppler,self.bw,self.observing_freq) + self.dispfilt.set_taps(self.disp_taps) + self.myform['Doppler'].set_value(doppler) + return(doppler) + + # + # Compute a de-dispersion filter + # From Hankins, et al, 1975 + # + # This code translated from dedisp_filter.c from Swinburne + # pulsar software repository + # + def compute_dispfilter(self,dm,doppler,bw,centerfreq): + npts = len(self.disp_taps) + tmp = Numeric.zeros(npts, Numeric.Complex64) + M_PI = 3.14159265358 + DM = dm/2.41e-10 + + # + # Because astronomers are a crazy bunch, the "standard" calcultion + # is in Mhz, rather than Hz + # + centerfreq = centerfreq / 1.0e6 + bw = bw / 1.0e6 + + isign = int(bw / abs (bw)) + + # Center frequency may be doppler shifted + cfreq = centerfreq / doppler + + # As well as the bandwidth.. + bandwidth = bw / doppler + + # Bandwidth divided among bins + binwidth = bandwidth / npts + + # Delay is an "extra" parameter, in usecs, and largely + # untested in the Swinburne code. + delay = 0.0 + + # This determines the coefficient of the frequency response curve + # Linear in DM, but quadratic in center frequency + coeff = isign * 2.0*M_PI * DM / (cfreq*cfreq) + + # DC to nyquist/2 + n = 0 + for i in range(0,int(npts/2)): + freq = (n + 0.5) * binwidth + phi = coeff*freq*freq/(cfreq+freq) + (2.0*M_PI*freq*delay) + tmp[i] = complex(math.cos(phi), math.sin(phi)) + n += 1 + + # -nyquist/2 to DC + n = int(npts/2) + n *= -1 + for i in range(int(npts/2),npts): + freq = (n + 0.5) * binwidth + phi = coeff*freq*freq/(cfreq+freq) + (2.0*M_PI*freq*delay) + tmp[i] = complex(math.cos(phi), math.sin(phi)) + n += 1 + + self.disp_taps = FFT.inverse_fft(tmp) + return(self.disp_taps) + + # + # Compute minimum number of taps required in de-dispersion FFT filter + # + def compute_disp_ntaps(self,dm,bw,freq): + # + # Dt calculations are in Mhz, rather than Hz + # crazy astronomers.... + mbw = bw/1.0e6 + mfreq = freq/1.0e6 + + f_lower = mfreq-(mbw/2) + f_upper = mfreq+(mbw/2) + + # Compute smear time + Dt = dm/2.41e-4 * (1.0/(f_lower*f_lower)-1.0/(f_upper*f_upper)) + + # ntaps is now bandwidth*smeartime + # Should be bandwidth*smeartime*2, but the Gnu Radio FFT filter + # already expands it by a factor of 2 + ntaps = bw*Dt + if ntaps < 64: + ntaps = 64 + return(int(ntaps)) + +def main (): + app = stdgui.stdapp(app_flow_graph, "RADIO ASTRONOMY PULSAR RECEIVER: $Revision$", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gr-radio-astronomy/src/python/usrp_ra_receiver.help b/gr-radio-astronomy/src/python/usrp_ra_receiver.help new file mode 100644 index 00000000..45a21e29 --- /dev/null +++ b/gr-radio-astronomy/src/python/usrp_ra_receiver.help @@ -0,0 +1,90 @@ +This program is used to take spectra and total power measurements. + It records spectral and total-power data to external datalogging + files. + +The program takes the following options: + + --rx-subdev-spec which USRP Rx side? A or B + + --decim USRP decimation rate: 8, 16, 32, and 64 are good + (8Mhz, 4Mhz, 2Mhz, and 1Mhz bandwidth) + + --freq USRP daughtercard frequency + + --observing Actual observing frequency (default is to use the + setting for --freq) + + --avg Averaging setting for spectral display--higher numbers + equal more averaging. 25 to 40 is typical. + + --integ Total power integration time: seconds + + --gain USRP daughtercard gain control + + --reflevel Reference level on pulse profile display + + --longitude Observer longitude: West is negative + + --latitude Observer latitude: South is negative + + --fft_size Size of FFT for post-detector spectrum: default is 1024 + + --prefix Filename prefix to use for data logging files + Default is ./ + + --divbase The base of the Y/Div menu in pulsar display + + --division The initial Y/Div in pulsar display + + --ylabel Y axis label + + --cfunc The function name prefix for the spectral and + calibrator functions + + --waterfall Use waterfall, rather than regular spectral display + NOT TESTED IN THIS APPLICATION + + --stripsize Size of the total-power stripchart, in samples + +There are two windows--a spectral window, and the total-power window. + Moving the cursor around in the spectral window shows you the + corresponding frequency and doppler shift. Left clicking in this + window sets an interference marker, which sets a "zero" in the + interference filter. Use the "clear interference" button to clear this. + +The total power window is updated at a fixed 2Hz rate, and grows from + the left of the display. + +If latitude and longitude are set correctly, and system time is correct, + then the current LMST is displayed, updated once per second. + +Averaging parameters, gain, and frequency can all be set from the GUI using + the appropriate controls. You can also enter the current declination, which + will appear in the datalogging files. This is useful both for mapping, + and housekeeping purposes, particularly when you haven't looked at a datafile + for quite some time. + +There are two datalog files produced by this program: + + YYYYMMDDHH.tpdat Total power data + + The date/time portion of the filename is referred to local time, + rather than UTC or sidereal. + + First field is sidereal time when sample was taken + Second field is total power datum + Third field is declination in decimal degrees + + Samples are written once per second + + YYYYMMDDHH.sdat Spectral data + + The date/time portion of the filename is referred to local time, + rather than UTC or sidereal. + + First field is sidereal time when spectrum was taken + Second field is declination in decimal degrees + Third field is complex spectral data--in the same order that FFTW3 library + places bins: DC to bandwidth/2, followed by -bandwidth/2 to DC. + + Spectral snapshots are written once every 5 seconds diff --git a/gr-radio-astronomy/src/python/usrp_ra_receiver.py b/gr-radio-astronomy/src/python/usrp_ra_receiver.py new file mode 100755 index 00000000..37a1ebff --- /dev/null +++ b/gr-radio-astronomy/src/python/usrp_ra_receiver.py @@ -0,0 +1,584 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import usrp +import usrp_dbid +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, ra_fftsink, ra_stripchartsink, waterfallsink, form, slider +from optparse import OptionParser +import wx +import sys +from Numeric import * +import FFT +import ephem +from gnuradio.local_calibrator import * + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-a", "--avg", type="eng_float", default=1.0, + help="set spectral averaging alpha") + parser.add_option("-i", "--integ", type="eng_float", default=1.0, + help="set integration time") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-l", "--reflevel", type="eng_float", default=30.0, + help="Set Total power reference level") + parser.add_option("-y", "--division", type="eng_float", default=0.5, + help="Set Total power Y division size") + parser.add_option("-e", "--longitude", type="eng_float", default=-76.02, help="Set Observer Longitude") + parser.add_option("-c", "--latitude", type="eng_float", default=44.85, help="Set Observer Latitude") + parser.add_option("-o", "--observing", type="eng_float", default=0.0, + help="Set observing frequency") + parser.add_option("-x", "--ylabel", default="dB", help="Y axis label") + parser.add_option("-C", "--cfunc", default="default", help="Calibration function name") + parser.add_option("-z", "--divbase", type="eng_float", default=0.025, help="Y Division increment base") + parser.add_option("-v", "--stripsize", type="eng_float", default=2400, help="Size of stripchart, in 2Hz samples") + parser.add_option("-F", "--fft_size", type="eng_float", default=1024, help="Size of FFT") + + parser.add_option("-N", "--decln", type="eng_float", default=999.99, help="Observing declination") + parser.add_option("-I", "--interfilt", action="store_true", default=False) + parser.add_option("-X", "--prefix", default="./") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + # build the graph + + self.u = usrp.source_c(decim_rate=options.decim) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + self.cardtype = self.u.daughterboard_id(0) + # Set initial declination + self.decln = options.decln + + # Turn off interference filter by default + self.use_interfilt = options.interfilt + + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + + input_rate = self.u.adc_freq() / self.u.decim_rate() + + tpstr="calib_"+options.cfunc+"_total_power" + sstr="calib_"+options.cfunc+"_fft" + self.tpcfunc=eval(tpstr) + self.scfunc=eval(sstr) + + # + # Set prefix for data files + # + self.prefix = options.prefix + calib_set_prefix(self.prefix) + + # Set up FFT display + self.scope = ra_fftsink.ra_fft_sink_c (self, panel, + fft_size=int(options.fft_size), sample_rate=input_rate, + fft_rate=8, title="Spectral", + cfunc=self.scfunc, xydfunc=self.xydfunc, interfunc=self.interference) + + # Set up ephemeris data + self.locality = ephem.Observer() + self.locality.long = str(options.longitude) + self.locality.lat = str(options.latitude) + + # Set up stripchart display + self.stripsize = int(options.stripsize) + self.chart = ra_stripchartsink.stripchart_sink_f (self, panel, + stripsize=self.stripsize, + title="Continuum", + xlabel="LMST Offset (Seconds)", + scaling=1.0, ylabel=options.ylabel, + divbase=options.divbase, cfunc=self.tpcfunc) + + # Set center frequency + self.centerfreq = options.freq + + # Set observing frequency (might be different from actual programmed + # RF frequency) + if options.observing == 0.0: + self.observing = options.freq + else: + self.observing = options.observing + + self.bw = input_rate + + # + # Produce a default interference map + # May not actually get used, unless --interfilt was specified + # + self.intmap = Numeric.zeros(256,Numeric.Complex64) + for i in range(0,len(self.intmap)): + self.intmap[i] = complex(1.0, 0.0) + + # We setup the first two integrators to produce a fixed integration + # Down to 1Hz, with output at 1 samples/sec + N = input_rate/5000 + + # Second stage runs on decimated output of first + M = (input_rate/N) + + # Create taps for first integrator + t = range(0,N-1) + tapsN = [] + for i in t: + tapsN.append(1.0/N) + + # Create taps for second integrator + t = range(0,M-1) + tapsM = [] + for i in t: + tapsM.append(1.0/M) + + # + # The 3rd integrator is variable, and user selectable at runtime + # This integrator doesn't decimate, but is used to set the + # final integration time based on the constant 1Hz input samples + # The strip chart is fed at a constant 1Hz rate as a result + # + + # + # Call constructors for receive chains + # + + # + # This is the interference-zapping filter + # + # The GUI is used to set/clear inteference zones in + # the filter. The non-interfering zones are set to + # 1.0. + # + if 0: + self.interfilt = gr.fft_filter_ccc(1,self.intmap) + tmp = FFT.inverse_fft(self.intmap) + self.interfilt.set_taps(tmp) + + # The three integrators--two FIR filters, and an IIR final filter + self.integrator1 = gr.fir_filter_fff (N, tapsN) + self.integrator2 = gr.fir_filter_fff (M, tapsM) + self.integrator3 = gr.single_pole_iir_filter_ff(1.0) + + # Split complex USRP stream into a pair of floats + self.splitter = gr.complex_to_float (1); + self.toshort = gr.float_to_short(); + + # I squarer (detector) + self.multI = gr.multiply_ff(); + + # Q squarer (detector) + self.multQ = gr.multiply_ff(); + + # Adding squared I and Q to produce instantaneous signal power + self.adder = gr.add_ff(); + + # + # Start connecting configured modules in the receive chain + # + + # Connect interference-filtered USRP input to selected scope function + if self.use_interfilt == True: + self.connect(self.u, self.interfilt, self.scope) + + # Connect interference-filtered USRP to a complex->float splitter + self.connect(self.interfilt, self.splitter) + + else: + self.connect(self.u, self.scope) + self.connect(self.u, self.splitter) + + # Connect splitter outputs to multipliers + # First do I^2 + self.connect((self.splitter, 0), (self.multI,0)) + self.connect((self.splitter, 0), (self.multI,1)) + + # Then do Q^2 + self.connect((self.splitter, 1), (self.multQ,0)) + self.connect((self.splitter, 1), (self.multQ,1)) + + # Then sum the squares + self.connect(self.multI, (self.adder,0)) + self.connect(self.multQ, (self.adder,1)) + + # Connect adder output to three-stages of FIR integrator + self.connect(self.adder, self.integrator1, + self.integrator2, self.integrator3, self.chart) + + + self._build_gui(vbox) + + # Make GUI agree with command-line + self.myform['integration'].set_value(int(options.integ)) + self.myform['average'].set_value(int(options.avg)) + + # Make integrator agree with command line + self.set_integration(int(options.integ)) + + # Make spectral averager agree with command line + if options.avg != 1.0: + self.scope.set_avg_alpha(float(1.0/options.avg)) + calib_set_avg_alpha(float(options.avg)) + self.scope.set_average(True) + + + # Set division size + self.chart.set_y_per_div(options.division) + + # Set reference(MAX) level + self.chart.set_ref_level(options.reflevel) + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdev.freq_range() + options.freq = float(r[0]+r[1])/2 + + # Set the initial gain control + self.set_gain(options.gain) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + self.set_decln (self.decln) + calib_set_bw(self.decln) + + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + self.myform['dbname'].set_value(self.subdev.name()) + + # Make sure calibrator knows what our bandwidth is + calib_set_bw(self.u.adc_freq() / self.u.decim_rate()) + + # Tell calibrator our declination as well + calib_set_decln(self.decln) + + # Start the timer for the LMST display + self.lmst_timer.Start(1000) + + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + def _form_set_decln(kv): + return self.set_decln(kv['decln']) + + # Position the FFT display + vbox.Add(self.scope.win, 15, wx.EXPAND) + + # Position the Total-power stripchart + vbox.Add(self.chart.win, 15, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((7,0), 0, wx.EXPAND) + vbox1 = wx.BoxSizer(wx.VERTICAL) + myform['freq'] = form.float_field( + parent=self.panel, sizer=vbox1, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + vbox1.Add((4,0), 0, 0) + + myform['lmst_high'] = form.static_text_field( + parent=self.panel, sizer=vbox1, label="Current LMST", weight=1) + vbox1.Add((4,0), 0, 0) + + myform['spec_data'] = form.static_text_field( + parent=self.panel, sizer=vbox1, label="Spectral Cursor", weight=1) + vbox1.Add((4,0), 0, 0) + + vbox2 = wx.BoxSizer(wx.VERTICAL) + g = self.subdev.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=vbox2, label="RF Gain", + weight=1, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + vbox2.Add((4,0), 0, 0) + myform['average'] = form.slider_field(parent=self.panel, sizer=vbox2, + label="Spectral Averaging (FFT frames)", weight=1, min=1, max=2000, callback=self.set_averaging) + + vbox2.Add((4,0), 0, 0) + + myform['integration'] = form.slider_field(parent=self.panel, sizer=vbox2, + label="Continuum Integration Time (sec)", weight=1, min=1, max=180, callback=self.set_integration) + + vbox2.Add((4,0), 0, 0) + myform['decln'] = form.float_field( + parent=self.panel, sizer=vbox2, label="Current Declination", weight=1, + callback=myform.check_input_and_call(_form_set_decln)) + vbox2.Add((4,0), 0, 0) + + buttonbox = wx.BoxSizer(wx.HORIZONTAL) + if self.use_interfilt == True: + self.doit = form.button_with_callback(self.panel, + label="Clear Interference List", + callback=self.clear_interferers) + if self.use_interfilt == True: + buttonbox.Add(self.doit, 0, wx.CENTER) + vbox.Add(buttonbox, 0, wx.CENTER) + hbox.Add(vbox1, 0, 0) + hbox.Add(vbox2, wx.ALIGN_RIGHT, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + self.lmst_timer = wx.PyTimer(self.lmst_timeout) + self.lmst_timeout() + + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['decim'] = form.static_float_field( + parent=panel, sizer=hbox, label="Decim") + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + # + # Everything except BASIC_RX should support usrp.tune() + # + if not (self.cardtype == usrp_dbid.BASIC_RX): + r = usrp.tune(self.u, 0, self.subdev, target_freq) + else: + r = self.u.set_rx_freq(0, target_freq) + f = self.u.rx_freq(0) + if abs(f-target_freq) > 2.0e3: + r = 0 + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + # + # Make sure calibrator knows our target freq + # + + # Remember centerfreq---used for doppler calcs + delta = self.centerfreq - target_freq + self.centerfreq = target_freq + self.observing -= delta + self.scope.set_baseband_freq (self.observing) + calib_set_freq(self.observing) + + # Clear interference list + self.clear_interferers() + + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + + return True + + return False + + def set_decln(self, dec): + self.decln = dec + self.myform['decln'].set_value(dec) # update displayed value + calib_set_decln(dec) + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + # + # Make sure calibrator knows our gain setting + # + calib_set_gain(gain) + + def set_averaging(self, avval): + self.myform['average'].set_value(avval) + self.scope.set_avg_alpha(1.0/(avval)) + calib_set_avg_alpha(avval) + self.scope.set_average(True) + + def set_integration(self, integval): + self.integrator3.set_taps(1.0/integval) + self.myform['integration'].set_value(integval) + + # + # Make sure calibrator knows our integration time + # + calib_set_integ(integval) + + def lmst_timeout(self): + self.locality.date = ephem.now() + sidtime = self.locality.sidereal_time() + self.myform['lmst_high'].set_value(str(ephem.hours(sidtime))) + + def xydfunc(self,xyv): + magn = int(log10(self.observing)) + if (magn == 6 or magn == 7 or magn == 8): + magn = 6 + dfreq = xyv[0] * pow(10.0,magn) + ratio = self.observing / dfreq + vs = 1.0 - ratio + vs *= 299792.0 + if magn >= 9: + xhz = "Ghz" + elif magn >= 6: + xhz = "Mhz" + elif magn <= 5: + xhz = "Khz" + s = "%.6f%s\n%.3fdB" % (xyv[0], xhz, xyv[1]) + s2 = "\n%.3fkm/s" % vs + self.myform['spec_data'].set_value(s+s2) + + def interference(self,x): + if self.use_interfilt == False: + return + magn = int(log10(self.observing)) + dfreq = x * pow(10.0,magn) + delta = dfreq - self.observing + fincr = self.bw / len(self.intmap) + l = len(self.intmap) + if delta > 0: + offset = delta/fincr + else: + offset = (l) - int((abs(delta)/fincr)) + + offset = int(offset) + + if offset >= len(self.intmap) or offset < 0: + print "interference offset is invalid--", offset + return + + # + # Zero out the region around the selected interferer + # + self.intmap[offset-2] = complex (0.5, 0.0) + self.intmap[offset-1] = complex (0.25, 0.0) + self.intmap[offset] = complex (0.0, 0.0) + self.intmap[offset+1] = complex(0.25, 0.0) + self.intmap[offset+2] = complex(0.5, 0.0) + + # + # Set new taps + # + tmp = FFT.inverse_fft(self.intmap) + self.interfilt.set_taps(tmp) + + def clear_interf(self): + self.clear_interferers() + + def clear_interferers(self): + for i in range(0,len(self.intmap)): + self.intmap[i] = complex(1.0,0.0) + tmp = FFT.inverse_fft(self.intmap) + if self.use_interfilt == True: + self.interfilt.set_taps(tmp) + + + + def toggle_cal(self): + if (self.calstate == True): + self.calstate = False + self.u.write_io(0,0,(1<<15)) + self.calibrator.SetLabel("Calibration Source: Off") + else: + self.calstate = True + self.u.write_io(0,(1<<15),(1<<15)) + self.calibrator.SetLabel("Calibration Source: On") + + def toggle_annotation(self): + if (self.annotate_state == True): + self.annotate_state = False + self.annotation.SetLabel("Annotation: Off") + else: + self.annotate_state = True + self.annotation.SetLabel("Annotation: On") + calib_set_interesting(self.annotate_state) + + +def main (): + app = stdgui.stdapp(app_flow_graph, "RADIO ASTRONOMY SPECTRAL/CONTINUUM RECEIVER: $Revision$", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gr-usrp/AUTHORS b/gr-usrp/AUTHORS new file mode 100644 index 00000000..ee4560a5 --- /dev/null +++ b/gr-usrp/AUTHORS @@ -0,0 +1 @@ +Eric Blossom diff --git a/gr-usrp/ChangeLog b/gr-usrp/ChangeLog new file mode 100644 index 00000000..9744d397 --- /dev/null +++ b/gr-usrp/ChangeLog @@ -0,0 +1,374 @@ +2006-06-17 Eric Blossom + + * src/usrp.py, src/usrp1.i, src/usrp1_sink_base.cc, src/usrp1_sink_base.h, + src/usrp1_sink_c.cc, src/usrp1_sink_c.h, src/usrp1_sink_s.cc, + src/usrp1_sink_s.h, src/usrp1_source_base.cc, src/usrp1_source_base.h, + src/usrp1_source_c.cc, src/usrp1_source_c.h, src/usrp1_source_s.cc, + src/usrp1_source_s.h: changed constructor args to add + fusb_block_size and fusb_nblocks so that the application can + adjust the amount of buffering being done. [This was an awful lot + of files to have to touch to make this change. There must be an + easier way?] + + +2006-05-11 Martin Dudok van Heel + Added synchronised multi_usrp support. + This work was funded by Toby Oliver at Sensus Analytics / Path Intelligence. + + See README_MULTI_USRP.txt and the multi_usrp examples on how to use. + In short: + Connect the 64MHz clocks between the boards with a short sma coax cable. + (See the wiki on how to enable clock-out and clock-in + http://comsec.com/wiki?USRPClockingNotes ) + Connect io15 on the RXA daughterboards of both usrps + instantiate multi=usrp_multi.multi_source_align([args]) + The 4 aligned channels become available as: + (multi.get_master_source_c(),1) (multi.get_master_source_c(),2) + (multi.get_slave_source(),1) (multi.get_slave_source(),2) + call multi.sync() at least once AFTER the flowgraph has started running + + * READMU_MULTI_USRP.txt: new + * configure.ac: added missing newline at end of file + * src/Makefile.am: added usrp_multi.py + * src/usrp1.i: added _write_fpga_reg_masked + * src/usrp1_source_base.[cc,h]: added _write_fpga_reg_masked + * src/usrp_multi.py: new Instantiate a usrp_multi.multi_source_align to + get aligned streams from two usrps. + +2006-03-11 Matt Ettus + + * src/Makefile.am, src/db_flexrf_mimo.py, src/usrp.py: New skeleton + file for mimo mode with the flexrf boards + + * src/db_base.py: added standard code to control refclock and + adc buffer bypass so all dboards can do it the same way. Taken from + db_dbs_rx.py + + * src/db_tv_rx.py: Use standard method for adc buffer bypass + + * src/db_flexrf.py: Use standard method for adc buffer bypass + + * src/db_dbs_rx.py: Use standard methods for adc buffer bypass and + refclock control + + * src/db_basic.py: Use standard method for adc buffer bypass, + and instantiate a BasicTX when the unknown or missing board is on + the TX side + +2006-03-10 Eric Blossom + + * src/db_dbs_rx.py (db_dbs_rx._refclk_freq): replaced 64e6 with + call to fpga_master_clock_freq(). + +2006-02-18 Eric Blossom + + * src/usrp1_{sink,source}_{base,c,s}.{h,cc}, src/usrp1.i, + src/usrp.py: added support for specifying the firmware and fpga + files that are to be loaded. + +2006-02-17 Eric Blossom + + * src/usrp1.i, src/usrp1_{sink,source}_base.{h,cc}: added serial_number() + +2006-01-30 Eric Blossom + + * src/db_base.py, src/db_flexrf.py: revised to use new auto t/r + switching strategy. FR_ATR_CTL no longer exists. We control auto + t/r via the FR_ATR_MASK* registers. + +2006-01-25 Eric Blossom + + * src/usrp.py (usrp_common): added code to read FPGA capability register. + (determine_tx_mux_value): new utility. + +2006-01-22 Eric Blossom + + * src/usrp.py (pick_rx_subdevice): added latest d'board revs to list. + +2006-01-04 Eric Blossom + + * src/usrp1_{sink,source}_{s,c}.cc: added usrp_bytesex.h include and + use usrp_to_host_short or host_to_usrp_short as appropriate to + handle usrp to host endianness differences. + + * configure.ac: added AC_C_BIGENDIAN and header check for byteswap.h + +2005-12-20 Matt Ettus + + * src/db_base.py (db_base.spectrum_inverted): Base function + defaults to no spectrum inversion, so we can handle daughterboards + which have analog spectra which are inverted (currently only tvrx2) + + * src/db_tv_rx.py (db_tv_rx.spectrum_inverted): Report that the + tvrx2 has inverted spectrum, the tvrx does not + + * src/usrp.py (tune): Handle daughterboards which have analog + spectra which are inverted (currently only tvrx2) + + +2005-12-08 Eric Blossom + + * src/usrp1_sink_s.cc (usrp1_sink_s): call set_output_multiple so + we ensure 512 byte writes across USB. + +2005-12-07 Eric Blossom + + * src/usrp.py: revised sink_c, sink_s, source_c and source_s to + properly fire daughterboard destructors. Without this, we had the + nasty habit of leaving the transmitter running if the user didn't + explicitly disable it. + +2005-12-05 Eric Blossom + + * src/db_base.py, src/db_flexrf.py: refactored to use new + Auto T/R switching. + + * src/db_flexrf.py (flexrf_base.set_freq): Offset the LO by 4 MHz. + Helps initial lock-up time with discontinuous transmission. + +2005-11-22 Eric Blossom + + * src/db_base.py, src/db_flexrf.py: renamed set_auto_tx to set_auto_tr. + +2005-11-17 Eric Blossom + + * src/usrp1_sink_base.cc: reduced amount of USB Tx buffering. + +2005-11-13 Eric Blossom + + * src/db_base.py (db_base.set_auto_tx): new stub method. + +2005-11-11 Eric Blossom + + * src/usrp.py (pick_rx_subdevice): moved to library. + +2005-11-10 Matt Ettus + + * src/db_flexrf.py (flexrf_base_tx.set_enable): fixed definition. + +2005-10-27 Eric Blossom + + * src/db_base.py, src/db_flexrf.py: new method: set_enable + +2005-10-20 Eric Blossom + + * src/usrp1_source_s.{h,cc}, src/usrp1_source_c.{h,cc}: support + both 8 and 16-bit samples across the USB. + * src/usrp1.i, src/usrp1_source_base.{h,cc}: new methods for + setting and getting rx format. + +2005-10-11 Eric Blossom + + * src/usrp.py: removed dispatch on usrp revision (no longer + support rev0 boards). Constructors now take keyword args, thus + all args are optional. This will allow us to get rid of the 64e6's + and 128e6's that are scattered throughout the example code. + * src/usrp1.i: removed default values from constructors. They are + now provided by keyword args in usrp.py + +2005-09-29 Eric Blossom + + * src/db_dbs_rx.py (db_dbs_rx.freq_range): set freq step size to 1M + +2005-09-27 Eric Blossom + + * src/db_base.py (db_base.i_and_q_swapped): new method for + Flex 400 Rx and other boards that route I into ADC 1 instead of 0. + + * src/usrp.py (tune): added tune fct. Reworked subdev_spec. No + longer accepts (0|1, None). Check for and handle i_and_q_swapped. + +2005-09-21 Eric Blossom + + * src/db_basic.py: new. + * src/db_instantiator.py, src/usrp.py: added framework for + automatically instantiating daughterboard subclasses. + + * src/usrp1.i, src/usrp1_sink_base.{h,cc}, + src/usrp1_source_base.{h,cc}: deprecated adc_freq(), dac_freq(), + recommend converter_rate(). + +2005-09-17 Eric Blossom + + * src/db_dbs_rx.py: renamed from dbs_rx.py + * src/db_flexrf.py: renamed from flexrf.py + * src/db_tv_rx.py: renamed from tv_rx.py + * src/db_base.py: renamed from daughterboard_base.py + +2005-08-28 Eric Blossom + + * src/flexrf.py: added hook to invoke debugging gui. + * src/flexrf_debug_gui.py: new debugging tool. + +2005-07-19 Eric Blossom + + * src/usrp1_source_base.{h,cc}, src/usrp1.i: new method: set_ddc_phase. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + +2005-06-09 Eric Blossom + + * src/gen_usrp_dbids.py: new. Generate usrp_dbids.py from + usrp_daughterboards.h. This file contains symbolic names for for + daughterboard ID's. + +2005-05-18 Eric Blossom + + * src/usrp1_sink_base.{h,cc}, src/usrp1_source_base.{h,cc}: use + new start/stop methods. + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-03-29 Eric Blossom + + * src/usrp.py: now check for usrp version at open time, not import + time. + +2005-03-15 Eric Blossom + + * src/usrp1_sink_base.{h,cc}, src/usrp1_source_base.{h,cc}: + read_aux_dac and write_aux_dac now take which_dboard instead of slot. + +2005-03-13 Matt Ettus + + * src/Makefile.am, src/tv_rx.py: first cut at TV RX dboard + * src/dbs_rx.py: minor fixes + +2005-03-11 Eric Blossom + + * src/usrp1_sink_base.{h,cc},src/usrp1_source_base.{h,cc}: new + methods: set_adc_offset, set_dac_offset, set_adc_buffer_bypass. + +2005-02-18 Eric Blossom + + * src/usrp1_sink_base.cc (_write_oe): fix delegation. + * src/usrp1_source_base.cc (_write_oe): fix delegation. + +2005-02-16 Eric Blossom + + * src/dbs_rx.py: new. control DBS_RX daughterboard. + * src/usrp1_{sink,source}_base.{h,cc}: add read_i2c and write_i2c. + +2005-02-06 Eric Blossom + + * configure.ac: upped rev to 0.4 for release. + * src/Makefile.am: backed out dependency on libpython + +2005-01-28 Stephane Fillod + + * src/Makefile.am: fixes for MinGW. + +2005-01-12 Eric Blossom + + * src/usrp1_sink_base.cc,src/usrp1_source_base.cc: changed + under/overrun diagnostic indicator to "uU" and "uO" to reduce + amount of diagnostic output. + +2005-01-10 Eric Blossom + + * src/usrp1.i,src/usrp1_sink_base.{h,cc}, + src/usrp1_source_base.{h,cc}: new methods to control all knobs. + +2005-01-04 Eric Blossom + + * src/usrp1.i,src/usrp1_source_base.{h,cc}: new methods for + messing with Rx PGA. + +2004-11-14 Eric Blossom + + * src/usrp1_sink_base.cc (work): corrected increment of obi. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 0.2cvs + +2004-10-11 Eric Blossom + + * configure.ac: bumped rev to 0.2, make release. + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-09-30 Eric Blossom + + * src/usrp1_sink_base.{h,cc}, src/usrp1_source_base.{h,cc}, + src/usrp1.i: new methods for reading and writing aux dac and adc, + eeproms, and fpga registers. + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-08-19 Eric Blossom + + * src/usrp1_{sink,source}_base.{h,cc}, src/usrp1.i: new method: set_verbose. + +2004-08-03 Eric Blossom + + * src/usrp1_source_base.{h,cc}, src/usrp1_sink_base.{h,cc}: + extracted base class that handles everything but the packing and + unpacking of data into the usrp buffer. + * src/usrp1_source_c.{h,cc}, src/usrp1_sink_c.{h,cc}: revised to + use new base class. + * src/usrp1_source_s.{h,cc}, src/usrp1_sink_s.{h,cc}: new. + + +2004-07-31 Eric Blossom + + * src/usrp1_{sink,source}_c.{h,cc}: new method: set_loopback + * src/usrp1.i: new method: set_loopback + +2004-07-30 Eric Blossom + + * src/usrp1_source_c.{h,cc}: renamed from usrp_source_c.{h,cc} + * src/usrp1_sink_c.{h,cc}: renamed from usrp_sink_c.{h,cc} + * src/usrp1.i: renamed from usrp.i + * src/usrp.py: new. Binds proper class depending on hardware found. + + +2004-07-29 Eric Blossom + + * src/usrp_{sink,source}_c.h: doc fix. + * src/usrp0.i: new + * src/usrp0_source_c.{h,cc}: new + * src/usrp0_sink_c.{h,cc}: new + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 0.1cvs + +2004-07-08 Eric Blossom + + * src/usrp_source_c.{h,cc}: new. + +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-usrp/Makefile.am b/gr-usrp/Makefile.am new file mode 100644 index 00000000..e500700c --- /dev/null +++ b/gr-usrp/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = README_MULTI_USRP.txt +SUBDIRS = src diff --git a/gr-usrp/README_MULTI_USRP.txt b/gr-usrp/README_MULTI_USRP.txt new file mode 100644 index 00000000..4ed7a15b --- /dev/null +++ b/gr-usrp/README_MULTI_USRP.txt @@ -0,0 +1,251 @@ +Multi usrp + +With this code you can connect two or more usrps (with a locked clock) and get synchronised samples. +You must connect a (flat)cable between a dboard on the master in RXA and a dboard on the slave in RXA. +You then put one usrp in master mode, put the other in slave mode. + +For a quick start using the examples look at gnuradio-examples/python/multi_usrp/README + +Use the usrp_multi block which is installed by gr-usrp. +instantiate in the following way: + + self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, nchan=options.nchan ) + +nchan should be 2 or 4. + +You determine which is the master by master_serialno (this is a text string a hexadecimal number). +If you enter a serial number which is not found it will print the serial numbers which are available. +If you give no serial number (master_serialno=None), the code will pick a Master for you. + +You can get a reference to the master and the slave usrp in the following way: + + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + +You only need these references for setting freqs/gains or getting info about daughterboards. +Don't use the output directly but use the aligned output from multi.get_master_source_c() and multi.get_slave_source_c() + +You get references to the aligned output samples in the following way: +aligned_master_source_c=self.multi.get_master_source_c() +aligned_slave_source_c=self.multi.get_slave_source_c() + +These blocks have multiple outputs. +output 0 is the sample counter (high bits in I, low bits in Q) +You normally don't need the samplecounters so you can ignore output 0 + +output 1 is the first aligend output channel (if you enable 2 or 4 channels) +output 2 is the second output channel (only if you enable 4 channels) + +so the usefull 4 channels are: +self.aligned_master_chan1=(self.multi.get_master_source_c(),1) +self.aligned_master_chan2=(self.multi.get_master_source_c(),2) +self.aligned_slave_chan1=(self.multi.get_slave_source_c(),1) +self.aligned_slave_chan2=(self.multi.get_slave_source_c(),2) + +The two samplecounters are: +self.aligned_master_samplecounter=(self.multi.get_master_source_c(),0) +self.aligned_slave_samplecounter=(self.multi.get_slave_source_c(),0) + +You can set the gain or tune the frequency for all 4 receive daughetrboards at once: + self.multi.set_gain_all_rx(options.gain) + result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq) + +This will only work reliably when you have all the same daughterboards. +Otherwise set all freqs and gains individually. + +You must call self.multi.sync() at least once AFTER the flowgraph has started running. +(This will synchronise the streams of the two usrps) + +This work was funded by Toby Oliver at Sensus Analytics / Path Intelligence. +Many Thanks for making this possible. + +It was written by Martin Dudok van Heel at Olifantasia. + +Quick start multi-usrp: +Unpack, build and install usrp, gnuradio-core and gr-usrp +Versions need to be more recent then 2.7cvs/svn 11 may 2006 + +Make sure usrp/fpga/rbf/rev2/multi*.rbf is installed in /usr/local/share/usrp/rev2/ +Make sure usrp/fpga/rbf/rev4/multi*.rbf is installed in /usr/local/share/usrp/rev4/ +(If in doubt, copy manually) + +build and install gr-wxgui gr-audio-xxx and so on. + +unpack gnuradio-examples. + +There is a gnuradio-examples/python/multi_usrp directory which contains examples and a README + + +Put at least a basic RX or dbsrx board in RXA of the master and RXA of the slave board. +Make sure that the usrps have a serial or unique identifier programmed in their eeprom. +(All new rev 4.1 boards have this) +You can do without a serial but then you never know which usrp is the master and which is the slave. + + +CONNECTING THE CABLES +Now connect the 64MHz clocks between the boards with a short sma coax cable. +(See the wiki on how to enable clock-out and clock-in +http://comsec.com/wiki?USRPClockingNotes ) + +You need one board with a clock out and one board with a clock in. + +You can choose any of the two boards as master or slave, this is not dependant on which board has the clock-out or in. +In my experiments I had fewer problems when the board that has the clock-in will be the master board. + +You can use a standard 16-pole flatcable to connect tvrx, basic-rx or dbsrx boards. +Of this 16pin flatcable only two pins are used (io15 and ground) +For all new daughterboards which use up a lot of io pins you have to use a cable with fewer connections. +The savest is using a 2pin headercable connected to io15,gnd (a cable like the ones used to connect frontpanel leds to the mainboard of a PC) + +If using basic rx board: + Connect a 16-pole flatcable from J25 on basicrx/dbs_rx in rxa of the master usrp to J25 on basicrx/dbsrx in RXA of the slave usrp + Don't twist the cable (Make sure the pin1 marker (red line on the flatcable) is on the same side of the connector (at io-8 on the master and at io8 on the slave.)) + For basic_rx this means the marker should be on the side of the dboard with the sma connectors. + For dbs_rx this means the marker should be on the side of the dboard with the two little chips. + In other words, don't twist the cable, you will burn your board if you do. + +You can also connect a flatcable with multiple connectors from master-J25 to slave1-J25 to slave2-J25 to ... +You will however have to think of something to create a common 64Mhz clock for more then two usrps. + +For all other daughterboards, connect a 2wire cable from masterRXA J25 io15,gnd to slaveRXA J25 io15,gnd + + +So now the hardware is setup, software is setup. Lets do some tests. + +Connect power to both usrps. +unpack the gnuradio_examples somewhere (cvs version later then 11 may 2006) +go to the gnuradio-examples/python/multi_usrp folder. + +Now run + ./multi_usrp_oscope.py -x 12345678 + +It should tell you that usrp 12345678 is not found and tell you which serials are available. + +Now run ./multi_usrp_oscope.py -x actualserialnum +You should now get an oscope with two channels, one is from the master and one is from the slave +It will which show the I-signal from channel 0 of the master usrp and I-signal from channel 0 of the slave usrp. +(For testing connect the same signal source to the inputs of both boards) +The signals should be aligned. +If you click the sync button, it will resync the master and slave (should never be needed) + +Now run +./multi_usrp_oscope.py --help +To see all available options. + + +Now you are ready to do phase-locked aligned signal processing. + +You can also capture to file with: +./multi_usrp_rx_cfile.py + +run ./multi_usrp_rx_cfile.py --help to see all available options. + + +Here follows a brief of the new blocks and (changes)functionality for multi-usrp. +You can also look at the generated documentation in +/usr/local/share/doc/gnuradio-core-X.X +/usr/local/share/doc/usrp-X.X +(Make sure to build and install the documentation, go to the doc directory of the sourcetree and issue make doc; make install) + + +gnuradio-examples: +new/changed files: +multi_usrp/multi_usrp_oscope.py +multi_usrp/multi_usrp_rx_cfile.py + + +gnuradio-core: +gr.align_on_samplenumbers_ss (int nchan,int align_interval) + +align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values) + +Parameters: + nchan number of complex_short input channels (including the 32 bit counting channel) + align_interval interval at which the samples are aligned, ignored for now. + +Pay attention on how you connect this block It expects a minimum of 2 usrp_source_s with nchan number of channels and as mode usrp_prims.bmFR_MODE_RX_COUNTING_32BIT enabled. This means that the first complex_short channel is an interleaved 32 bit counter. The samples are aligned by dropping samples untill the samplenumbers match. + +files: +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i + + +gr-usrp + added _write_fpga_reg_masked + added usrp_multi.py + new usrp_multi block which can instantiate two linked usrps as master and slave and alignes their output. + It has a sync() function which should be called AFTER the flowgraph has started running. + bool sync(); + \brief Call this on a master usrp to sync master and slave by outputing a sync pulse on rx_a_io[15]. + The 32 bit samplecounter of master and slave will be reset to zero and all phase and buffer related things in the usrps are reset. + Call this only after the flowgraph has been started, otherwise there will be no effect since everything is kept in reset state as long as the flowgraph is not running. + \returns true if successfull. + +files: +configure.ac +src/Makefile.am +src/usrp1.i +src/usrp1_source_base.cc +src/usrp1_source_base.h +src/usrp_multi.py + +usrp-0.11cvsmulti: +usrp: + new constant bmFR_MODE_RX_COUNTING_32BIT (could also be added as extra mode like FPGA_MODE_COUNTING_32BIT) + Use this for the mode parameter when creating a usrp when you want to use the master/slave setup or if you want to use the 32 bit counter for other things, like testing with gr.check_counting_s(True) + + added register FR_RX_MASTER_SLAVE + added bitno and bitmaskes: + bmFR_MODE_RX_COUNTING_32BIT + + bitnoFR_RX_SYNC + bitnoFR_RX_SYNC_MASTER + bitnoFR_RX_SYNC_SLAVE + + bitnoFR_RX_SYNC_INPUT_IOPIN 15 + bmFR_RX_SYNC_INPUT_IOPIN (1<>8)) + if regno == 1: + self._write_reg(1,self.n & 255) + if regno == 2: + self._write_reg(2,self.osc + (self.cp<<3) + (self.r_int<<5)) + if regno == 3: + self._write_reg(3,self.fdac) + if regno == 4: + self._write_reg(4,self.m + (self.dl<<5) + (self.ade<<6) + (self.adl<<7)) + if regno == 5: + self._write_reg(5,self.gc2 + (self.diag<<5)) + + # BW setting + def _set_m(self,m): + assert m>0 and m<32 + self.m = m + self._send_reg(4) + + def _set_fdac(self,fdac): + assert fdac>=0 and fdac<128 + self.fdac = fdac + self._send_reg(3) + + def set_bw (self, bw): + #assert (bw>=4e6 and bw<=33e6) + assert (bw>=1e6 and bw<=33e6) + if bw >= 4e6: + m_max = int(min(31,math.floor(self._refclk_freq()/1e6))) + elif bw >= 2e6: # Outside of Specs! + m_max = int(min(31,math.floor(self._refclk_freq()/.5e6))) + else: # Way outside of Specs! + m_max = int(min(31,math.floor(self._refclk_freq()/.25e6))) + + m_min = int(math.ceil(self._refclk_freq()/2.5e6)) + m_test = m_max + while m_test >= m_min: + fdac_test = int(round(((bw * m_test / self._refclk_freq())-4)/.145)) + if fdac_test>127: + m_test = m_test - 1 + else: + break + if (m_test>=m_min and fdac_test >=0): + self._set_m(m_test) + self._set_fdac(fdac_test) + return (self.m,self.fdac,self._refclk_freq()/self.m*(4+0.145*self.fdac)) + else: + print "Failed to set bw" + + # Gain setting + def _set_dl(self,dl): + assert dl == 0 or dl == 1 + self.dl = dl + self._send_reg(4) + + def _set_gc2(self,gc2): + assert gc2<32 and gc2>=0 + self.gc2 = gc2 + self._send_reg(5) + + def _set_gc1(self,gc1): + assert gc1>=0 and gc1<4096 + self.gc1 = gc1 + self._u.write_aux_dac(self._which,0,int(gc1)) + + def _set_pga(self, pga_gain): + assert pga_gain >=0 and pga_gain <=20 + if(self._which == 0): + self._u.set_pga (0, pga_gain) + self._u.set_pga (1, pga_gain) + else: + self._u.set_pga (2, pga_gain) + self._u.set_pga (3, pga_gain) + + def gain_range(self): + return (0, 104, 1) + + def set_gain(self,gain): + if not (gain>=0 and gain<105): + raise ValueError, "gain out of range" + gc1 = 0 + gc2 = 0 + dl = 0 + pga = 0 + if gain <56: + gc1 = int((-gain*1.85/56.0 + 2.6)*4096.0/3.3) + gain = 0 + else: + gc1 = 0 + gain = gain - 56 + if gain < 24: + gc2 = int(round(31.0 * (1-gain/24.0))) + gain = 0 + else: + gc2 = 0 + gain = gain - 24 + if gain >= 4.58: + dl = 1 + gain = gain - 4.58 + pga = gain + self._set_gc1(gc1) + self._set_gc2(gc2) + self._set_dl(dl) + self._set_pga(pga) + + # Frequency setting + def _set_osc(self,osc): + assert osc>=0 and osc<8 + self.osc = osc + self._send_reg(2) + + def _set_cp(self,cp): + assert cp>=0 and cp<4 + self.cp = cp + self._send_reg(2) + + def _set_n(self,n): + assert n>256 and n<32768 + self.n = n + self._send_reg(0) + self._send_reg(1) + + def _set_div2(self,div2): + assert div2 == 0 or div2 == 1 + self.div2 = div2 + self._send_reg(0) + + def _set_r(self,r): + assert r>=0 and r<128 + self.r = r + self.r_int = int(round(math.log10(r)/math.log10(2)) - 1) + self._send_reg(2) + + # FIXME How do we handle ADE and ADL properly? + def _set_ade(self,ade): + assert ade == 0 or ade == 1 + self.ade = ade + self._send_reg(4) + + def freq_range(self): + return (500e6, 2.6e9, 1e6) + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + + def set_freq(self, freq): + """ + Set the frequency. + + @param freq: target frequency in Hz + @type freq: float + + @returns (ok, actual_baseband_freq) where: + ok is True or False and indicates success or failure, + actual_baseband_freq is the RF frequency that corresponds to DC in the IF. + """ + if not (freq>=500e6 and freq<=2.6e9): + return (False, 0) + + if(freq<1150e6): + self._set_div2(0) + vcofreq = 4 * freq + else: + self._set_div2(1) + vcofreq = 2 * freq + self._set_ade(1) + rmin=max(2,self._refclk_freq()/2e6) + rmax=min(128,self._refclk_freq()/150e3) + r = 2 + n=0 + best_r = 2 + best_n =0 + best_delta = 10e6 + while r <= rmax: + n = round(freq/(self._refclk_freq()/r)) + if r> 2 + if(adc_val == 0): + if vco <= 0: + return (False, 0) + else: + vco = vco - 1 + elif(adc_val == 7): + if(vco >= 7): + return (False, 0) + else: + vco = vco + 1 + self._set_osc(vco) + if adc_val == 1 or adc_val == 2: + self._set_cp(1) + elif adc_val == 3 or adc_val == 4: + self._set_cp(2) + else: + self._set_cp(3) + + return (True, self.n * self._refclk_freq() / self.r) + + def is_quadrature(self): + """ + Return True if this board requires both I & Q analog channels. + + This bit of info is useful when setting up the USRP Rx mux register. + """ + return True + +# hook this daughterboard class into the auto-instantiation framework +db_instantiator.add(usrp_dbid.DBS_RX, lambda usrp, which : (db_dbs_rx(usrp, which),)) diff --git a/gr-usrp/src/db_flexrf.py b/gr-usrp/src/db_flexrf.py new file mode 100644 index 00000000..a00cfe89 --- /dev/null +++ b/gr-usrp/src/db_flexrf.py @@ -0,0 +1,680 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import usrp1 +import time,math + +import usrp_dbid +import db_base +import db_instantiator +from usrp_fpga_regs import * + +#debug_using_gui = True # Must be set to True or False +debug_using_gui = False # Must be set to True or False + +if debug_using_gui: + import flexrf_debug_gui + +# d'board i/o pin defs +# Tx and Rx have shared defs, but different i/o regs +AUX_RXAGC = (1 << 8) +POWER_UP = (1 << 7) # enables power supply +RX_TXN = (1 << 6) # Tx only: T/R antenna switch for TX/RX port +RX2_RX1N = (1 << 6) # Rx only: antenna switch between RX2 and TX/RX port +ENABLE = (1 << 5) # enables mixer +AUX_SEN = (1 << 4) +AUX_SCLK = (1 << 3) +PLL_LOCK_DETECT = (1 << 2) +AUX_SDO = (1 << 1) +CLOCK_OUT = (1 << 0) + +SPI_ENABLE_TX_A = usrp1.SPI_ENABLE_TX_A +SPI_ENABLE_TX_B = usrp1.SPI_ENABLE_TX_B +SPI_ENABLE_RX_A = usrp1.SPI_ENABLE_RX_A +SPI_ENABLE_RX_B = usrp1.SPI_ENABLE_RX_B + +class flexrf_base(db_base.db_base): + """ + Abstract base class for all flexrf boards. + + Derive board specific subclasses from db_flexrf_base_{tx,rx} + """ + def __init__(self, usrp, which): + """ + @param usrp: instance of usrp.source_c + @param which: which side: 0 or 1 corresponding to side A or B respectively + @type which: int + """ + # sets _u _which _tx and _slot + db_base.db_base.__init__(self, usrp, which) + + self.first = True + self.spi_format = usrp1.SPI_FMT_MSB | usrp1.SPI_FMT_HDR_0 + + self._u._write_oe(self._which, 0, 0xffff) # turn off all outputs + self._enable_refclk(False) # disable refclk + + g = self.gain_range() # initialize gain + self.set_gain(float(g[0]+g[1]) / 2) + + self.set_auto_tr(False) + + if debug_using_gui: + title = "FlexRF Debug Rx" + if self._tx: + title = "FlexRF Debug Tx" + self.gui = flexrf_debug_gui.flexrf_debug_gui(self, title) + self.gui.Show(True) + + + def __del__(self): + #print "flexrf_base.__del__" + self._u.write_io(self._which, self.power_off, POWER_UP) # turn off power to board + self._enable_refclk(False) # turn off refclk + self.set_auto_tr(False) + + def _write_all(self, R, control, N): + """ + Write R counter latch, control latch and N counter latch to VCO. + + Adds 10ms delay between writing control and N if this is first call. + This is the required power-up sequence. + + @param $: 24-bit R counter latch + @type R: int + @param control: 24-bit control latch + @type control: int + @param N: 24-bit N counter latch + @type N: int + """ + self._write_R(R) + self._write_control( control) + if self.first: + time.sleep(0.010) + self.first = False + self._write_N(N) + + def _write_control(self, control): + self._write_it((control & ~0x3) | 0) + + def _write_R(self, R): + self._write_it((R & ~0x3) | 1) + + def _write_N(self, N): + self._write_it((N & ~0x3) | 2) + + def _write_it(self, v): + s = ''.join((chr((v >> 16) & 0xff), + chr((v >> 8) & 0xff), + chr(v & 0xff))) + self._u._write_spi(0, self.spi_enable, self.spi_format, s) + + def _lock_detect(self): + """ + @returns: the value of the VCO/PLL lock detect bit. + @rtype: 0 or 1 + """ + if self._u.read_io(self._which) & PLL_LOCK_DETECT: + return True + else: # Give it a second chance + if self._u.read_io(self._which) & PLL_LOCK_DETECT: + return True + else: + return False + + def _compute_regs(self, freq): + """ + Determine values of R, control, and N registers, along with actual freq. + + @param freq: target frequency in Hz + @type freq: float + @returns: (R, control, N, actual_freq) + @rtype: tuple(int, int, int, float) + + Override this in derived classes. + """ + raise NotImplementedError + + def _refclk_freq(self): + # return float(self._u.fpga_master_clock_freq())/self._refclk_divisor() + return 64e6/self._refclk_divisor() + + def set_freq(self, freq): + """ + @returns (ok, actual_baseband_freq) where: + ok is True or False and indicates success or failure, + actual_baseband_freq is the RF frequency that corresponds to DC in the IF. + """ + + # Offsetting the LO helps get the Tx carrier leakage out of the way. + # This also ensures that on Rx, we're not getting hosed by the + # FPGA's DC removal loop's time constant. We were seeing a + # problem when running with discontinuous transmission. + # Offsetting the LO made the problem go away. + freq += self.lo_offset + + R, control, N, actual_freq = self._compute_regs(freq) + if R==0: + return(False,0) + self._write_all(R, control, N) + return (self._lock_detect(), actual_freq) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + """ + return (self._u.pga_min(), self._u.pga_max(), self._u.pga_db_per_step()) + + def set_gain(self, gain): + """ + Set the gain. + + @param gain: gain in decibels + @returns True/False + """ + return self._set_pga(gain) + + def _set_pga(self, pga_gain): + if(self._which == 0): + self._u.set_pga (0, pga_gain) + self._u.set_pga (1, pga_gain) + else: + self._u.set_pga (2, pga_gain) + self._u.set_pga (3, pga_gain) + + def is_quadrature(self): + """ + Return True if this board requires both I & Q analog channels. + + This bit of info is useful when setting up the USRP Rx mux register. + """ + return True + +# ---------------------------------------------------------------- + +class flexrf_base_tx(flexrf_base): + def __init__(self, usrp, which): + """ + @param usrp: instance of usrp.sink_c + @param which: 0 or 1 corresponding to side TX_A or TX_B respectively. + """ + flexrf_base.__init__(self, usrp, which) + self.spi_enable = (SPI_ENABLE_TX_A, SPI_ENABLE_TX_B)[which] + + # power up the transmit side, but don't enable the mixer + self._u._write_oe(self._which,(POWER_UP|RX_TXN|ENABLE), 0xffff) + self._u.write_io(self._which, (self.power_on|RX_TXN), (POWER_UP|RX_TXN|ENABLE)) + self.lo_offset = 4e6 # FIXME may want to be a function of d'board + + def __del__(self): + #print "flexrf_base_tx.__del__" + # Power down and leave the T/R switch in the R position + self._u.write_io(self._which, (self.power_off|RX_TXN), (POWER_UP|RX_TXN|ENABLE)) + flexrf_base.__del__(self) + + def set_auto_tr(self, on): + if on: + self.set_atr_mask (RX_TXN | ENABLE) + self.set_atr_txval(0 | ENABLE) + self.set_atr_rxval(RX_TXN | 0) + else: + self.set_atr_mask (0) + self.set_atr_txval(0) + self.set_atr_rxval(0) + + def set_enable(self, on): + """ + Enable transmitter if on is True + """ + mask = RX_TXN | ENABLE + if on: + v = ENABLE + else: + v = RX_TXN + self._u.write_io(self._which, v, mask) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + + Flex Tx boards require that the PGA be maxed out to properly bias their circuitry. + """ + g = self._u.pga_max() + return (g, g, 1.0) + + def set_gain(self, gain): + """ + Set the gain. + + @param gain: gain in decibels + @returns True/False + """ + return self._set_pga(self._u.pga_max()) + + +class flexrf_base_rx(flexrf_base): + def __init__(self, usrp, which): + """ + @param usrp: instance of usrp.source_c + @param which: 0 or 1 corresponding to side RX_A or RX_B respectively. + """ + flexrf_base.__init__(self, usrp, which) + self.spi_enable = (SPI_ENABLE_RX_A, SPI_ENABLE_RX_B)[which] + + self._u._write_oe(self._which, (POWER_UP|RX2_RX1N|ENABLE), 0xffff) + self._u.write_io(self._which, (self.power_on|RX2_RX1N|ENABLE), (POWER_UP|RX2_RX1N|ENABLE)) + + # set up for RX on TX/RX port + self.select_rx_antenna('TX/RX') + + self.bypass_adc_buffers(True) + + self.lo_offset = -4e6 # FIXME may want to be a function of d'board + + def __del__(self): + # print "flexrf_base_rx.__del__" + # Power down + self._u.write_io(self._which, self.power_off, (POWER_UP|ENABLE)) + flexrf_base.__del__(self) + + def set_auto_tr(self, on): + if on: + self.set_atr_mask (ENABLE) + self.set_atr_txval( 0) + self.set_atr_rxval(ENABLE) + else: + self.set_atr_mask (0) + self.set_atr_txval(0) + self.set_atr_rxval(0) + + def select_rx_antenna(self, which_antenna): + """ + Specify which antenna port to use for reception. + @param which_antenna: either 'TX/RX' or 'RX2' + """ + if which_antenna in (0, 'TX/RX'): + self._u.write_io(self._which, 0, RX2_RX1N) + elif which_antenna in (1, 'RX2'): + self._u.write_io(self._which, RX2_RX1N, RX2_RX1N) + else: + raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'" + + def set_gain(self, gain): + """ + Set the gain. + + @param gain: gain in decibels + @returns True/False + """ + maxgain = self.gain_range()[1] - self._u.pga_max() + if gain > maxgain: + pga_gain = gain-maxgain + assert pga_gain <= self._u.pga_max() + agc_gain = maxgain + else: + pga_gain = 0 + agc_gain = gain + V_maxgain = .2 + V_mingain = 1.2 + V_fullscale = 3.3 + dac_value = (agc_gain*(V_maxgain-V_mingain)/maxgain + V_mingain)*4096/V_fullscale + assert dac_value>=0 and dac_value<4096 + return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \ + self._set_pga(int(pga_gain)) + + +# ---------------------------------------------------------------- + +class _AD4360_common(object): + def __init__(self): + # R-Register Common Values + self.R_RSV = 0 # bits 23,22 + self.BSC = 3 # bits 21,20 Div by 8 to be safe + self.TEST = 0 # bit 19 + self.LDP = 1 # bit 18 + self.ABP = 0 # bit 17,16 3ns + + # N-Register Common Values + self.N_RSV = 0 # bit 7 + + # Control Register Common Values + self.PD = 0 # bits 21,20 Normal operation + self.PL = 0 # bits 13,12 11mA + self.MTLD = 1 # bit 11 enabled + self.CPG = 0 # bit 10 CP setting 1 + self.CP3S = 0 # bit 9 Normal + self.PDP = 1 # bit 8 Positive + self.MUXOUT = 1 # bits 7:5 Digital Lock Detect + self.CR = 0 # bit 4 Normal + self.PC = 1 # bits 3,2 Core power 10mA + + def _compute_regs(self, freq): + """ + Determine values of R, control, and N registers, along with actual freq. + + @param freq: target frequency in Hz + @type freq: float + @returns: (R, control, N, actual_freq) + @rtype: tuple(int, int, int, float) + """ + + # Band-specific N-Register Values + phdet_freq = self._refclk_freq()/self.R_DIV + desired_n = round(freq*self.freq_mult/phdet_freq) + actual_freq = desired_n * phdet_freq + B = math.floor(desired_n/self._prescaler()) + A = desired_n - self._prescaler()*B + self.B_DIV = int(B) # bits 20:8 + self.A_DIV = int(A) # bit 6:2 + #assert self.B_DIV >= self.A_DIV + if self.B_DIV < self.A_DIV: + return (0,0,0,0) + R = (self.R_RSV<<22) | (self.BSC<<20) | (self.TEST<<19) | (self.LDP<<18) \ + | (self.ABP<<16) | (self.R_DIV<<2) + + control = (self.P<<22) | (self.PD<<20) | (self.CP2<<17) | (self.CP1<<14) | (self.PL<<12) \ + | (self.MTLD<<11) | (self.CPG<<10) | (self.CP3S<<9) | (self.PDP<<8) | \ + (self.MUXOUT<<5) | (self.CR<<4) | (self.PC<<2) + + N = (self.DIVSEL<<23) | (self.DIV2<<22) | (self.CPGAIN<<21) | (self.B_DIV<<8) | \ + (self.N_RSV<<7) | (self.A_DIV<<2) + + return (R,control,N,actual_freq/self.freq_mult) + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + + def _prescaler(self): + if self.P == 0: + return 8 + elif self.P == 1: + return 16 + else: + return 32 + +#---------------------------------------------------------------------- +class _2400_common(_AD4360_common): + def __init__(self): + _AD4360_common.__init__(self) + + # Band-specific R-Register Values + self.R_DIV = 16 # bits 15:2 + + # Band-specific C-Register values + self.P = 1 # bits 23,22 Div by 16/17 + self.CP2 = 7 # bits 19:17 + self.CP1 = 7 # bits 16:14 + + # Band specifc N-Register Values + self.DIVSEL = 0 # bit 23 + self.DIV2 = 0 # bit 22 + self.CPGAIN = 0 # bit 21 + self.freq_mult = 1 + + def freq_range(self): # FIXME + return (2300e6, 2700e6, 4e6) + +#---------------------------------------------------------------------- +class _1200_common(_AD4360_common): + def __init__(self): + _AD4360_common.__init__(self) + + # Band-specific R-Register Values + self.R_DIV = 16 # bits 15:2 DIV by 16 for a 1 MHz phase detector freq + + # Band-specific C-Register values + self.P = 1 # bits 23,22 Div by 16/17 + self.CP2 = 7 # bits 19:17 1.25 mA + self.CP1 = 7 # bits 16:14 1.25 mA + + # Band specifc N-Register Values + self.DIVSEL = 0 # bit 23 + self.DIV2 = 1 # bit 22 + self.CPGAIN = 0 # bit 21 + self.freq_mult = 2 + + def freq_range(self): # FIXME + return (1150e6, 1350e6, 4e6) + +#------------------------------------------------------------------------- +class _1800_common(_AD4360_common): + def __init__(self): + _AD4360_common.__init__(self) + + # Band-specific R-Register Values + self.R_DIV = 16 # bits 15:2 DIV by 16 for a 1 MHz phase detector freq + + # Band-specific C-Register values + self.P = 1 # bits 23,22 Div by 16/17 + self.CP2 = 7 # bits 19:17 1.25 mA + self.CP1 = 7 # bits 16:14 1.25 mA + + # Band specifc N-Register Values + self.DIVSEL = 0 # bit 23 + self.DIV2 = 0 # bit 22 + self.freq_mult = 1 + self.CPGAIN = 0 # bit 21 + + def freq_range(self): # FIXME + return (1600e6, 2000e6, 4e6) + +#------------------------------------------------------------------------- +class _900_common(_AD4360_common): + def __init__(self): + _AD4360_common.__init__(self) + + # Band-specific R-Register Values + self.R_DIV = 16 # bits 15:2 DIV by 16 for a 1 MHz phase detector freq + + # Band-specific C-Register values + self.P = 1 # bits 23,22 Div by 16/17 + self.CP2 = 7 # bits 19:17 1.25 mA + self.CP1 = 7 # bits 16:14 1.25 mA + + # Band specifc N-Register Values + self.DIVSEL = 0 # bit 23 + self.DIV2 = 1 # bit 22 + self.freq_mult = 2 + self.CPGAIN = 0 # bit 21 + + def freq_range(self): # FIXME + return (800e6, 1000e6, 4e6) + +#------------------------------------------------------------------------- +class _400_common(_AD4360_common): + def __init__(self): + _AD4360_common.__init__(self) + + # Band-specific R-Register Values + self.R_DIV = 16 # bits 15:2 + + # Band-specific C-Register values + self.P = 0 # bits 23,22 Div by 8/9 + self.CP2 = 7 # bits 19:17 1.25 mA + self.CP1 = 7 # bits 16:14 1.25 mA + + # Band specifc N-Register Values These are different for TX/RX + self.DIVSEL = 0 # bit 23 + if self._tx: + self.DIV2 = 1 # bit 22 + else: + self.DIV2 = 0 # bit 22 # RX side has built-in DIV2 in AD8348 + self.freq_mult = 2 + + self.CPGAIN = 0 # bit 21 + + def freq_range(self): + #return (350e6, 465e6, 1e6) # FIXME prototype + return (400e6, 500e6, 1e6) # final version + + +#------------------------------------------------------------ +class db_flexrf_2400_tx(_2400_common, flexrf_base_tx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_tx.__init__(self, usrp, which) + _2400_common.__init__(self) + +class db_flexrf_2400_rx(_2400_common, flexrf_base_rx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # Powering it off kills the serial bus + flexrf_base_rx.__init__(self, usrp, which) + _2400_common.__init__(self) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + """ + return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) + + def i_and_q_swapped(self): + return True + +class db_flexrf_1200_tx(_1200_common, flexrf_base_tx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_tx.__init__(self, usrp, which) + _1200_common.__init__(self) + +class db_flexrf_1200_rx(_1200_common, flexrf_base_rx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_rx.__init__(self, usrp, which) + _1200_common.__init__(self) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + """ + return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) + + def i_and_q_swapped(self): + return True + +class db_flexrf_1800_tx(_1800_common, flexrf_base_tx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_tx.__init__(self, usrp, which) + _1800_common.__init__(self) + +class db_flexrf_1800_rx(_1800_common, flexrf_base_rx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_rx.__init__(self, usrp, which) + _1800_common.__init__(self) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + """ + return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) + + def i_and_q_swapped(self): + return True + +class db_flexrf_900_tx(_900_common, flexrf_base_tx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_tx.__init__(self, usrp, which) + _900_common.__init__(self) + +class db_flexrf_900_rx(_900_common, flexrf_base_rx): + def __init__(self, usrp, which): + self.power_on = ~POWER_UP + self.power_off = ~POWER_UP # powering it off kills the serial bus + flexrf_base_rx.__init__(self, usrp, which) + _900_common.__init__(self) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + """ + return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) + + def i_and_q_swapped(self): + return True + +class db_flexrf_400_tx(_400_common, flexrf_base_tx): + def __init__(self, usrp, which): + self.power_on = POWER_UP + self.power_off = ~POWER_UP + flexrf_base_tx.__init__(self, usrp, which) + _400_common.__init__(self) + +class db_flexrf_400_rx(_400_common, flexrf_base_rx): + def __init__(self, usrp, which): + self.power_on = POWER_UP + self.power_off = ~POWER_UP + flexrf_base_rx.__init__(self, usrp, which) + _400_common.__init__(self) + + def gain_range(self): + """ + Return range of gain that can be set by this d'board. + + @returns (min_gain, max_gain, step_size) + Where gains are expressed in decibels (your mileage may vary) + """ + return (self._u.pga_min(), self._u.pga_max() + 45, 0.035) + + def i_and_q_swapped(self): + return True + +# hook these daughterboard classes into the auto-instantiation framework + +db_instantiator.add(usrp_dbid.FLEX_2400_TX, lambda usrp, which : (db_flexrf_2400_tx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_2400_RX, lambda usrp, which : (db_flexrf_2400_rx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1200_TX, lambda usrp, which : (db_flexrf_1200_tx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1200_RX, lambda usrp, which : (db_flexrf_1200_rx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1800_TX, lambda usrp, which : (db_flexrf_1800_tx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1800_RX, lambda usrp, which : (db_flexrf_1800_rx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_900_TX, lambda usrp, which : (db_flexrf_900_tx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_900_RX, lambda usrp, which : (db_flexrf_900_rx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_400_TX, lambda usrp, which : (db_flexrf_400_tx(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_400_RX, lambda usrp, which : (db_flexrf_400_rx(usrp, which),)) diff --git a/gr-usrp/src/db_flexrf_mimo.py b/gr-usrp/src/db_flexrf_mimo.py new file mode 100644 index 00000000..71c49a8f --- /dev/null +++ b/gr-usrp/src/db_flexrf_mimo.py @@ -0,0 +1,286 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import usrp1 +import time,math + +import usrp_dbid +import db_base +import db_instantiator +from usrp_fpga_regs import * +from db_flexrf import * + +# self._u.fpga_master_clock_freq() + +# MIMO Classes +class db_flexrf_2400_tx_mimo_a(db_flexrf_2400_tx): + def __init__(self, usrp, which): + db_flexrf_2400_tx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_2400_rx_mimo_a(db_flexrf_2400_rx): + def __init__(self, usrp, which): + db_flexrf_2400_rx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_2400_tx_mimo_b(db_flexrf_2400_tx): + def __init__(self, usrp, which): + db_flexrf_2400_tx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_2400_rx_mimo_b(db_flexrf_2400_rx): + def __init__(self, usrp, which): + db_flexrf_2400_rx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_1800_tx_mimo_a(db_flexrf_1800_tx): + def __init__(self, usrp, which): + db_flexrf_1800_tx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_1800_rx_mimo_a(db_flexrf_1800_rx): + def __init__(self, usrp, which): + db_flexrf_1800_rx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_1800_tx_mimo_b(db_flexrf_1800_tx): + def __init__(self, usrp, which): + db_flexrf_1800_tx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_1800_rx_mimo_b(db_flexrf_1800_rx): + def __init__(self, usrp, which): + db_flexrf_1800_rx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_1200_tx_mimo_a(db_flexrf_1200_tx): + def __init__(self, usrp, which): + db_flexrf_1200_tx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_1200_rx_mimo_a(db_flexrf_1200_rx): + def __init__(self, usrp, which): + db_flexrf_1200_rx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_1200_tx_mimo_b(db_flexrf_1200_tx): + def __init__(self, usrp, which): + db_flexrf_1200_tx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_1200_rx_mimo_b(db_flexrf_1200_rx): + def __init__(self, usrp, which): + db_flexrf_1200_rx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_900_tx_mimo_a(db_flexrf_900_tx): + def __init__(self, usrp, which): + db_flexrf_900_tx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_900_rx_mimo_a(db_flexrf_900_rx): + def __init__(self, usrp, which): + db_flexrf_900_rx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_900_tx_mimo_b(db_flexrf_900_tx): + def __init__(self, usrp, which): + db_flexrf_900_tx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_900_rx_mimo_b(db_flexrf_900_rx): + def __init__(self, usrp, which): + db_flexrf_900_rx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_400_tx_mimo_a(db_flexrf_400_tx): + def __init__(self, usrp, which): + db_flexrf_400_tx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_400_rx_mimo_a(db_flexrf_400_rx): + def __init__(self, usrp, which): + db_flexrf_400_rx.__init__(self, usrp, which) + self._enable_refclk(True) + self.R_DIV = 1 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 16 + +class db_flexrf_400_tx_mimo_b(db_flexrf_400_tx): + def __init__(self, usrp, which): + db_flexrf_400_tx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +class db_flexrf_400_rx_mimo_b(db_flexrf_400_rx): + def __init__(self, usrp, which): + db_flexrf_400_rx.__init__(self, usrp, which) + self.R_DIV = 16 + + def _refclk_divisor(self): + """ + Return value to stick in REFCLK_DIVISOR register + """ + return 1 + +# hook these daughterboard classes into the auto-instantiation framework +db_instantiator.add(usrp_dbid.FLEX_2400_TX_MIMO_A, lambda usrp, which : (db_flexrf_2400_tx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_2400_RX_MIMO_A, lambda usrp, which : (db_flexrf_2400_rx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1800_TX_MIMO_A, lambda usrp, which : (db_flexrf_1800_tx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1800_RX_MIMO_A, lambda usrp, which : (db_flexrf_1800_rx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1200_TX_MIMO_A, lambda usrp, which : (db_flexrf_1200_tx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1200_RX_MIMO_A, lambda usrp, which : (db_flexrf_1200_rx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_900_TX_MIMO_A, lambda usrp, which : (db_flexrf_900_tx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_900_RX_MIMO_A, lambda usrp, which : (db_flexrf_900_rx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_400_TX_MIMO_A, lambda usrp, which : (db_flexrf_400_tx_mimo_a(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_400_RX_MIMO_A, lambda usrp, which : (db_flexrf_400_rx_mimo_a(usrp, which),)) + +db_instantiator.add(usrp_dbid.FLEX_2400_TX_MIMO_B, lambda usrp, which : (db_flexrf_2400_tx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_2400_RX_MIMO_B, lambda usrp, which : (db_flexrf_2400_rx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1800_TX_MIMO_B, lambda usrp, which : (db_flexrf_1800_tx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1800_RX_MIMO_B, lambda usrp, which : (db_flexrf_1800_rx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1200_TX_MIMO_B, lambda usrp, which : (db_flexrf_1200_tx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_1200_RX_MIMO_B, lambda usrp, which : (db_flexrf_1200_rx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_900_TX_MIMO_B, lambda usrp, which : (db_flexrf_900_tx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_900_RX_MIMO_B, lambda usrp, which : (db_flexrf_900_rx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_400_TX_MIMO_B, lambda usrp, which : (db_flexrf_400_tx_mimo_b(usrp, which),)) +db_instantiator.add(usrp_dbid.FLEX_400_RX_MIMO_B, lambda usrp, which : (db_flexrf_400_rx_mimo_b(usrp, which),)) + diff --git a/gr-usrp/src/db_instantiator.py b/gr-usrp/src/db_instantiator.py new file mode 100644 index 00000000..db10de4a --- /dev/null +++ b/gr-usrp/src/db_instantiator.py @@ -0,0 +1,31 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +_instantiator_map = {} + +def add(dbid, instantiator): + _instantiator_map[dbid] = instantiator + +def instantiate(usrp, which): + dbid = usrp.daughterboard_id(which) + if _instantiator_map.has_key(dbid): + return _instantiator_map[dbid](usrp, which) + raise ValueError, "No class defined to handle daughterboard (dbid = %d)" % (dbid,) diff --git a/gr-usrp/src/db_tv_rx.py b/gr-usrp/src/db_tv_rx.py new file mode 100644 index 00000000..05504553 --- /dev/null +++ b/gr-usrp/src/db_tv_rx.py @@ -0,0 +1,198 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +__all__ = ['tv_rx'] + +import math +import usrp_dbid +import db_base +import db_instantiator + +def int_seq_to_str(seq): + """convert a sequence of integers into a string""" + return ''.join (map (chr, seq)) + +def str_to_int_seq(str): + """convert a string to a list of integers""" + return map (ord, str) + +def control_byte_1(fast_tuning_p, reference_divisor): + c = 0x88 + if fast_tuning_p: + c |= 0x40 + if reference_divisor == 512: + c |= 0x3 << 1 + elif reference_divisor == 640: + c |= 0x0 << 1 + elif reference_divisor == 1024: + c |= 0x1 << 1 + else: + assert 0 + return c + +def control_byte_2(target_freq, shutdown_tx_PGA): + if target_freq < 158e6: # VHF low + c = 0xa0 + elif target_freq < 464e6: # VHF high + c = 0x90 + else: # UHF + c = 0x30 + if shutdown_tx_PGA: + c |= 0x08 + return c + +class db_tv_rx(db_base.db_base): + def __init__(self, usrp, which, first_IF, second_IF): + """ + Control Microtune 4937 based USRP daughterboard. + + @param usrp: instance of usrp.source_c + @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively + @type which: int + """ + # sets _u and _which + db_base.db_base.__init__(self, usrp, which) + + self._i2c_addr = (0x60, 0x61)[which] + + self._first_IF = first_IF + self._second_IF = second_IF + self._reference_divisor = 640 + self._fast_tuning = False + self._inverted = False # FIXME get rid of this + + g = self.gain_range() # initialize gain + self.set_gain(float(g[0]+g[1]) / 2) + + self.bypass_adc_buffers(False) + + # Gain setting + def _set_rfagc(self,gain): + assert gain <= 60 and gain >= 0 + # FIXME this has a 0.5V step between gain = 60 and gain = 59. + # Why are there two cases instead of a single linear case? + if gain == 60: + voltage = 4 + else: + voltage = gain/60.0 * 2.25 + 1.25 + dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain + + assert dacword>=0 and dacword<4096 + self._u.write_aux_dac(self._which, 1, dacword) + + def _set_ifagc(self,gain): + assert gain <= 35 and gain >= 0 + voltage = gain/35.0 * 2.1 + 1.4 + dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain + + assert dacword>=0 and dacword<4096 + self._u.write_aux_dac(self._which, 0, dacword) + + def _set_pga(self,pga_gain): + assert pga_gain >=0 and pga_gain <=20 + if(self._which == 0): + self._u.set_pga (0, pga_gain) + else: + self._u.set_pga (2, pga_gain) + + def gain_range(self): + return (0, 115, 1) + + def set_gain(self,gain): + assert gain>=0 and gain<=115 + if gain>60: + rfgain = 60 + gain = gain - 60 + else: + rfgain = gain + gain = 0 + if gain > 35: + ifgain = 35 + gain = gain - 35 + else: + ifgain = gain + gain = 0 + pgagain = gain + self._set_rfagc(rfgain) + self._set_ifagc(ifgain) + self._set_pga(pgagain) + + def freq_range(self): + return (50e6, 860e6, 10e3) + + def set_freq(self, target_freq): + """ + @returns (ok, actual_baseband_freq) where: + ok is True or False and indicates success or failure, + actual_baseband_freq is the RF frequency that corresponds to DC in the IF. + """ + r = self.freq_range() + if target_freq < r[0] or target_freq > r[1]: + return (False, 0) + + target_lo_freq = target_freq + self._first_IF; # High side mixing + f_ref = 4e6 / self._reference_divisor # frequency steps + + divisor = int((target_lo_freq + (f_ref * 4)) / (f_ref * 8)) + actual_lo_freq = (f_ref * 8 * divisor) + actual_freq = actual_lo_freq - self._first_IF; + + if (divisor & ~0x7fff) != 0: # must be 15-bits or less + return (False, 0) + + # build i2c command string + buf = [0] * 4 + buf[0] = (divisor >> 8) & 0xff # DB1 + buf[1] = divisor & 0xff # DB2 + buf[2] = control_byte_1(self._fast_tuning, self._reference_divisor) + buf[3] = control_byte_2(actual_freq, True) + + ok = self._u.write_i2c(self._i2c_addr, int_seq_to_str (buf)) + + return (ok, actual_freq - self._second_IF) + + def is_quadrature(self): + """ + Return True if this board requires both I & Q analog channels. + + This bit of info is useful when setting up the USRP Rx mux register. + """ + return False + + def spectrum_inverted(self): + """ + The 43.75 MHz version is inverted + """ + return self._inverted + +# hook this daughterboard class into the auto-instantiation framework + +# With MT4937DI5-3x7702 with second downconversion +db_instantiator.add(usrp_dbid.TV_RX, + lambda usrp, which : (db_tv_rx(usrp, which, 43.75e6, 5.75e6),)) + +# With MT4937DI5-3x8680, and 3x8769 without second downconversion +db_instantiator.add(usrp_dbid.TV_RX_REV_2, + lambda usrp, which : (db_tv_rx(usrp, which, 44e6, 20e6),)) + +# With MT4937DI5-3x7901 without second downconversion, basically the same as tvrx2 +db_instantiator.add(usrp_dbid.TV_RX_REV_3, + lambda usrp, which : (db_tv_rx(usrp, which, 44e6, 20e6),)) diff --git a/gr-usrp/src/flexrf_debug_gui.py b/gr-usrp/src/flexrf_debug_gui.py new file mode 100755 index 00000000..173d48a7 --- /dev/null +++ b/gr-usrp/src/flexrf_debug_gui.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import sys +import wx +from gnuradio.wxgui import form + +class flexrf_debug_gui(wx.Frame): + def __init__(self, flexrf, title="Flexrf Debug"): + wx.Frame.__init__(self, None, -1, title) + + self.flexrf = flexrf + + self.CreateStatusBar (1) + + self.panel = wx.Panel(self, -1) + self.vbox = wx.BoxSizer(wx.VERTICAL) + self.panel.SetSizer(self.vbox) + self.panel.SetAutoLayout(True) + + self._create_form() + + self.vbox.Fit(self.panel) + + self.frame_vbox = wx.BoxSizer(wx.VERTICAL) + self.frame_vbox.Add(self.panel, 1, wx.EXPAND) + self.SetSizer(self.frame_vbox) + self.SetAutoLayout(True) + self.frame_vbox.Fit(self) + + def _create_form(self): + self._create_set_freq() + self._create_write_fpga() + self._create_write_all() + self._create_write_it() + #self._create_set_gain() + + # ---------------------------------------------------------------- + + def _create_set_freq(self): + + def _set_freq(kv): + return self.flexrf.set_freq(kv['freq'])[0] + + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.HORIZONTAL) + sbs.Add((5,0), 0.1) # stretchy space + #sbs.Add(wx.StaticText(self.panel, -1, "set_freq "), 0, 0) + #sbs.Add((5,0), 0.1) # stretchy space + myform = form.form() + myform['freq'] = form.float_field(self.panel, sbs, "Set Frequency") + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(form.button_with_callback(self.panel, "Do It!", + self._generic_doit(_set_freq, myform)), 1, wx.EXPAND) + sbs.Add((5,0), 0.1) # stretchy space + self.vbox.Add(sbs, 0, wx.EXPAND) + + + def _create_write_fpga(self): + + def _write_fpga(kv): + return self.flexrf._u._write_fpga_reg(kv['regno'], kv['value']) + + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.HORIZONTAL) + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(wx.StaticText(self.panel, -1, "write_fpga_reg "), 0, 0) + sbs.Add((5,0), 0.1) # stretchy space + myform = form.form() + myform['regno'] = form.int_field(self.panel, sbs, "regno") + sbs.Add((5,0), 0.1) # stretchy space + myform['value'] = form.int_field(self.panel, sbs, "value") + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(form.button_with_callback(self.panel, "Do It!", + self._generic_doit(_write_fpga, myform)), 1, wx.EXPAND) + sbs.Add((5,0), 0.1) # stretchy space + self.vbox.Add(sbs, 0, wx.EXPAND) + + + def _create_write_all(self): + + def _write_all(kv): + self.flexrf._write_all(kv['R'], kv['control'], kv['N']) # void + return True + + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.HORIZONTAL) + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(wx.StaticText(self.panel, -1, "write_all "), 0, 0) + sbs.Add((5,0), 0.1) # stretchy space + myform = form.form() + myform['R'] = form.int_field(self.panel, sbs, "R") + sbs.Add((5,0), 0.1) # stretchy space + myform['control'] = form.int_field(self.panel, sbs, "control") + sbs.Add((5,0), 0.1) # stretchy space + myform['N'] = form.int_field(self.panel, sbs, "N") + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(form.button_with_callback(self.panel, "Do It!", + self._generic_doit(_write_all, myform)), 1, wx.EXPAND) + sbs.Add((5,0), 0.1) # stretchy space + self.vbox.Add(sbs, 0, wx.EXPAND) + + + def _create_write_it(self): + + def _write_it(kv): + self.flexrf._write_it(kv['v']) # void + return True + + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.HORIZONTAL) + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(wx.StaticText(self.panel, -1, "write_it "), 0, 0) + sbs.Add((5,0), 0.1) # stretchy space + myform = form.form() + myform['v'] = form.int_field(self.panel, sbs, "24-bit value") + sbs.Add((5,0), 0.1) # stretchy space + sbs.Add(form.button_with_callback(self.panel, "Do It!", + self._generic_doit(_write_it, myform)), 1, wx.EXPAND) + sbs.Add((5,0), 0.1) # stretchy space + self.vbox.Add(sbs, 0, wx.EXPAND) + + + # ---------------------------------------------------------------- + + def _set_status_msg(self, msg): + self.GetStatusBar().SetStatusText(msg, 0) + + def _generic_doit(self, callback, form): + + def button_callback(): + errors = form.check_input_for_errors() + if errors: + self._set_status_msg(errors[0]) + print '\n'.join(tuple(errors)) + else: + kv = form.get_key_vals() + if callback(kv): + self._set_status_msg("OK") + else: + self._set_status_msg("Failed") + + return button_callback + + + +if False and __name__ == '__main__': + + class demo_app (wx.App): + def __init__ (self): + wx.App.__init__(self) + + def OnInit (self): + frame = flexrf_debug_gui(None, "Debug FlexRF TX") + frame.Show(True) + self.SetTopWindow (frame) + return True + + app = demo_app() + app.MainLoop() + diff --git a/gr-usrp/src/qa_usrp.py b/gr-usrp/src/qa_usrp.py new file mode 100755 index 00000000..eb68c640 --- /dev/null +++ b/gr-usrp/src/qa_usrp.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import usrp1 + +class qa_usrp (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have a USRP connected, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-usrp/src/run_tests.in b/gr-usrp/src/run_tests.in new file mode 100644 index 00000000..793cb249 --- /dev/null +++ b/gr-usrp/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-usrp/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-usrp/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-usrp/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-usrp/src/tx_debug_gui.py b/gr-usrp/src/tx_debug_gui.py new file mode 100755 index 00000000..6988f986 --- /dev/null +++ b/gr-usrp/src/tx_debug_gui.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import sys +import wx +from gnuradio.wxgui import form + +class tx_debug_gui(wx.Frame): + def __init__(self, tx_subdev, title="Tx Debug"): + wx.Frame.__init__(self, None, -1, title) + + self.subdev = tx_subdev + self.subdev._u.set_verbose(True) + + self.CreateStatusBar (1) + + self.panel = wx.Panel(self, -1) + self.vbox = wx.BoxSizer(wx.VERTICAL) + self.panel.SetSizer(self.vbox) + self.panel.SetAutoLayout(True) + + self._create_form() + + self.vbox.Fit(self.panel) + + self.frame_vbox = wx.BoxSizer(wx.VERTICAL) + self.frame_vbox.Add(self.panel, 1, wx.EXPAND) + self.SetSizer(self.frame_vbox) + self.SetAutoLayout(True) + self.frame_vbox.Fit(self) + + # ---------------------------------------------------------------- + + def _write_9862(self, regno, v): + return self.subdev._u._write_9862(self.subdev._which, regno, v) + + def _set_dac_offset(self, i_or_q, offset, offset_pin): + return self.subdev._u.set_dac_offset(self.subdev._which * 2 + i_or_q, offset, offset_pin) + + def _set_dac_fine_gain(self, i_or_q, gain, coarse): + return self._write_9862(14 + i_or_q, (coarse & 0xC0) | (gain & 0x3f)) + + def _create_form(self): + self._create_dac_offset() + self._create_dac_fine_gain() + self._create_pga() + + # ---------------------------------------------------------------- + + def _create_dac_offset(self): + + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add(wx.StaticText(self.panel, -1, "DAC Offset"), 5, 0) + sbs.Add(hbox, 0, 1) + + + self._create_dac_offset_helper(sbs, 0) + self._create_dac_offset_helper(sbs, 1) + + self.vbox.Add(sbs, 0, wx.EXPAND) + + def _create_dac_offset_helper(self, vbox, i_or_q): + + def doit(kv): + drive_positive = kv['drive_positive'] + dac_offset = kv['dac_offset'] + print "drive_positive =", drive_positive + print "dac_offset[%d] = %4d" % (i_or_q, dac_offset) + + # FIXME signed magnitude?? + # dac_offset = signed_mag10(dac_offset) + return self._set_dac_offset(i_or_q, dac_offset, int(drive_positive)) + + def signed_mag10(x): + # not clear from doc if this is really 2's comp or 10-bit signed magnitude + # we'll guess it's 10-bit signed mag + if x < 0: + return (1 << 9) | min(511, max(0, abs(x))) + else: + return (0 << 9) | min(511, max(0, abs(x))) + + myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + vbox.Add(hbox, 0, wx.EXPAND) + myform['drive_positive'] = form.checkbox_field(parent=self.panel, sizer=hbox, + callback=myform.check_input_and_call(doit), + weight=0, + label="drive +ve") + myform['dac_offset'] = form.slider_field(parent=self.panel, sizer=hbox, + callback=myform.check_input_and_call(doit), + min=-512, max=511, value=0, + weight=5) + + # ---------------------------------------------------------------- + + def _create_dac_fine_gain(self): + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add(wx.StaticText(self.panel, -1, "DAC Gain"), 5, 0) + sbs.Add(hbox, 0, 1) + + self._create_dac_gain_helper(sbs, 0) + self._create_dac_gain_helper(sbs, 1) + + self.vbox.Add(sbs, 0, wx.EXPAND) + + def _create_dac_gain_helper(self, vbox, i_or_q): + + d = { "1/1" : 0xC0, + "1/2" : 0x40, + "1/11" : 0x00 } + + def doit(kv): + dac_gain = kv['dac_gain'] + coarse_s = kv['coarse'] + print "dac_gain[%d] = %4d" % (i_or_q, dac_gain) + print "coarse = ", coarse_s + return self._set_dac_fine_gain(i_or_q, dac_gain, d[coarse_s]) + + myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + vbox.Add(hbox, 0, wx.EXPAND) + myform['coarse'] = form.radiobox_field(parent=self.panel, sizer=hbox, + callback=myform.check_input_and_call(doit), + choices=['1/11', '1/2', '1/1'], + weight=1, value='1/1') + myform['dac_gain'] = form.slider_field(parent=self.panel, sizer=hbox, + callback=myform.check_input_and_call(doit), + min=-32, max=31, value=0, + weight=4) + + + # ---------------------------------------------------------------- + + def _create_pga(self): + sbs = wx.StaticBoxSizer(wx.StaticBox(self.panel), wx.VERTICAL) + + form.quantized_slider_field(parent=self.panel, sizer=sbs, label="PGA", + weight=3, range=self.subdev.gain_range(), + callback=self.subdev.set_gain) + + self.vbox.Add(sbs, 0, wx.EXPAND) + + + # ---------------------------------------------------------------- + + + def _set_status_msg(self, msg): + self.GetStatusBar().SetStatusText(msg, 0) + + +if False and __name__ == '__main__': + + class demo_app (wx.App): + def __init__ (self): + wx.App.__init__(self) + + def OnInit (self): + frame = tx_debug_gui(None, "Debug TX") + frame.Show(True) + self.SetTopWindow (frame) + return True + + app = demo_app() + app.MainLoop() diff --git a/gr-usrp/src/usrp.py b/gr-usrp/src/usrp.py new file mode 100644 index 00000000..6e19c1bb --- /dev/null +++ b/gr-usrp/src/usrp.py @@ -0,0 +1,474 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + + +import usrp_prims +import usrp_dbid +from gnuradio import usrp1 # usrp Rev 1 and later +from gnuradio import gru +from usrp_fpga_regs import * + +FPGA_MODE_NORMAL = usrp1.FPGA_MODE_NORMAL +FPGA_MODE_LOOPBACK = usrp1.FPGA_MODE_LOOPBACK +FPGA_MODE_COUNTING = usrp1.FPGA_MODE_COUNTING + +SPI_FMT_xSB_MASK = usrp1.SPI_FMT_xSB_MASK +SPI_FMT_LSB = usrp1.SPI_FMT_LSB +SPI_FMT_MSB = usrp1.SPI_FMT_MSB +SPI_FMT_HDR_MASK = usrp1.SPI_FMT_HDR_MASK +SPI_FMT_HDR_0 = usrp1.SPI_FMT_HDR_0 +SPI_FMT_HDR_1 = usrp1.SPI_FMT_HDR_1 +SPI_FMT_HDR_2 = usrp1.SPI_FMT_HDR_2 + +SPI_ENABLE_FPGA = usrp1.SPI_ENABLE_FPGA +SPI_ENABLE_CODEC_A = usrp1.SPI_ENABLE_CODEC_A +SPI_ENABLE_CODEC_B = usrp1.SPI_ENABLE_CODEC_B +SPI_ENABLE_reserved = usrp1.SPI_ENABLE_reserved +SPI_ENABLE_TX_A = usrp1.SPI_ENABLE_TX_A +SPI_ENABLE_RX_A = usrp1.SPI_ENABLE_RX_A +SPI_ENABLE_TX_B = usrp1.SPI_ENABLE_TX_B +SPI_ENABLE_RX_B = usrp1.SPI_ENABLE_RX_B + + +# Import all the daughterboard classes we know about. +# This hooks them into the auto-instantiation framework. + +import db_instantiator + +import db_basic +import db_dbs_rx +import db_flexrf +import db_flexrf_mimo +import db_tv_rx + + +def _look_for_usrp(which): + """ + Try to open the specified usrp. + + @param which: int >= 0 specifying which USRP to open + @type which: int + + @return: Returns version number, or raises RuntimeError + @rtype: int + """ + d = usrp_prims.usrp_find_device(which) + if not d: + raise RuntimeError, "Unable to find USRP #%d" % (which,) + + return usrp_prims.usrp_hw_rev(d) + + +def _ensure_rev2(which): + v = _look_for_usrp(which) + if not v in (2, 4): + raise RuntimeError, "Sorry, unsupported USRP revision (rev=%d)" % (v,) + + +class tune_result(object): + """ + Container for intermediate tuning information. + """ + def __init__(self, baseband_freq, dxc_freq, residual_freq, inverted): + self.baseband_freq = baseband_freq + self.dxc_freq = dxc_freq + self.residual_freq = residual_freq + self.inverted = inverted + + +def tune(u, chan, subdev, target_freq): + """ + Set the center frequency we're interested in. + + @param u: instance of usrp.source_* or usrp.sink_* + @param chan: DDC/DUC channel + @type chan: int + @param subdev: daughterboard subdevice + @param target_freq: frequency in Hz + @returns False if failure else tune_result + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + + # Does this usrp instance do Tx or Rx? + rx_p = True + try: + u.rx_freq + except AttributeError: + rx_p = False + + ok, baseband_freq = subdev.set_freq(target_freq) + dxc_freq, inverted = calc_dxc_freq(target_freq, baseband_freq, u.converter_rate()) + + # If the spectrum is inverted, and the daughterboard doesn't do + # quadrature downconversion, we can fix the inversion by flipping the + # sign of the dxc_freq... (This only happens using the basic_rx board) + + if subdev.spectrum_inverted(): + inverted = not(inverted) + + if inverted and not(subdev.is_quadrature()): + dxc_freq = -dxc_freq + inverted = not(inverted) + + if rx_p: + ok = ok and u.set_rx_freq(chan, dxc_freq) + else: + dxc_freq = -dxc_freq + ok = ok and u.set_tx_freq(chan, dxc_freq) + + if not(ok): + return False + + # residual_freq is the offset left over because of dxc tuning step size + if rx_p: + residual_freq = dxc_freq - u.rx_freq(chan) + else: + # FIXME 50-50 chance this has the wrong sign... + residual_freq = dxc_freq - u.tx_freq(chan) + + return tune_result(baseband_freq, dxc_freq, residual_freq, inverted) + + +# ------------------------------------------------------------------------ +# Build subclasses of raw usrp1.* class that add the db attribute +# by automatically instantiating the appropriate daughterboard classes. +# [Also provides keyword args.] +# ------------------------------------------------------------------------ + +class usrp_common(object): + def __init__(self): + # read capability register + r = self._u._read_fpga_reg(FR_RB_CAPS) + if r < 0: + r += 2**32 + if r == 0xaa55ff77: # value of this reg prior to being defined as cap reg + r = ((2 << bmFR_RB_CAPS_NDUC_SHIFT) + | (2 << bmFR_RB_CAPS_NDDC_SHIFT) + | bmFR_RB_CAPS_RX_HAS_HALFBAND) + self._fpga_caps = r + + if False: + print "FR_RB_CAPS = %#08x" % (self._fpga_caps,) + print "has_rx_halfband =", self.has_rx_halfband() + print "nDDCs =", self.nddc() + print "has_tx_halfband =", self.has_tx_halfband() + print "nDUCs =", self.nduc() + + def __getattr__(self, name): + return getattr(self._u, name) + + def tune(self, chan, subdev, target_freq): + return tune(self, chan, subdev, target_freq) + + def has_rx_halfband(self): + return self._fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND != 0 + + def has_tx_halfband(self): + return self._fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND != 0 + + def nddc(self): + """ + Number of Digital Down Converters implemented in FPGA + """ + return (self._fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT + + def nduc(self): + """ + Number of Digital Up Converters implemented in FPGA + """ + return (self._fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT + + +class sink_c(usrp_common): + def __init__(self, which=0, interp_rate=128, nchan=1, mux=0x98, + fusb_block_size=0, fusb_nblocks=0, + fpga_filename="", firmware_filename=""): + _ensure_rev2(which) + self._u = usrp1.sink_c(which, interp_rate, nchan, mux, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) + # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes + self.db = (db_instantiator.instantiate(self._u, 0), + db_instantiator.instantiate(self._u, 1)) + usrp_common.__init__(self) + + def __del__(self): + self.db = None # will fire d'board destructors + self._u = None # will fire usrp1.* destructor + + +class sink_s(usrp_common): + def __init__(self, which=0, interp_rate=128, nchan=1, mux=0x98, + fusb_block_size=0, fusb_nblocks=0, + fpga_filename="", firmware_filename=""): + _ensure_rev2(which) + self._u = usrp1.sink_s(which, interp_rate, nchan, mux, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) + # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes + self.db = (db_instantiator.instantiate(self._u, 0), + db_instantiator.instantiate(self._u, 1)) + usrp_common.__init__(self) + + def __del__(self): + self.db = None # will fire d'board destructors + self._u = None # will fire usrp1.* destructor + + +class source_c(usrp_common): + def __init__(self, which=0, decim_rate=64, nchan=1, mux=0x32103210, mode=0, + fusb_block_size=0, fusb_nblocks=0, + fpga_filename="", firmware_filename=""): + _ensure_rev2(which) + self._u = usrp1.source_c(which, decim_rate, nchan, mux, mode, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) + # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes + self.db = (db_instantiator.instantiate(self._u, 0), + db_instantiator.instantiate(self._u, 1)) + usrp_common.__init__(self) + + def __del__(self): + self.db = None # will fire d'board destructors + self._u = None # will fire usrp1.* destructor + + +class source_s(usrp_common): + def __init__(self, which=0, decim_rate=64, nchan=1, mux=0x32103210, mode=0, + fusb_block_size=0, fusb_nblocks=0, + fpga_filename="", firmware_filename=""): + _ensure_rev2(which) + self._u = usrp1.source_s(which, decim_rate, nchan, mux, mode, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) + # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes + self.db = (db_instantiator.instantiate(self._u, 0), + db_instantiator.instantiate(self._u, 1)) + usrp_common.__init__(self) + + def __del__(self): + self.db = None # will fire d'board destructors + self._u = None # will fire usrp1.* destructor + + +# ------------------------------------------------------------------------ +# utilities +# ------------------------------------------------------------------------ + +def determine_rx_mux_value(u, subdev_spec): + """ + Determine appropriate Rx mux value as a function of the subdevice choosen and the + characteristics of the respective daughterboard. + + @param u: instance of USRP source + @param subdev_spec: return value from subdev option parser. + @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 or 1 + @returns: the Rx mux value + """ + # Figure out which A/D's to connect to the DDC. + # + # Each daughterboard consists of 1 or 2 subdevices. (At this time, + # all but the Basic Rx have a single subdevice. The Basic Rx + # has two independent channels, treated as separate subdevices). + # subdevice 0 of a daughterboard may use 1 or 2 A/D's. We determine this + # by checking the is_quadrature() method. If subdevice 0 uses only a single + # A/D, it's possible that the daughterboard has a second subdevice, subdevice 1, + # and it uses the second A/D. + # + # If the card uses only a single A/D, we wire a zero into the DDC Q input. + # + # (side, 0) says connect only the A/D's used by subdevice 0 to the DDC. + # (side, 1) says connect only the A/D's used by subdevice 1 to the DDC. + # + + side = subdev_spec[0] # side A = 0, side B = 1 + + if not(side in (0, 1)): + raise ValueError, "Invalid subdev_spec: %r:" % (subdev_spec,) + + db = u.db[side] # This is a tuple of length 1 or 2 containing the subdevice + # classes for the selected side. + + # compute bitmasks of used A/D's + + if db[0].is_quadrature(): + subdev0_uses = 0x3 # uses A/D 0 and 1 + else: + subdev0_uses = 0x1 # uses A/D 0 only + + if len(db) > 1: + subdev1_uses = 0x2 # uses A/D 1 only + else: + subdev1_uses = 0x0 # uses no A/D (doesn't exist) + + if subdev_spec[1] == 0: + uses = subdev0_uses + elif subdev_spec[1] == 1: + uses = subdev1_uses + else: + raise ValueError, "Invalid subdev_spec: %r: " % (subdev_spec,) + + if uses == 0: + raise RuntimeError, "Daughterboard doesn't have a subdevice 1: %r: " % (subdev_spec,) + + swap_iq = db[0].i_and_q_swapped() + + truth_table = { + # (side, uses, swap_iq) : mux_val + (0, 0x1, False) : 0xf0f0f0f0, + (0, 0x2, False) : 0xf0f0f0f1, + (0, 0x3, False) : 0x00000010, + (0, 0x3, True) : 0x00000001, + (1, 0x1, False) : 0xf0f0f0f2, + (1, 0x2, False) : 0xf0f0f0f3, + (1, 0x3, False) : 0x00000032, + (1, 0x3, True) : 0x00000023 + } + + return gru.hexint(truth_table[(side, uses, swap_iq)]) + + +def determine_tx_mux_value(u, subdev_spec): + """ + Determine appropriate Tx mux value as a function of the subdevice choosen. + + @param u: instance of USRP source + @param subdev_spec: return value from subdev option parser. + @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 + @returns: the Rx mux value + """ + # This is simpler than the rx case. Either you want to talk + # to side A or side B. If you want to talk to both sides at once, + # determine the value manually. + + side = subdev_spec[0] # side A = 0, side B = 1 + + if not(side in (0, 1)): + raise ValueError, "Invalid subdev_spec: %r:" % (subdev_spec,) + + return gru.hexint([0x0098, 0x9800][side]) + + +def selected_subdev(u, subdev_spec): + """ + Return the user specified daughterboard subdevice. + + @param u: an instance of usrp.source_* or usrp.sink_* + @param subdev_spec: return value from subdev option parser. + @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 or 1 + @returns: an instance derived from db_base + """ + side, subdev = subdev_spec + return u.db[side][subdev] + + +def calc_dxc_freq(target_freq, baseband_freq, fs): + """ + Calculate the frequency to use for setting the digital up or down converter. + + @param target_freq: desired RF frequency (Hz) + @type target_freq: number + @param baseband_freq: the RF frequency that corresponds to DC in the IF. + @type baseband_freq: number + @param fs: converter sample rate + @type fs: number + + @returns: 2-tuple (ddc_freq, inverted) where ddc_freq is the value + for the ddc and inverted is True if we're operating in an inverted + Nyquist zone. + """ + + delta = target_freq - baseband_freq + + if delta >= 0: + while delta > fs: + delta -= fs + if delta <= fs/2: + return (-delta, False) # non-inverted region + else: + return (delta - fs, True) # inverted region + else: + while delta < -fs: + delta += fs + if delta >= -fs/2: + return (-delta, False) # non-inverted region + else: + return (delta + fs, True) # inverted region + + +# ------------------------------------------------------------------------ +# Utilities +# ------------------------------------------------------------------------ + +def pick_tx_subdevice(u): + """ + The user didn't specify a tx subdevice on the command line. + Try for one of these, in order: FLEX_400, FLEX_900, FLEX_1200, FLEX_2400, + BASIC_TX, whatever's on side A. + + @return a subdev_spec + """ + return pick_subdev(u, (usrp_dbid.FLEX_400_TX, + usrp_dbid.FLEX_900_TX, + usrp_dbid.FLEX_1200_TX, + usrp_dbid.FLEX_2400_TX, + usrp_dbid.BASIC_TX)) + +def pick_rx_subdevice(u): + """ + The user didn't specify an rx subdevice on the command line. + Try for one of these, in order: FLEX_400, FLEX_900, FLEX_1200, FLEX_2400, + TV_RX, DBS_RX, BASIC_RX, whatever's on side A. + + @return a subdev_spec + """ + return pick_subdev(u, (usrp_dbid.FLEX_400_RX, + usrp_dbid.FLEX_900_RX, + usrp_dbid.FLEX_1200_RX, + usrp_dbid.FLEX_2400_RX, + usrp_dbid.TV_RX, + usrp_dbid.TV_RX_REV_2, + usrp_dbid.DBS_RX, + usrp_dbid.DBS_RX_REV_2_1, + usrp_dbid.BASIC_RX)) + +def pick_subdev(u, candidates): + """ + @param u: usrp instance + @param candidates: list of dbids + @returns: subdev specification + """ + db0 = u.db[0][0].dbid() + db1 = u.db[1][0].dbid() + for c in candidates: + if c == db0: return (0, 0) + if c == db1: return (1, 0) + if db0 >= 0: + return (0, 0) + if db1 >= 0: + return (1, 0) + raise RuntimeError, "No suitable daughterboard found!" + diff --git a/gr-usrp/src/usrp1.i b/gr-usrp/src/usrp1.i new file mode 100644 index 00000000..b73abcd7 --- /dev/null +++ b/gr-usrp/src/usrp1.i @@ -0,0 +1,657 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 "usrp1_sink_c.h" +#include "usrp1_sink_s.h" +#include "usrp1_source_c.h" +#include "usrp1_source_s.h" +#include +#include +#include +%} + +%include + +%constant int FPGA_MODE_NORMAL = usrp_standard_rx::FPGA_MODE_NORMAL; +%constant int FPGA_MODE_LOOPBACK = usrp_standard_rx::FPGA_MODE_LOOPBACK; +%constant int FPGA_MODE_COUNTING = usrp_standard_rx::FPGA_MODE_COUNTING; + +// ================================================================ +// abstract classes +// ================================================================ + +class usrp1_sink_base : public gr_sync_block { +protected: + usrp1_sink_base (const std::string &name, + gr_io_signature_sptr input_signature, + int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written) = 0; + public: + ~usrp1_sink_base (); + + /*! + * \brief Set interpolator rate. \p rate must be in [4, 1024] and a multiple of 4. + * + * The final complex sample rate across the USB is + * dac_freq () * nchannels () / interp_rate () + */ + bool set_interp_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + + /*! + * \brief set the frequency of the digital up converter. + * + * \p channel must be 0 or 1. \p freq is the center frequency in Hz. + * It must be in the range [-44M, 44M]. The frequency specified is + * quantized. Use tx_freq to retrieve the actual value used. + */ + bool set_tx_freq (int channel, double freq); + + void set_verbose (bool verbose); + + // ACCESSORS + + long fpga_master_clock_freq() const; + long converter_rate() const; // D/A sample rate + long dac_rate() const; // alias + long dac_freq () const; // deprecated name. Use converter_rate() or dac_rate(). + + unsigned int interp_rate () const; + double tx_freq (int channel) const; + int nunderruns () const { return d_nunderruns; } + + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which D/A [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3. + * Setting DAC 0 affects DAC 1 and vice versa. Same with DAC 2 and DAC 3. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain in dB. + * + * \param which which D/A [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + /*! + * \brief Return daughterboard ID for given Tx daughterboard slot [0,1]. + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + int daughterboard_id (int which_dboard) const; + + /*! + * \brief Set ADC offset correction + * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... + * \param offset 16-bit value to subtract from raw ADC input. + */ + bool set_adc_offset (int which, int offset); + + /*! + * \brief Set DAC offset correction + * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... + * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). + * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; + * If 1 offset applied to +ve differential pin. + */ + bool set_dac_offset (int which, int offset, int offset_pin); + + /*! + * \brief Control ADC input buffer + * \param which which ADC[0,3] + * \param bypass if non-zero, bypass input buffer and connect input + * directly to switched cap SHA input of RxPGA. + */ + bool set_adc_buffer_bypass (int which, bool bypass); + + /*! + * \brief return the usrp's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + * + * Each d'board has 16-bits of general purpose i/o. + * Setting the bit makes it an output from the FPGA to the d'board. + * + * This register is initialized based on a value stored in the + * d'board EEPROM. In general, you shouldn't be using this routine + * without a very good reason. Using this method incorrectly will + * kill your USRP motherboard and/or daughterboard. + */ + bool _write_oe (int which_dboard, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool write_io (int which_dboard, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int read_io (int which_dboard); + + bool write_aux_dac (int which_dboard, int which_dac, int value); + int read_aux_adc (int which_dboard, int which_adc); + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + bool write_i2c (int i2c_addr, const std::string buf); + std::string read_i2c (int i2c_addr, int len); + + bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value + int _read_fpga_reg (int regno); + bool _write_9862 (int which_codec, int regno, unsigned char value); + int _read_9862 (int which_codec, int regno) const; + + /*! + * \brief Write data to SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripherals to write. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they are + * written to the peripheral immediately prior to writing \p buf. + */ + bool _write_spi (int optional_header, int enables, int format, std::string buf); + + /* + * \brief Read data from SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripheral to read. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param len number of bytes to read. Must be in [0,64]. + * \returns the data read if sucessful, else a zero length string. + * + * Reads are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they + * are written to the peripheral first. Then \p len bytes are read from + * the peripheral and returned. + */ + std::string _read_spi (int optional_header, int enables, int format, int len); +}; + +// ---------------------------------------------------------------- + +class usrp1_source_base : public gr_sync_block { + protected: + + usrp1_sink_base (const std::string &name, + gr_io_signature_sptr input_signature, + int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; + + virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read) = 0; + public: + ~usrp1_source_base (); + + + /*! + * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () + */ + bool set_decim_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + + /*! + * \brief set the center frequency of the digital down converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-FIXME, FIXME]. The frequency specified is + * quantized. Use rx_freq to retrieve the actual value used. + */ + bool set_rx_freq (int channel, double freq); + + /*! + * \brief set fpga special modes + */ + bool set_fpga_mode (int mode); + + /*! + * \brief Set the digital down converter phase register. + * + * \param channel which ddc channel [0, 3] + * \param phase 32-bit integer phase value. + */ + bool set_ddc_phase(int channel, int phase); + + + void set_verbose (bool verbose); + + // ACCESSORS + + long fpga_master_clock_freq() const; + long converter_rate() const; // A/D sample rate + long adc_rate() const; // alias + long adc_freq() const; // Deprecated name. Use converter_rate() or adc_rate(). + + unsigned int decim_rate () const; + double rx_freq (int channel) const; + int noverruns () const { return d_noverruns; } + + + // PGA stuff + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which A/D [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param which which A/D [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA setting in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA setting in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + /*! + * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + int daughterboard_id (int which_dboard) const; + + /*! + * \brief Set ADC offset correction + * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... + * \param offset 16-bit value to subtract from raw ADC input. + */ + bool set_adc_offset (int which, int offset); + + /*! + * \brief Set DAC offset correction + * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... + * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). + * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; + * If 1 offset applied to +ve differential pin. + */ + bool set_dac_offset (int which, int offset, int offset_pin); + + /*! + * \brief Control ADC input buffer + * \param which which ADC[0,3] + * \param bypass if non-zero, bypass input buffer and connect input + * directly to switched cap SHA input of RxPGA. + */ + bool set_adc_buffer_bypass (int which, bool bypass); + + /*! + * \brief return the usrp's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + * + * Each d'board has 16-bits of general purpose i/o. + * Setting the bit makes it an output from the FPGA to the d'board. + * + * This register is initialized based on a value stored in the + * d'board EEPROM. In general, you shouldn't be using this routine + * without a very good reason. Using this method incorrectly will + * kill your USRP motherboard and/or daughterboard. + */ + bool _write_oe (int which_dboard, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool write_io (int which_dboard, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int read_io (int which_dboard); + + /*! + * \brief Enable/disable automatic DC offset removal control loop in FPGA + * + * \param bits which control loops to enable + * \param mask which \p bits to pay attention to + * + * If the corresponding bit is set, enable the automatic DC + * offset correction control loop. + * + *
+   * The 4 low bits are significant:
+   *
+   *   ADC0 = (1 << 0)
+   *   ADC1 = (1 << 1)
+   *   ADC2 = (1 << 2)
+   *   ADC3 = (1 << 3)
+   * 
+ * + * By default the control loop is enabled on all ADC's. + */ + bool set_dc_offset_cl_enable(int bits, int mask); + + /*! + * \brief Specify Rx data format. + * + * \param format format specifier + * + * Rx data format control register + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------------------------------------+-+-+---------+-------+ + * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | + * +-----------------------------------------+-+-+---------+-------+ + * + * SHIFT specifies arithmetic right shift [0, 15] + * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) + * Q if set deliver both I & Q, else just I + * B if set bypass half-band filter. + * + * Right now the acceptable values are: + * + * B Q WIDTH SHIFT + * 0 1 16 0 + * 0 1 8 8 + * + * More valid combos to come. + * + * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. + */ + bool set_format(unsigned int format); + + /*! + * \brief return current format + */ + unsigned int format () const; + + static unsigned int make_format(int width=16, int shift=0, + bool want_q=true, bool bypass_halfband=false); + static int format_width(unsigned int format); + static int format_shift(unsigned int format); + static bool format_want_q(unsigned int format); + static bool format_bypass_halfband(unsigned int format); + + + + + bool write_aux_dac (int which_dboard, int which_dac, int value); + int read_aux_adc (int which_dboard, int which_adc); + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + bool write_i2c (int i2c_addr, const std::string buf); + std::string read_i2c (int i2c_addr, int len); + bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value + bool _write_fpga_reg_masked (int regno, int value, int mask); //< 7-bit regno, 16-bit value, 16-bit mask + int _read_fpga_reg (int regno); + bool _write_9862 (int which_codec, int regno, unsigned char value); + int _read_9862 (int which_codec, int regno) const; + + bool _write_spi (int optional_header, int enables, int format, std::string buf); + + /* + * \brief Read data from SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripheral to read. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param len number of bytes to read. Must be in [0,64]. + * \returns the data read if sucessful, else a zero length string. + * + * Reads are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they + * are written to the peripheral first. Then \p len bytes are read from + * the peripheral and returned. + */ + std::string _read_spi (int optional_header, int enables, int format, int len); +}; + + +// ================================================================ +// concrete sinks +// ================================================================ + + +GR_SWIG_BLOCK_MAGIC(usrp1,sink_c) + +usrp1_sink_c_sptr +usrp1_make_sink_c (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + +class usrp1_sink_c : public usrp1_sink_base { + protected: + usrp1_sink_c (int which_board, unsigned int interp_rate, + int nchan, int mux); + + public: + ~usrp1_sink_c (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(usrp1,sink_s) + +usrp1_sink_s_sptr +usrp1_make_sink_s (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + +class usrp1_sink_s : public usrp1_sink_base { + protected: + usrp1_sink_s (int which_board, unsigned int interp_rate, + int nchan, int mux); + + public: + ~usrp1_sink_s (); +}; + +// ================================================================ +// concrete sources +// ================================================================ + +GR_SWIG_BLOCK_MAGIC(usrp1,source_c) + + +usrp1_source_c_sptr +usrp1_make_source_c (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + +class usrp1_source_c : public usrp1_source_base { + protected: + usrp1_source_c (int which_board, unsigned int decim_rate, + int nchan, int mux, int mode); + + public: + ~usrp1_source_c (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(usrp1,source_s) + +usrp1_source_s_sptr +usrp1_make_source_s (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + +class usrp1_source_s : public usrp1_source_base { + protected: + usrp1_source_s (int which_board, unsigned int decim_rate, + int nchan, int mux, int mode); + + public: + ~usrp1_source_s (); +}; + diff --git a/gr-usrp/src/usrp1_sink_base.cc b/gr-usrp/src/usrp1_sink_base.cc new file mode 100644 index 00000000..19e0b23f --- /dev/null +++ b/gr-usrp/src/usrp1_sink_base.cc @@ -0,0 +1,359 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static const int OUTPUT_MULTIPLE_SAMPLES = 128; // DON'T CHANGE THIS VALUE! + +usrp1_sink_base::usrp1_sink_base (const std::string &name, + gr_io_signature_sptr input_signature, + int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : gr_sync_block (name, + input_signature, + gr_make_io_signature (0, 0, 0)), + d_nunderruns (0) +{ + d_usrp = usrp_standard_tx::make (which_board, + interp_rate, + nchan, mux, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename + ); + if (d_usrp == 0) + throw std::runtime_error ("can't open usrp1"); + + // All calls to d_usrp->write must be multiples of 512 bytes. + + set_output_multiple (OUTPUT_MULTIPLE_SAMPLES); +} + +usrp1_sink_base::~usrp1_sink_base () +{ + delete d_usrp; +} + +bool +usrp1_sink_base::start() +{ + return d_usrp->start(); +} + +bool +usrp1_sink_base::stop() +{ + return d_usrp->stop(); +} + +int +usrp1_sink_base::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + static const int BUFSIZE = 16 * (1L << 10); // 16kB + unsigned char outbuf[BUFSIZE]; + int obi = 0; + int input_index = 0; + int input_items_consumed; + int bytes_written; + bool underrun; + + + while (input_index < noutput_items){ + + copy_to_usrp_buffer (input_items, + input_index, + noutput_items - input_index, // input_items_available + input_items_consumed, // [out] + &outbuf[obi], // [out] usrp_buffer + BUFSIZE - obi, // usrp_buffer_length + bytes_written); // [out] + + assert (input_index + input_items_consumed <= noutput_items); + assert (obi + bytes_written <= BUFSIZE); + + input_index += input_items_consumed; + obi += bytes_written; + + if (obi >= BUFSIZE){ // flush + if (d_usrp->write (outbuf, obi, &underrun) != obi) + return -1; // indicate we're done + + if (underrun){ + d_nunderruns++; + // fprintf (stderr, "usrp1_sink: underrun\n"); + fputs ("uU", stderr); + } + obi = 0; + } + } + + if (obi != 0){ + assert (obi % 512 == 0); + if (d_usrp->write (outbuf, obi, &underrun) != obi) + return -1; // indicate we're done + + if (underrun){ + d_nunderruns++; + // fprintf (stderr, "usrp1_sink: underrun\n"); + fputs ("uU", stderr); + } + } + + return noutput_items; +} + +bool +usrp1_sink_base::set_interp_rate (unsigned int rate) +{ + return d_usrp->set_interp_rate (rate); +} + +bool +usrp1_sink_base::set_nchannels (int nchan) +{ + return d_usrp->set_nchannels (nchan); +} + +bool +usrp1_sink_base::set_mux (int mux) +{ + return d_usrp->set_mux (mux); +} + +bool +usrp1_sink_base::set_tx_freq (int channel, double freq) +{ + return d_usrp->set_tx_freq (channel, freq); +} + +long +usrp1_sink_base::fpga_master_clock_freq() const +{ + return d_usrp->fpga_master_clock_freq(); +} + +long +usrp1_sink_base::converter_rate () const +{ + return d_usrp->converter_rate (); +} + +unsigned int +usrp1_sink_base::interp_rate () const +{ + return d_usrp->interp_rate (); +} + +int +usrp1_sink_base::nchannels () const +{ + return d_usrp->nchannels (); +} + +int +usrp1_sink_base::mux () const +{ + return d_usrp->mux (); +} + + +double +usrp1_sink_base::tx_freq (int channel) const +{ + return d_usrp->tx_freq (channel); +} + +void +usrp1_sink_base::set_verbose (bool verbose) +{ + d_usrp->set_verbose (verbose); +} + +bool +usrp1_sink_base::write_aux_dac (int which_dboard, int which_dac, int value) +{ + return d_usrp->write_aux_dac (which_dboard, which_dac, value); +} + +int +usrp1_sink_base::read_aux_adc (int which_dboard, int which_adc) +{ + return d_usrp->read_aux_adc (which_dboard, which_adc); +} + +bool +usrp1_sink_base::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) +{ + return d_usrp->write_eeprom (i2c_addr, eeprom_offset, buf); +} + +std::string +usrp1_sink_base::read_eeprom (int i2c_addr, int eeprom_offset, int len) +{ + return d_usrp->read_eeprom (i2c_addr, eeprom_offset, len); +} + +bool +usrp1_sink_base::write_i2c (int i2c_addr, const std::string buf) +{ + return d_usrp->write_i2c (i2c_addr, buf); +} + +std::string +usrp1_sink_base::read_i2c (int i2c_addr, int len) +{ + return d_usrp->read_i2c (i2c_addr, len); +} + +bool +usrp1_sink_base::set_pga (int which, double gain) +{ + return d_usrp->set_pga (which, gain); +} + +double +usrp1_sink_base::pga (int which) const +{ + return d_usrp->pga (which); +} + +double +usrp1_sink_base::pga_min () const +{ + return d_usrp->pga_min (); +} + +double +usrp1_sink_base::pga_max () const +{ + return d_usrp->pga_max (); +} + +double +usrp1_sink_base::pga_db_per_step () const +{ + return d_usrp->pga_db_per_step (); +} + +int +usrp1_sink_base::daughterboard_id (int which) const +{ + return d_usrp->daughterboard_id (which); +} + +bool +usrp1_sink_base::set_adc_offset (int which, int offset) +{ + return d_usrp->set_adc_offset (which, offset); +} + +bool +usrp1_sink_base::set_dac_offset (int which, int offset, int offset_pin) +{ + return d_usrp->set_dac_offset (which, offset, offset_pin); +} + +bool +usrp1_sink_base::set_adc_buffer_bypass (int which, bool bypass) +{ + return d_usrp->set_adc_buffer_bypass (which, bypass); +} + +std::string +usrp1_sink_base::serial_number() +{ + return d_usrp->serial_number(); +} + +bool +usrp1_sink_base::_write_oe (int which_dboard, int value, int mask) +{ + return d_usrp->_write_oe (which_dboard, value, mask); +} + +bool +usrp1_sink_base::write_io (int which_dboard, int value, int mask) +{ + return d_usrp->write_io (which_dboard, value, mask); +} + +int +usrp1_sink_base::read_io (int which_dboard) +{ + return d_usrp->read_io (which_dboard); +} + +// internal routines... + +bool +usrp1_sink_base::_write_fpga_reg (int regno, int value) +{ + return d_usrp->_write_fpga_reg (regno, value); +} + +int +usrp1_sink_base::_read_fpga_reg (int regno) +{ + return d_usrp->_read_fpga_reg (regno); +} + +bool +usrp1_sink_base::_write_9862 (int which_codec, int regno, unsigned char value) +{ + return d_usrp->_write_9862 (which_codec, regno, value); +} + +int +usrp1_sink_base::_read_9862 (int which_codec, int regno) const +{ + return d_usrp->_read_9862 (which_codec, regno); +} + +bool +usrp1_sink_base::_write_spi (int optional_header, int enables, + int format, std::string buf) +{ + return d_usrp->_write_spi (optional_header, enables, format, buf); +} + +std::string +usrp1_sink_base::_read_spi (int optional_header, int enables, int format, int len) +{ + return d_usrp->_read_spi (optional_header, enables, format, len); +} diff --git a/gr-usrp/src/usrp1_sink_base.h b/gr-usrp/src/usrp1_sink_base.h new file mode 100644 index 00000000..d5775377 --- /dev/null +++ b/gr-usrp/src/usrp1_sink_base.h @@ -0,0 +1,359 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP1_SINK_BASE_H +#define INCLUDED_USRP1_SINK_BASE_H + +#include +#include + +class usrp_standard_tx; + + +/*! + * \brief abstract interface to Universal Software Radio Peripheral Tx path (Rev 1) + */ +class usrp1_sink_base : public gr_sync_block { + private: + usrp_standard_tx *d_usrp; + int d_nunderruns; + + protected: + usrp1_sink_base (const std::string &name, + gr_io_signature_sptr input_signature, + int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + /*! + * \brief convert between input item format and usrp native format + * + * \param input_items[in] stream(s) of input items + * \param input_index[in] starting index in input_items + * \param input_items_available[in] number of items available starting at item[index] + * \param input_items_consumed[out] number of input items consumed by copy + * \param usrp_buffer[out] destination buffer + * \param usrp_buffer_length[in] \p usrp_buffer length in bytes + * \param bytes_written[out] number of bytes written into \p usrp_buffer + */ + virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written) = 0; + + public: + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; + + + ~usrp1_sink_base (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool start(); + bool stop(); + + /*! + * \brief Set interpolator rate. \p rate must be in [4, 1024] and a multiple of 4. + * + * The final complex sample rate across the USB is + * dac_freq () / interp_rate () * nchannels () + */ + bool set_interp_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + + /*! + * \brief set the frequency of the digital up converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-44M, 44M]. The frequency specified is + * quantized. Use tx_freq to retrieve the actual value used. + */ + bool set_tx_freq (int channel, double freq); + + void set_verbose (bool verbose); + + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which D/A [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3. + * Setting DAC 0 affects DAC 1 and vice versa. Same with DAC 2 and DAC 3. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain in dB. + * + * \param which which D/A [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + + // ACCESSORS + + long fpga_master_clock_freq() const; + long converter_rate() const; + long dac_rate() const { return converter_rate(); } // alias + long dac_freq() const { return converter_rate(); } // deprecated alias + + unsigned int interp_rate () const; + int nchannels () const; + int mux () const; + double tx_freq (int channel) const; + int nunderruns () const { return d_nunderruns; } + + /*! + * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + int daughterboard_id (int which_dboard) const; + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param which_dboard [0,1] which d'board + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. + * \param which_dac [2,3] TX slots must use only 2 and 3. + * \param value [0,4095] + * \returns true iff successful + */ + bool write_aux_dac (int which_board, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_dboard [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + int read_aux_adc (int which_dboard, int which_adc); + + /*! + * \brief Write EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin writing + * \param buf the data to write + * \returns true iff sucessful + */ + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); + + /*! + * \brief Write EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin reading + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + */ + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + + /*! + * \brief Write to I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of of 64 bytes. + */ + bool write_i2c (int i2c_addr, const std::string buf); + + /*! + * \brief Read from I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + * Reads are limited to a maximum of of 64 bytes. + */ + std::string read_i2c (int i2c_addr, int len); + + /*! + * \brief Set ADC offset correction + * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... + * \param offset 16-bit value to subtract from raw ADC input. + */ + bool set_adc_offset (int which, int offset); + + /*! + * \brief Set DAC offset correction + * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... + * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). + * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; + * If 1 offset applied to +ve differential pin. + */ + bool set_dac_offset (int which, int offset, int offset_pin); + + /*! + * \brief Control ADC input buffer + * \param which which ADC[0,3] + * \param bypass if non-zero, bypass input buffer and connect input + * directly to switched cap SHA input of RxPGA. + */ + bool set_adc_buffer_bypass (int which, bool bypass); + + /*! + * \brief return the usrp's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + * + * Each d'board has 16-bits of general purpose i/o. + * Setting the bit makes it an output from the FPGA to the d'board. + * + * This register is initialized based on a value stored in the + * d'board EEPROM. In general, you shouldn't be using this routine + * without a very good reason. Using this method incorrectly will + * kill your USRP motherboard and/or daughterboard. + */ + bool _write_oe (int which_dboard, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool write_io (int which_dboard, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int read_io (int which_dboard); + + // + // internal routines... + // You probably shouldn't be using these... + // + /*! + * \brief Write FPGA register. + * \param regno 7-bit register number + * \param value 32-bit value + * \returns true iff successful + */ + bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value + + /*! + * \brief Read FPGA register. + * \param regno 7-bit register number + * \returns register value if successful, else READ_FAILED + */ + int _read_fpga_reg (int regno); + + /*! + * \brief Write AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \param value 8-bit value + * \returns true iff successful + */ + bool _write_9862 (int which_codec, int regno, unsigned char value); + + /*! + * \brief Read AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \returns register value if successful, else READ_FAILED + */ + int _read_9862 (int which_codec, int regno) const; + + /*! + * \brief Write data to SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripherals to write. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they are + * written to the peripheral immediately prior to writing \p buf. + */ + bool _write_spi (int optional_header, int enables, int format, std::string buf); + + /* + * \brief Read data from SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripheral to read. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param len number of bytes to read. Must be in [0,64]. + * \returns the data read if sucessful, else a zero length string. + * + * Reads are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they + * are written to the peripheral first. Then \p len bytes are read from + * the peripheral and returned. + */ + std::string _read_spi (int optional_header, int enables, int format, int len); +}; + +#endif /* INCLUDED_USRP1_SINK_BASE_H */ diff --git a/gr-usrp/src/usrp1_sink_c.cc b/gr-usrp/src/usrp1_sink_c.cc new file mode 100644 index 00000000..16296cfd --- /dev/null +++ b/gr-usrp/src/usrp1_sink_c.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +usrp1_sink_c_sptr +usrp1_make_sink_c (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) +{ + return usrp1_sink_c_sptr (new usrp1_sink_c (which_board, + interp_rate, + nchan, + mux, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename + )); +} + + +usrp1_sink_c::usrp1_sink_c (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : usrp1_sink_base ("usrp1_sink_c", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + which_board, interp_rate, nchan, mux, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) +{ +} + +usrp1_sink_c::~usrp1_sink_c () +{ + // NOP +} + +/* + * Take one complex input stream and format it into interleaved short I & Q + * for the usrp. + */ +void +usrp1_sink_c::copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, // out + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written) // out +{ + gr_complex *in = &((gr_complex *) input_items[0])[input_index]; + short *dst = (short *) usrp_buffer; + + static const int usrp_bytes_per_input_item = 2 * sizeof (short); // I & Q + + int nitems = std::min (input_items_available, + usrp_buffer_length / usrp_bytes_per_input_item); + + for (int i = 0; i < nitems; i++){ + dst[2*i + 0] = host_to_usrp_short((short) real(in[i])); // FIXME saturate? + dst[2*i + 1] = host_to_usrp_short((short) imag(in[i])); // FIXME saturate? + } + + input_items_consumed = nitems; + bytes_written = nitems * usrp_bytes_per_input_item; +} + diff --git a/gr-usrp/src/usrp1_sink_c.h b/gr-usrp/src/usrp1_sink_c.h new file mode 100644 index 00000000..15d92a9c --- /dev/null +++ b/gr-usrp/src/usrp1_sink_c.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP1_SINK_C_H +#define INCLUDED_USRP1_SINK_C_H + +#include + +class usrp1_sink_c; +typedef boost::shared_ptr usrp1_sink_c_sptr; + + +// public shared_ptr constructor + +usrp1_sink_c_sptr +usrp1_make_sink_c (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + +/*! + * \brief interface to Universal Software Radio Peripheral Tx path (Rev 1) + * + * input: gr_complex + */ +class usrp1_sink_c : public usrp1_sink_base { + private: + + friend usrp1_sink_c_sptr + usrp1_make_sink_c (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + protected: + usrp1_sink_c (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written); + public: + ~usrp1_sink_c (); +}; + +#endif /* INCLUDED_USRP1_SINK_C_H */ diff --git a/gr-usrp/src/usrp1_sink_s.cc b/gr-usrp/src/usrp1_sink_s.cc new file mode 100644 index 00000000..634eb5ae --- /dev/null +++ b/gr-usrp/src/usrp1_sink_s.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +usrp1_sink_s_sptr +usrp1_make_sink_s (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) +{ + return usrp1_sink_s_sptr (new usrp1_sink_s (which_board, + interp_rate, + nchan, + mux, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename + )); +} + + +usrp1_sink_s::usrp1_sink_s (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : usrp1_sink_base ("usrp1_sink_s", + gr_make_io_signature (1, 1, sizeof (short)), + which_board, interp_rate, nchan, mux, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) +{ + set_output_multiple (512 / sizeof(short)); // don't change +} + +usrp1_sink_s::~usrp1_sink_s () +{ + // NOP +} + +/* + * Take one short input stream and format it into interleaved short I & Q + * for the usrp. + */ +void +usrp1_sink_s::copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, // out + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written) // out +{ + short *in = &((short *) input_items[0])[input_index]; + short *dst = (short *) usrp_buffer; + + static const int usrp_bytes_per_input_item = sizeof (short); + + int nitems = std::min (input_items_available, + usrp_buffer_length / usrp_bytes_per_input_item); + + for (int i = 0; i < nitems; i++){ // FIXME unroll + dst[i] = host_to_usrp_short(in[i]); + } + + input_items_consumed = nitems; + bytes_written = nitems * usrp_bytes_per_input_item; +} + diff --git a/gr-usrp/src/usrp1_sink_s.h b/gr-usrp/src/usrp1_sink_s.h new file mode 100644 index 00000000..a2e086ca --- /dev/null +++ b/gr-usrp/src/usrp1_sink_s.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP1_SINK_S_H +#define INCLUDED_USRP1_SINK_S_H + +#include + +class usrp1_sink_s; +typedef boost::shared_ptr usrp1_sink_s_sptr; + + +// public shared_ptr constructor + +usrp1_sink_s_sptr +usrp1_make_sink_s (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + +/*! + * \brief interface to Universal Software Radio Peripheral Tx path (Rev 1) + * + * input: short + */ +class usrp1_sink_s : public usrp1_sink_base { + private: + + friend usrp1_sink_s_sptr + usrp1_make_sink_s (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + protected: + usrp1_sink_s (int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written); + public: + ~usrp1_sink_s (); +}; + +#endif /* INCLUDED_USRP1_SINK_S_H */ diff --git a/gr-usrp/src/usrp1_source_base.cc b/gr-usrp/src/usrp1_source_base.cc new file mode 100644 index 00000000..9f5cb251 --- /dev/null +++ b/gr-usrp/src/usrp1_source_base.cc @@ -0,0 +1,425 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static const int OUTPUT_MULTIPLE_BYTES = 4 * 1024; + +usrp1_source_base::usrp1_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : gr_sync_block (name, + gr_make_io_signature (0, 0, 0), + output_signature), + d_noverruns (0) +{ + d_usrp = usrp_standard_rx::make (which_board, decim_rate, + nchan, mux, mode, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename); + if (d_usrp == 0) + throw std::runtime_error ("can't open usrp1"); + + // All calls to d_usrp->read must be multiples of 512 bytes. + // We jack this up to 4k to reduce overhead. + + set_output_multiple (OUTPUT_MULTIPLE_BYTES / output_signature->sizeof_stream_item (0)); +} + +usrp1_source_base::~usrp1_source_base () +{ + delete d_usrp; +} + +unsigned int +usrp1_source_base::sizeof_basic_sample() const +{ + return usrp_standard_rx::format_width(d_usrp->format()) / 8; +} + +bool +usrp1_source_base::start() +{ + return d_usrp->start(); +} + +bool +usrp1_source_base::stop() +{ + return d_usrp->stop(); +} + +int +usrp1_source_base::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + static const int BUFSIZE = 4 * OUTPUT_MULTIPLE_BYTES; + unsigned char buf[BUFSIZE]; + int output_index = 0; + int output_items_produced; + int bytes_read; + bool overrun; + + while (output_index < noutput_items){ + int nbytes = ninput_bytes_reqd_for_noutput_items (noutput_items - output_index); + nbytes = std::min (nbytes, BUFSIZE); + + int result_nbytes = d_usrp->read (buf, nbytes, &overrun); + if (overrun){ + // fprintf (stderr, "usrp1_source: overrun\n"); + fputs ("uO", stderr); + d_noverruns++; + } + + if (result_nbytes < 0) // We've got a problem. Usually board unplugged or powered down. + return -1; // Indicate we're done. + + if (result_nbytes != nbytes){ // not really an error, but unexpected + fprintf (stderr, "usrp1_source: short read. Expected %d, got %d\n", + nbytes, result_nbytes); + } + + copy_from_usrp_buffer (output_items, + output_index, + noutput_items - output_index, // output_items_available + output_items_produced, // [out] + buf, // usrp_buffer + result_nbytes, // usrp_buffer_length + bytes_read); // [out] + + assert (output_index + output_items_produced <= noutput_items); + assert (bytes_read == result_nbytes); + + output_index += output_items_produced; + } + + return noutput_items; +} + + +bool +usrp1_source_base::set_decim_rate (unsigned int rate) +{ + return d_usrp->set_decim_rate (rate); +} + +bool +usrp1_source_base::set_nchannels (int nchan) +{ + return d_usrp->set_nchannels (nchan); +} + +bool +usrp1_source_base::set_mux (int mux) +{ + return d_usrp->set_mux (mux); +} + +bool +usrp1_source_base::set_rx_freq (int channel, double freq) +{ + return d_usrp->set_rx_freq (channel, freq); +} + +long +usrp1_source_base::fpga_master_clock_freq() const +{ + return d_usrp->fpga_master_clock_freq(); +} + +long +usrp1_source_base::converter_rate() const +{ + return d_usrp->converter_rate(); +} + +unsigned int +usrp1_source_base::decim_rate () const +{ + return d_usrp->decim_rate (); +} + +int +usrp1_source_base::nchannels () const +{ + return d_usrp->nchannels (); +} + +int +usrp1_source_base::mux () const +{ + return d_usrp->mux (); +} + +double +usrp1_source_base::rx_freq (int channel) const +{ + return d_usrp->rx_freq (channel); +} + +bool +usrp1_source_base::set_fpga_mode (int mode) +{ + return d_usrp->set_fpga_mode (mode); +} + +bool +usrp1_source_base::set_ddc_phase (int channel, int phase) +{ + return d_usrp->set_ddc_phase(channel, phase); +} + +bool +usrp1_source_base::set_dc_offset_cl_enable(int bits, int mask) +{ + return d_usrp->set_dc_offset_cl_enable(bits, mask); +} + +void +usrp1_source_base::set_verbose (bool verbose) +{ + d_usrp->set_verbose (verbose); +} + +bool +usrp1_source_base::write_aux_dac (int which_dboard, int which_dac, int value) +{ + return d_usrp->write_aux_dac (which_dboard, which_dac, value); +} + +int +usrp1_source_base::read_aux_adc (int which_dboard, int which_adc) +{ + return d_usrp->read_aux_adc (which_dboard, which_adc); +} + +bool +usrp1_source_base::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) +{ + return d_usrp->write_eeprom (i2c_addr, eeprom_offset, buf); +} + +std::string +usrp1_source_base::read_eeprom (int i2c_addr, int eeprom_offset, int len) +{ + return d_usrp->read_eeprom (i2c_addr, eeprom_offset, len); +} + +bool +usrp1_source_base::write_i2c (int i2c_addr, const std::string buf) +{ + return d_usrp->write_i2c (i2c_addr, buf); +} + +std::string +usrp1_source_base::read_i2c (int i2c_addr, int len) +{ + return d_usrp->read_i2c (i2c_addr, len); +} + +bool +usrp1_source_base::set_pga (int which, double gain) +{ + return d_usrp->set_pga (which, gain); +} + +double +usrp1_source_base::pga (int which) const +{ + return d_usrp->pga (which); +} + +double +usrp1_source_base::pga_min () const +{ + return d_usrp->pga_min (); +} + +double +usrp1_source_base::pga_max () const +{ + return d_usrp->pga_max (); +} + +double +usrp1_source_base::pga_db_per_step () const +{ + return d_usrp->pga_db_per_step (); +} + +int +usrp1_source_base::daughterboard_id (int which) const +{ + return d_usrp->daughterboard_id (which); +} + + +bool +usrp1_source_base::set_adc_offset (int which, int offset) +{ + return d_usrp->set_adc_offset (which, offset); +} + +bool +usrp1_source_base::set_dac_offset (int which, int offset, int offset_pin) +{ + return d_usrp->set_dac_offset (which, offset, offset_pin); +} + +bool +usrp1_source_base::set_adc_buffer_bypass (int which, bool bypass) +{ + return d_usrp->set_adc_buffer_bypass (which, bypass); +} + +std::string +usrp1_source_base::serial_number() +{ + return d_usrp->serial_number(); +} + +bool +usrp1_source_base::_write_oe (int which_dboard, int value, int mask) +{ + return d_usrp->_write_oe (which_dboard, value, mask); +} + +bool +usrp1_source_base::write_io (int which_dboard, int value, int mask) +{ + return d_usrp->write_io (which_dboard, value, mask); +} + +int +usrp1_source_base::read_io (int which_dboard) +{ + return d_usrp->read_io (which_dboard); +} + + + + +// internal routines... + +bool +usrp1_source_base::_write_fpga_reg (int regno, int value) +{ + return d_usrp->_write_fpga_reg (regno, value); +} + +bool +usrp1_source_base::_write_fpga_reg_masked (int regno, int value, int mask) +{ + return d_usrp->_write_fpga_reg_masked (regno, value, mask); +} + +int +usrp1_source_base::_read_fpga_reg (int regno) +{ + return d_usrp->_read_fpga_reg (regno); +} + +bool +usrp1_source_base::_write_9862 (int which_codec, int regno, unsigned char value) +{ + return d_usrp->_write_9862 (which_codec, regno, value); +} + +int +usrp1_source_base::_read_9862 (int which_codec, int regno) const +{ + return d_usrp->_read_9862 (which_codec, regno); +} + +bool +usrp1_source_base::_write_spi (int optional_header, int enables, + int format, std::string buf) +{ + return d_usrp->_write_spi (optional_header, enables, format, buf); +} + +std::string +usrp1_source_base::_read_spi (int optional_header, int enables, int format, int len) +{ + return d_usrp->_read_spi (optional_header, enables, format, len); +} + +bool +usrp1_source_base::set_format(unsigned int format) +{ + return d_usrp->set_format(format); +} + +unsigned int +usrp1_source_base::format() const +{ + return d_usrp->format(); +} + +unsigned int +usrp1_source_base::make_format(int width, int shift, bool want_q, bool bypass_halfband) +{ + return usrp_standard_rx::make_format(width, shift, want_q, bypass_halfband); +} + +int +usrp1_source_base::format_width(unsigned int format) +{ + return usrp_standard_rx::format_width(format); +} + +int +usrp1_source_base::format_shift(unsigned int format) +{ + return usrp_standard_rx::format_shift(format); +} + +bool +usrp1_source_base::format_want_q(unsigned int format) +{ + return usrp_standard_rx::format_want_q(format); +} + +bool +usrp1_source_base::format_bypass_halfband(unsigned int format) +{ + return usrp_standard_rx::format_bypass_halfband(format); +} diff --git a/gr-usrp/src/usrp1_source_base.h b/gr-usrp/src/usrp1_source_base.h new file mode 100644 index 00000000..a04eadf2 --- /dev/null +++ b/gr-usrp/src/usrp1_source_base.h @@ -0,0 +1,455 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP1_SOURCE_BASE_H +#define INCLUDED_USRP1_SOURCE_BASE_H + +#include +#include + +class usrp_standard_rx; + +/*! + * \brief abstract interface to Universal Software Radio Peripheral Rx path (Rev 1) + */ +class usrp1_source_base : public gr_sync_block { + private: + usrp_standard_rx *d_usrp; + int d_noverruns; + + protected: + usrp1_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + /*! + * \brief return number of usrp input bytes required to produce noutput items. + */ + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; + + /*! + * \brief number of bytes in a low-level sample + */ + unsigned int sizeof_basic_sample() const; + + /*! + * \brief convert between native usrp format and output item format + * + * \param output_items[out] stream(s) of output items + * \param output_index[in] starting index in output_items + * \param output_items_available[in] number of empty items available at item[index] + * \param output_items_produced[out] number of items produced by copy + * \param usrp_buffer[in] source buffer + * \param usrp_buffer_length[in] number of bytes available in \p usrp_buffer + * \param bytes_read[out] number of bytes read from \p usrp_buffer + * + * The copy must consume all bytes available. That is, \p bytes_read must equal + * \p usrp_buffer_length. + */ + virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read) = 0; + + public: + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; + + ~usrp1_source_base (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool start(); + bool stop(); + + /*! + * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () + */ + bool set_decim_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + + /*! + * \brief set the center frequency of the digital down converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-FIXME, FIXME]. The frequency specified is + * quantized. Use rx_freq to retrieve the actual value used. + */ + bool set_rx_freq (int channel, double freq); + + /*! + * \brief set fpga special modes + */ + bool set_fpga_mode (int mode); + + void set_verbose (bool verbose); + + /*! + * \brief Set the digital down converter phase register. + * + * \param channel which ddc channel [0, 3] + * \param phase 32-bit integer phase value. + */ + bool set_ddc_phase(int channel, int phase); + + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which A/D [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param which which A/D [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA setting in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA setting in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + // ACCESSORS + + long fpga_master_clock_freq() const; + long converter_rate() const; + long adc_rate() const { return converter_rate(); } // alias + long adc_freq() const { return converter_rate(); } // deprecated alias + + unsigned int decim_rate () const; + int nchannels () const; + int mux () const; + double rx_freq (int channel) const; + int noverruns () const { return d_noverruns; } + + /*! + * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + int daughterboard_id (int which_dboard) const; + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param which_dboard [0,1] which d'board + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. + * \param which_dac [2,3] TX slots must use only 2 and 3. + * \param value [0,4095] + * \returns true iff successful + */ + bool write_aux_dac (int which_board, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_dboard [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + int read_aux_adc (int which_dboard, int which_adc); + + /*! + * \brief Write EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin writing + * \param buf the data to write + * \returns true iff sucessful + */ + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); + + /*! + * \brief Write EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin reading + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + */ + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + + /*! + * \brief Write to I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of of 64 bytes. + */ + bool write_i2c (int i2c_addr, const std::string buf); + + /*! + * \brief Read from I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + * Reads are limited to a maximum of of 64 bytes. + */ + std::string read_i2c (int i2c_addr, int len); + + /*! + * \brief Set ADC offset correction + * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... + * \param offset 16-bit value to subtract from raw ADC input. + */ + bool set_adc_offset (int which, int offset); + + /*! + * \brief Set DAC offset correction + * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... + * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). + * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; + * If 1 offset applied to +ve differential pin. + */ + bool set_dac_offset (int which, int offset, int offset_pin); + + /*! + * \brief Control ADC input buffer + * \param which which ADC[0,3] + * \param bypass if non-zero, bypass input buffer and connect input + * directly to switched cap SHA input of RxPGA. + */ + bool set_adc_buffer_bypass (int which, bool bypass); + + /*! + * \brief return the usrp's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + * + * Each d'board has 16-bits of general purpose i/o. + * Setting the bit makes it an output from the FPGA to the d'board. + * + * This register is initialized based on a value stored in the + * d'board EEPROM. In general, you shouldn't be using this routine + * without a very good reason. Using this method incorrectly will + * kill your USRP motherboard and/or daughterboard. + */ + bool _write_oe (int which_dboard, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool write_io (int which_dboard, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int read_io (int which_dboard); + + /*! + * \brief Enable/disable automatic DC offset removal control loop in FPGA + * + * \param bits which control loops to enable + * \param mask which \p bits to pay attention to + * + * If the corresponding bit is set, enable the automatic DC + * offset correction control loop. + * + *
+   * The 4 low bits are significant:
+   *
+   *   ADC0 = (1 << 0)
+   *   ADC1 = (1 << 1)
+   *   ADC2 = (1 << 2)
+   *   ADC3 = (1 << 3)
+   * 
+ * + * By default the control loop is enabled on all ADC's. + */ + bool set_dc_offset_cl_enable(int bits, int mask); + + /*! + * \brief Specify Rx data format. + * + * \param format format specifier + * + * Rx data format control register + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------------------------------------+-+-+---------+-------+ + * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | + * +-----------------------------------------+-+-+---------+-------+ + * + * SHIFT specifies arithmetic right shift [0, 15] + * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) + * Q if set deliver both I & Q, else just I + * B if set bypass half-band filter. + * + * Right now the acceptable values are: + * + * B Q WIDTH SHIFT + * 0 1 16 0 + * 0 1 8 8 + * + * More valid combos to come. + * + * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. + */ + bool set_format(unsigned int format); + + /*! + * \brief return current format + */ + unsigned int format () const; + + static unsigned int make_format(int width=16, int shift=0, + bool want_q=true, bool bypass_halfband=false); + static int format_width(unsigned int format); + static int format_shift(unsigned int format); + static bool format_want_q(unsigned int format); + static bool format_bypass_halfband(unsigned int format); + + // ---------------------------------------------------------------- + // internal routines... + // You probably shouldn't be using these... + // ---------------------------------------------------------------- + + /*! + * \brief Write FPGA register. + * \param regno 7-bit register number + * \param value 32-bit value + * \returns true iff successful + */ + bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value + + /*! + * \brief Write FPGA register masked. + * \param regno 7-bit register number + * \param value 16-bit value + * \param mask 16-bit mask + * \returns true iff successful + */ + bool _write_fpga_reg_masked (int regno, int value, int mask); //< 7-bit regno, 16-bit value, 16-bit mask + + /*! + * \brief Read FPGA register. + * \param regno 7-bit register number + * \returns register value if successful, else READ_FAILED + */ + int _read_fpga_reg (int regno); + + /*! + * \brief Write AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \param value 8-bit value + * \returns true iff successful + */ + bool _write_9862 (int which_codec, int regno, unsigned char value); + + /*! + * \brief Read AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \returns register value if successful, else READ_FAILED + */ + int _read_9862 (int which_codec, int regno) const; + + /*! + * \brief Write data to SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripherals to write. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they are + * written to the peripheral immediately prior to writing \p buf. + */ + bool _write_spi (int optional_header, int enables, int format, std::string buf); + + /* + * \brief Read data from SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripheral to read. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param len number of bytes to read. Must be in [0,64]. + * \returns the data read if sucessful, else a zero length string. + * + * Reads are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they + * are written to the peripheral first. Then \p len bytes are read from + * the peripheral and returned. + */ + std::string _read_spi (int optional_header, int enables, int format, int len); +}; + +#endif /* INCLUDED_USRP1_SOURCE_BASE_H */ diff --git a/gr-usrp/src/usrp1_source_c.cc b/gr-usrp/src/usrp1_source_c.cc new file mode 100644 index 00000000..e6143700 --- /dev/null +++ b/gr-usrp/src/usrp1_source_c.cc @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static const int NBASIC_SAMPLES_PER_ITEM = 2; // I & Q + +usrp1_source_c_sptr +usrp1_make_source_c (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) +{ + return usrp1_source_c_sptr (new usrp1_source_c (which_board, + decim_rate, + nchan, + mux, + mode, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename + )); +} + + +usrp1_source_c::usrp1_source_c (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : usrp1_source_base ("usrp1_source_c", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + which_board, decim_rate, nchan, mux, mode, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename) +{ +} + +usrp1_source_c::~usrp1_source_c () +{ + // NOP +} + +int +usrp1_source_c::ninput_bytes_reqd_for_noutput_items (int noutput_items) +{ + return noutput_items * NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); +} + +/* + * Convert interleaved 8 or 16-bit I & Q from usrp buffer into a single + * complex output stream. + */ +void +usrp1_source_c::copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read) +{ + gr_complex *out = &((gr_complex *) output_items[0])[output_index]; + unsigned sbs = sizeof_basic_sample(); + unsigned nusrp_bytes_per_item = NBASIC_SAMPLES_PER_ITEM * sbs; + + int nitems = std::min (output_items_available, + (int)(usrp_buffer_length / nusrp_bytes_per_item)); + + signed char *s8 = (signed char *) usrp_buffer; + short *s16 = (short *) usrp_buffer; + + switch (sbs){ + case 1: + for (int i = 0; i < nitems; i++){ + out[i] = gr_complex ((float)(s8[2*i+0] << 8), (float)(s8[2*i+1] << 8)); + } + break; + + case 2: + for (int i = 0; i < nitems; i++){ + out[i] = gr_complex ((float) usrp_to_host_short(s16[2*i+0]), + (float) usrp_to_host_short(s16[2*i+1])); + } + break; + + default: + assert(0); + } + + output_items_produced = nitems; + bytes_read = nitems * nusrp_bytes_per_item; +} diff --git a/gr-usrp/src/usrp1_source_c.h b/gr-usrp/src/usrp1_source_c.h new file mode 100644 index 00000000..4b874935 --- /dev/null +++ b/gr-usrp/src/usrp1_source_c.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP1_SOURCE_C_H +#define INCLUDED_USRP1_SOURCE_C_H + +#include +#include + +class usrp_standard_rx; + + +class usrp1_source_c; +typedef boost::shared_ptr usrp1_source_c_sptr; + + +// public shared_ptr constructor + +usrp1_source_c_sptr +usrp1_make_source_c (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + +/*! + * \brief interface to Universal Software Radio Peripheral Rx path (Rev 1) + */ +class usrp1_source_c : public usrp1_source_base { + private: + friend usrp1_source_c_sptr + usrp1_make_source_c (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + protected: + usrp1_source_c (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items); + + virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read); + + public: + ~usrp1_source_c (); +}; + +#endif /* INCLUDED_USRP1_SOURCE_C_H */ diff --git a/gr-usrp/src/usrp1_source_s.cc b/gr-usrp/src/usrp1_source_s.cc new file mode 100644 index 00000000..c2c105bc --- /dev/null +++ b/gr-usrp/src/usrp1_source_s.cc @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static const int NBASIC_SAMPLES_PER_ITEM = 1; + +usrp1_source_s_sptr +usrp1_make_source_s (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) +{ + return usrp1_source_s_sptr (new usrp1_source_s (which_board, + decim_rate, + nchan, + mux, + mode, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename + )); +} + + +usrp1_source_s::usrp1_source_s (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : usrp1_source_base ("usrp1_source_s", + gr_make_io_signature (1, 1, sizeof (short)), + which_board, decim_rate, nchan, mux, mode, + fusb_block_size, + fusb_nblocks, + fpga_filename, firmware_filename) +{ +} + +usrp1_source_s::~usrp1_source_s () +{ + // NOP +} + +int +usrp1_source_s::ninput_bytes_reqd_for_noutput_items (int noutput_items) +{ + return noutput_items * NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); +} + +/* + * Convert interleaved 8 or 16-bit I & Q from usrp buffer into a single + * short output stream. + */ +void +usrp1_source_s::copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read) +{ + short *out = &((short *) output_items[0])[output_index]; + unsigned sbs = sizeof_basic_sample(); + unsigned nusrp_bytes_per_item = NBASIC_SAMPLES_PER_ITEM * sbs; + + int nitems = std::min (output_items_available, + (int)(usrp_buffer_length / nusrp_bytes_per_item)); + + signed char *s8 = (signed char *) usrp_buffer; + short *s16 = (short *) usrp_buffer; + + switch(sbs){ + case 1: + for (int i = 0; i < nitems; i++){ + out[i] = s8[i] << 8; + } + break; + + case 2: + for (int i = 0; i < nitems; i++){ + out[i] = usrp_to_host_short(s16[i]); + } + break; + + default: + assert(0); + } + + output_items_produced = nitems; + bytes_read = nitems * nusrp_bytes_per_item; +} diff --git a/gr-usrp/src/usrp1_source_s.h b/gr-usrp/src/usrp1_source_s.h new file mode 100644 index 00000000..a3a3e743 --- /dev/null +++ b/gr-usrp/src/usrp1_source_s.h @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP1_SOURCE_S_H +#define INCLUDED_USRP1_SOURCE_S_H + +#include +#include + +class usrp_standard_rx; + + +class usrp1_source_s; +typedef boost::shared_ptr usrp1_source_s_sptr; + + +// public shared_ptr constructor + +usrp1_source_s_sptr +usrp1_make_source_s (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + +/*! + * \brief interface to Universal Software Radio Peripheral Rx path (Rev 1) + * + * output: 1 stream of short + */ +class usrp1_source_s : public usrp1_source_base { + private: + friend usrp1_source_s_sptr + usrp1_make_source_s (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + protected: + usrp1_source_s (int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items); + + virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read); + public: + ~usrp1_source_s (); +}; + +#endif /* INCLUDED_USRP1_SOURCE_S_H */ diff --git a/gr-usrp/src/usrp_multi.py b/gr-usrp/src/usrp_multi.py new file mode 100644 index 00000000..865e42fa --- /dev/null +++ b/gr-usrp/src/usrp_multi.py @@ -0,0 +1,233 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import math +from gnuradio import gr, gru +from gnuradio.gr import hier_block_base +from gnuradio import usrp +from gnuradio import usrp1 # usrp Rev 1 and later +from gnuradio import blks +import usrp_prims +import sys + + +class multi_source_align(object): + def __init__(self, fg, master_serialno,decim,nchan=2,pga_gain=0.0,cordic_freq=0.0,mux=None,align_interval=-1): + """ + Align multiple sources (usrps) using samplenumbers in the first channel. + + Takes two ore more sources producing interleaved shorts. + produces nchan * nsources gr_complex output streams. + + @param nchan: number of interleaved channels in source + @param align_interval: number of samples to minimally skip between alignments + default = -1 which means align only once per work call. + @param master_serial_no: serial number of the source which must be the master. + + + Exported sub-blocks (attributes): + master_source + slave_source + usrp_master + usrp_slave + """ + mode=usrp.FPGA_MODE_NORMAL + mode = mode | usrp_prims.bmFR_MODE_RX_COUNTING_32BIT #(1 << 2) #usrp1.FPGA_MODE_COUNTING_32BIT + align=gr.align_on_samplenumbers_ss (nchan,align_interval) + self.usrp_master = None + self.usrp_slave = None + # um is master usrp + # us is slave usrp + if mux is None: + mux=self.get_default_mux() #Note that all channels have shifted left because of the added 32 bit counter channel + + u1 = usrp.source_s (1, decim, nchan, gru.hexint(mux), mode,fpga_filename="multi_2rxhb_2tx.rbf" ) + u0 = usrp.source_s (0, decim, nchan, gru.hexint(mux), mode,fpga_filename="multi_2rxhb_2tx.rbf" ) + print 'usrp[0] serial',u0.serial_number() + print 'usrp[1] serial',u1.serial_number() + #default, choose the second found usrp as master (which is usually the usrp which was first plugged in) + um_index=1 + um=u1 + us_index=0 + us=u0 + if (not (master_serialno is None)): #((master_serialno>0) | (master_serialno <-2)): + if (u0.serial_number() == master_serialno): + um_index=0 + um=u0 + us_index=1 + us=u1 + elif (u1.serial_number() != master_serialno): + errorstring = 'Error. requested master_serialno ' + master_serialno +' not found\n' + errorstring = errorstring + 'Available are:\n' + errorstring = errorstring + 'usrp[1] serial_no = ' + u1.serial_number() +'\n' + errorstring = errorstring + 'usrp[0] serial_no = ' + u0.serial_number() +'\n' + print errorstring + raise ValueError, errorstring + else: #default, just choose the first found usrp as master + um_index=0 + um=u0 + us_index=1 + us=u1 + + self.usrp_master=um + self.usrp_slave=us + print 'usrp_master=usrp[%i] serial_no = %s' % (um_index,self.usrp_master.serial_number() ,) + print 'usrp_slave=usrp[%i] serial_no = %s' % (us_index,self.usrp_slave.serial_number() ,) + self.subdev_mAr = usrp.selected_subdev(self.usrp_master, (0,0)) + self.subdev_mBr = usrp.selected_subdev(self.usrp_master, (1,0)) + self.subdev_sAr = usrp.selected_subdev(self.usrp_slave, (0,0)) + self.subdev_sBr = usrp.selected_subdev(self.usrp_slave, (1,0)) + #throttle = gr.throttle(gr.sizeof_gr_complex, input_rate) + if not (pga_gain is None): + um.set_pga (0, pga_gain) + um.set_pga (1, pga_gain) + + us.set_pga (0, pga_gain) + us.set_pga (1, pga_gain) + + self.input_rate = um.adc_freq () / um.decim_rate () + deintm=gr.deinterleave(gr.sizeof_gr_complex) + deints=gr.deinterleave(gr.sizeof_gr_complex) + nullsinkm=gr.null_sink(gr.sizeof_gr_complex) + nullsinks=gr.null_sink(gr.sizeof_gr_complex) + + tocomplexm=gr.interleaved_short_to_complex() + tocomplexs=gr.interleaved_short_to_complex() + + fg.connect(um,(align,0)) + fg.connect(us,(align,1)) + fg.connect((align,0),tocomplexm) + fg.connect((align,1),tocomplexs) + fg.connect(tocomplexm,deintm) + fg.connect(tocomplexs,deints) + fg.connect((deintm,0),nullsinkm) #The counters are not usefull for the user but must be connected to something + fg.connect((deints,0),nullsinks) #The counters are not usefull for the user but must be connected to something + if 4==nchan: + nullsinkm3=gr.null_sink(gr.sizeof_gr_complex) + nullsinks3=gr.null_sink(gr.sizeof_gr_complex) + fg.connect((deintm,3), nullsinkm3) #channel 4 is not used but must be connected + fg.connect((deints,3), nullsinks3) #channel 4 is not used but must be connected + + self.fg=fg + self.master_source=deintm + self.slave_source=deints + + if not (cordic_freq is None): + um.set_rx_freq (1, cordic_freq) + um.set_rx_freq (0, cordic_freq) + us.set_rx_freq (1, cordic_freq) + us.set_rx_freq (0, cordic_freq) + + self.enable_master_and_slave() + # add an idle handler + self.unsynced=True + + # wire the block together + #hier_block_multi_tail.__init__(self, fg, nchan,deintm,deints) + + def get_default_mux(self): + return 0x10321032 # Note that all channels have shifted left because of the added 32 bit counter channel + + def get_master_source_c(self): + return self.master_source + + def get_slave_source_c(self): + return self.slave_source + + def get_master_usrp(self): + return self.usrp_master + + def get_slave_usrp(self): + return self.usrp_slave + + def enable_master_and_slave(self): + # Warning, allways FIRST enable the slave before you enable the master + # This is to be sure you don't have two masters connecting to each other + # Otherwise you could ruin your hardware because the two sync outputs would be connected together + + #SLAVE + #disable master, enable slave and set sync pulse to zero + reg_mask = usrp_prims.bmFR_RX_SYNC_SLAVE | usrp_prims.bmFR_RX_SYNC_MASTER | usrp_prims.bmFR_RX_SYNC + self.usrp_slave._u._write_fpga_reg_masked(usrp_prims.FR_RX_MASTER_SLAVE, usrp_prims.bmFR_RX_SYNC_SLAVE,reg_mask) + #set SYNC slave iopin on daughterboards RXA as input + oe = 0 # set rx_a_io[bitnoFR_RX_SYNC_INPUT_IOPIN] as input + oe_mask = usrp_prims.bmFR_RX_SYNC_INPUT_IOPIN + self.usrp_slave._u._write_oe(0,oe,oe_mask) + #Now it is save to enable the master + + #MASTER + #enable master, disable slave and set sync pulse to zero + reg_mask = usrp_prims.bmFR_RX_SYNC_SLAVE | usrp_prims.bmFR_RX_SYNC_MASTER | usrp_prims.bmFR_RX_SYNC + self.usrp_master._u._write_fpga_reg_masked(usrp_prims.FR_RX_MASTER_SLAVE,usrp_prims.bmFR_RX_SYNC_MASTER,reg_mask) + #set SYNC master iopin on daughterboards RXA as output + oe = usrp_prims.bmFR_RX_SYNC_OUTPUT_IOPIN # set rx_a_io[bitnoFR_RX_SYNC_OUTPUT_IOPIN] as output + oe_mask = usrp_prims.bmFR_RX_SYNC_OUTPUT_IOPIN + self.usrp_master._u._write_oe(0,oe,oe_mask) + + def sync_usrps(self, evt): + self.sync() + + def sync(self): + result=False + result = self.usrp_master._u._write_fpga_reg_masked (usrp_prims.FR_RX_MASTER_SLAVE, usrp_prims.bmFR_RX_SYNC, usrp_prims.bmFR_RX_SYNC ) + #There should be a small delay here, but the time it takes to get the sync to the usrp is long enough + #turn sync pulse off + result = result & self.usrp_master._u._write_fpga_reg_masked (usrp_prims.FR_RX_MASTER_SLAVE,0 ,usrp_prims.bmFR_RX_SYNC); + return result; + + def nullsink_counters(self): + nullsinkm=gr.null_sink(gr.sizeof_gr_complex) + nullsinks=gr.null_sink(gr.sizeof_gr_complex) + self.fg.connect((self.master_source,0),nullsinkm) + self.fg.connect((self.slave_source,0),nullsinks) + + + def print_db_info(self): + print "MASTER RX d'board %s" % (self.subdev_mAr.side_and_name(),) + print "MASTER RX d'board %s" % (self.subdev_mBr.side_and_name(),) + #print "TX d'board %s" % (self.subdev_At.side_and_name(),) + #print "TX d'board %s" % (self.subdev_Bt.side_and_name(),) + print "SLAVE RX d'board %s" % (self.subdev_sAr.side_and_name(),) + print "SLAVE RX d'board %s" % (self.subdev_sBr.side_and_name(),) + #print "TX d'board %s" % (self.subdev_At.side_and_name(),) + #print "TX d'board %s" % (self.subdev_Bt.side_and_name(),) + + def tune_all_rx(self,target_freq): + result = True + r1 = usrp.tune(self.usrp_master, 0, self.subdev_mAr, target_freq) + if r1 is None: + result=False + r2 = usrp.tune(self.usrp_master, 1, self.subdev_mBr, target_freq) + if r2 is None: + result=False + r3 = usrp.tune(self.usrp_slave, 0, self.subdev_sAr, target_freq) + if r3 is None: + result=False + r4 = usrp.tune(self.usrp_slave, 1, self.subdev_sBr, target_freq) + if r4 is None: + result=False + return result,r1,r2,r3,r4 + + def set_gain_all_rx(self, gain): + self.subdev_mAr.set_gain(gain) + self.subdev_mBr.set_gain(gain) + self.subdev_sAr.set_gain(gain) + self.subdev_sBr.set_gain(gain) diff --git a/gr-video-sdl/AUTHORS b/gr-video-sdl/AUTHORS new file mode 100644 index 00000000..3e57f56d --- /dev/null +++ b/gr-video-sdl/AUTHORS @@ -0,0 +1 @@ +Martin Dudok van Heel diff --git a/gr-video-sdl/ChangeLog b/gr-video-sdl/ChangeLog new file mode 100644 index 00000000..f142ef80 --- /dev/null +++ b/gr-video-sdl/ChangeLog @@ -0,0 +1,25 @@ +2006-02-21 Martin Dudok van Heel + + Initial release + * src/video_sdl_sink.{h,cc,i}: new. + +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-video-sdl/Makefile.am b/gr-video-sdl/Makefile.am new file mode 100644 index 00000000..12d751e7 --- /dev/null +++ b/gr-video-sdl/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src diff --git a/gr-video-sdl/src/Makefile.am b/gr-video-sdl/src/Makefile.am new file mode 100644 index 00000000..0a28e0ce --- /dev/null +++ b/gr-video-sdl/src/Makefile.am @@ -0,0 +1,86 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.video_sdl module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in +TESTS = run_tests + +LOCAL_IFILES = \ + video_sdl.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + video_sdl.cc \ + video_sdl.py + +ourpython_PYTHON = \ + video_sdl.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(SDL_CFLAGS) + +SWIGCPPPYTHONARGS = -fvirtual -python -modern $(PYTHON_CPPFLAGS) $(STD_DEFINES_AND_INCLUDES) + +ourlib_LTLIBRARIES = _video_sdl.la + +_video_sdl_la_SOURCES = \ + video_sdl.cc \ + video_sdl_sink_uc.cc \ + video_sdl_sink_s.cc + + +grinclude_HEADERS = \ + video_sdl_sink_uc.h \ + video_sdl_sink_s.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_video_sdl_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + $(GNURADIO_CORE_LIBS) \ + $(SDL_LIBS) \ + -lstdc++ + +_video_sdl_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +video_sdl.cc video_sdl.py: video_sdl.i + $(SWIG) $(SWIGCPPPYTHONARGS) -module video_sdl -o video_sdl.cc $< + + +noinst_PYTHON = qa_video_sdl.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc + diff --git a/gr-video-sdl/src/qa_video_sdl.py b/gr-video-sdl/src/qa_video_sdl.py new file mode 100755 index 00000000..905b2871 --- /dev/null +++ b/gr-video-sdl/src/qa_video_sdl.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import video_sdl + +class qa_video_sdl (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have video drivers, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-video-sdl/src/run_tests.in b/gr-video-sdl/src/run_tests.in new file mode 100644 index 00000000..2f84c378 --- /dev/null +++ b/gr-video-sdl/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-video-sdl/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-video-sdl/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-video-sdl/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gr-video-sdl/src/video_sdl.i b/gr-video-sdl/src/video_sdl.i new file mode 100644 index 00000000..e70d1235 --- /dev/null +++ b/gr-video-sdl/src/video_sdl.i @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "video_sdl_sink_uc.h" +#include "video_sdl_sink_s.h" +#include +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(video_sdl,sink_uc) + +video_sdl_sink_uc_sptr +video_sdl_make_sink_uc ( double framerate,int width=640, int height=480,unsigned int format=0,int dst_width=-1,int dst_height=-1 + ) throw (std::runtime_error); + + +class video_sdl_sink_uc : public gr_sync_block { + protected: + video_sdl_sink_uc (double framerate,int width, int height,gr_uint32 format,int dst_width,int dst_height); + + public: + ~video_sdl_sink_uc (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(video_sdl,sink_s) + +video_sdl_sink_s_sptr +video_sdl_make_sink_s ( double framerate,int width=640, int height=480,unsigned int format=0,int dst_width=-1,int dst_height=-1 + ) throw (std::runtime_error); + + +class video_sdl_sink_s : public gr_sync_block { + protected: + video_sdl_sink_s (double framerate,int width, int height,gr_uint32 format,int dst_width,int dst_height); + + public: + ~video_sdl_sink_s (); +}; diff --git a/gr-video-sdl/src/video_sdl_sink_s.cc b/gr-video-sdl/src/video_sdl_sink_s.cc new file mode 100644 index 00000000..50e730db --- /dev/null +++ b/gr-video-sdl/src/video_sdl_sink_s.cc @@ -0,0 +1,301 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +video_sdl_sink_s::video_sdl_sink_s (double framerate,int width, int height,unsigned int format,int dst_width,int dst_height) + : gr_sync_block ("video_sdl_sink_s", + gr_make_io_signature (1, 3, sizeof (short)), + gr_make_io_signature (0, 0, 0)), + d_chunk_size (width*height), + d_framerate(framerate), + d_wanted_frametime_ms(0), + d_width(width), + d_height (height), + d_dst_width(dst_width), + d_dst_height(dst_height), + d_format(format), + d_current_line(0), + d_screen(NULL), + d_image(NULL), + d_avg_delay(0.0), + d_wanted_ticks(0) +{ + if(framerate<=0.0) + d_wanted_frametime_ms=0;//Go as fast as possible + else + d_wanted_frametime_ms=(int)(1000.0/framerate); + if(dst_width<0) d_dst_width=d_width; + if(dst_height<0) d_dst_height=d_height; + if(0==format) d_format=IMGFMT_YV12; + + atexit(SDL_Quit);//check if this is the way to do this + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + std::cerr << "video_sdl_sink_s: Couldn't initialize SDL:" << SDL_GetError() << " \n SDL_Init(SDL_INIT_VIDEO) failed\n"; + throw std::runtime_error ("video_sdl_sink_s"); + }; + + /* accept any depth */ + d_screen = SDL_SetVideoMode(dst_width, dst_height, 0, SDL_SWSURFACE|SDL_RESIZABLE|SDL_ANYFORMAT);//SDL_DOUBLEBUF |SDL_SWSURFACE| SDL_HWSURFACE||SDL_FULLSCREEN + if ( d_screen == NULL ) { + std::cerr << "Unable to set SDL video mode: " << SDL_GetError() <<"\n SDL_SetVideoMode() Failed \n"; + exit(1); + } + if ( d_image ) { + SDL_FreeYUVOverlay(d_image); + } + /* Initialize and create the YUV Overlay used for video out */ + if (!(d_image = SDL_CreateYUVOverlay (d_width, d_height, SDL_YV12_OVERLAY, d_screen))) { + std::cerr << "SDL: Couldn't create a YUV overlay: \n"<< SDL_GetError() <<"\n"; + throw std::runtime_error ("video_sdl_sink_s"); + } + + printf("SDL screen_mode %d bits-per-pixel\n", + d_screen->format->BitsPerPixel); + printf("SDL overlay_mode %i \n", + d_image->format); + d_chunk_size = std::min(1,16384/width); //width*16; + d_chunk_size = d_chunk_size*width; + //d_chunk_size = (int) (width); + set_output_multiple (d_chunk_size); + /* Set the default playback area */ + d_dst_rect.x = 0; + d_dst_rect.y = 0; + d_dst_rect.w = d_dst_width; + d_dst_rect.h = d_dst_height; + //clear the surface to grey + if ( SDL_LockYUVOverlay( d_image ) ) { + std::cerr << "SDL: Couldn't lock YUV overlay: \n"<< SDL_GetError() <<"\n"; + throw std::runtime_error ("video_sdl_sink_s"); + } + memset(d_image->pixels[0], 128, d_image->pitches[0]*d_height); + memset(d_image->pixels[1], 128, d_image->pitches[1]*d_height/2); + memset(d_image->pixels[2], 128, d_image->pitches[2]*d_height/2); + SDL_UnlockYUVOverlay( d_image ); +} + +video_sdl_sink_s::~video_sdl_sink_s () +{ + SDL_Quit(); +} + +video_sdl_sink_s_sptr +video_sdl_make_sink_s (double framerate,int width, int height,unsigned int format,int dst_width,int dst_height) +{ + return video_sdl_sink_s_sptr (new video_sdl_sink_s (framerate, width, height,format,dst_width,dst_height)); +} + +void +video_sdl_sink_s::copy_line_pixel_interleaved(unsigned char *dst_pixels_u,unsigned char *dst_pixels_v,const short * src_pixels,int src_width) +{ + for(int i=0;ipixels[first_dst_plane]; + dst_pixels=&dst_pixels[current_line*d_image->pitches[first_dst_plane]]; + unsigned char * dst_pixels_2 = (unsigned char *)d_image->pixels[second_dst_plane]; + dst_pixels_2=&dst_pixels_2[current_line*d_image->pitches[second_dst_plane]]; + int src_width=(0==plane || 12==plane || 1122==plane)?d_width:d_width/2; + int noutput_items_produced=0; + int max_height=(0==plane)?d_height-1:d_height/2-1; + for (int i = 0; i < noutput_items; i += src_width){ + //output one line at a time + if(12==plane) + { + copy_line_pixel_interleaved(dst_pixels,dst_pixels_2,src_pixels,src_width); + dst_pixels_2 += d_image->pitches[second_dst_plane]; + } + else if (1122==plane) + { + copy_line_line_interleaved(dst_pixels,dst_pixels_2,src_pixels,src_width); + dst_pixels_2 += d_image->pitches[second_dst_plane]; + src_pixels += src_width; + } + else if (0==plane) + copy_line_single_plane(dst_pixels,src_pixels,src_width); + else /* 1==plane || 2==plane*/ + copy_line_single_plane_dec2(dst_pixels,src_pixels,src_width);//decimate by two horizontally + + src_pixels += src_width; + dst_pixels += d_image->pitches[first_dst_plane]; + noutput_items_produced+=src_width; + current_line++; + if (current_line>max_height) + { + //Start new frame + //TODO, do this all in a seperate thread + current_line=0; + dst_pixels=d_image->pixels[first_dst_plane]; + dst_pixels_2=d_image->pixels[second_dst_plane]; + if(0==plane) + { + SDL_DisplayYUVOverlay(d_image, &d_dst_rect); + //SDL_Flip(d_screen); + unsigned int ticks=SDL_GetTicks();//milliseconds + d_wanted_ticks+=d_wanted_frametime_ms; + float avg_alpha=0.1; + int time_diff=d_wanted_ticks-ticks; + d_avg_delay=time_diff*avg_alpha +d_avg_delay*(1.0-avg_alpha); + } + } + } + if(0==plane) d_current_line=current_line; + return noutput_items_produced; +} + +int +video_sdl_sink_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + short *src_pixels_0,*src_pixels_1,*src_pixels_2; + int noutput_items_produced=0; + int plane; + int delay=(int)d_avg_delay; + if(0==d_wanted_ticks) + d_wanted_ticks=SDL_GetTicks(); + if(delay>0) + SDL_Delay((unsigned int)delay);//compensate if running too fast + + if ( SDL_LockYUVOverlay( d_image ) ) { + return 0; + } + switch (input_items.size ()){ + case 3: // first channel=Y, second channel is U , third channel is V + src_pixels_0 = (short *) input_items[0]; + src_pixels_1 = (short *) input_items[1]; + src_pixels_2 = (short *) input_items[2]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + copy_plane_to_surface (1,d_chunk_size, src_pixels_1); + copy_plane_to_surface (2,d_chunk_size, src_pixels_2); + noutput_items_produced+=copy_plane_to_surface (0,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + src_pixels_1 += d_chunk_size; + src_pixels_2 += d_chunk_size; + } + break; + case 2: + if(1) //if(pixel_interleaved_uv) + { + // first channel=Y, second channel is alternating pixels U and V + src_pixels_0 = (short *) input_items[0]; + src_pixels_1 = (short *) input_items[1]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + copy_plane_to_surface (12,d_chunk_size/2, src_pixels_1); + noutput_items_produced+=copy_plane_to_surface (0,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + src_pixels_1 += d_chunk_size; + } + } else + { + // first channel=Y, second channel is alternating lines U and V + src_pixels_0 = (short *) input_items[0]; + src_pixels_1 = (short *) input_items[1]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + copy_plane_to_surface (1222,d_chunk_size/2, src_pixels_1); + noutput_items_produced+=copy_plane_to_surface (0,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + src_pixels_1 += d_chunk_size; + } + } + break; + case 1: // grey (Y) input + /* Y component */ + plane=0; + src_pixels_0 = (short *) input_items[plane]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + noutput_items_produced+=copy_plane_to_surface (plane,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + } + break; + default: //0 or more then 3 channels + std::cerr << "video_sdl_sink_s: Wrong number of channels: "; + std::cerr <<"1, 2 or 3 channels are supported.\n Requested number of channels is "<< input_items.size () <<"\n"; + throw std::runtime_error ("video_sdl_sink_s"); + } + + SDL_UnlockYUVOverlay( d_image ); + return noutput_items_produced; +} diff --git a/gr-video-sdl/src/video_sdl_sink_s.h b/gr-video-sdl/src/video_sdl_sink_s.h new file mode 100644 index 00000000..662c52b9 --- /dev/null +++ b/gr-video-sdl/src/video_sdl_sink_s.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_VIDEO_SDL_SINK_S_H +#define INCLUDED_VIDEO_SDL_SINK_S_H + +#include +#include +#include + +/* fourcc (four character code) */ +#define vid_fourcc(a,b,c,d) (((unsigned)(a)<<0) | ((unsigned)(b)<<8) | ((unsigned)(c)<<16) | ((unsigned)(d)<<24)) +#define IMGFMT_YV12 vid_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ + +class video_sdl_sink_s; +typedef boost::shared_ptr video_sdl_sink_s_sptr; + +video_sdl_sink_s_sptr +video_sdl_make_sink_s (double framerate,int width=640, int height=480,unsigned int format=IMGFMT_YV12,int dst_width=-1,int dst_height=-1); + +/*! + * \brief video sink using SDL + * + * input signature is one, two or three streams of signed short. + * One stream: stream is grey (Y) + * two streems: first is grey (Y), second is alternating U and V + * Three streams: first is grey (Y), second is U, third is V + * Input samples must be in the range [0,255]. + */ + +class video_sdl_sink_s : public gr_sync_block { + friend video_sdl_sink_s_sptr + video_sdl_make_sink_s (double framerate,int width, int height,unsigned int format,int dst_width,int dst_height); + + int d_chunk_size; + + protected: + video_sdl_sink_s (double framerate,int width, int height,unsigned int format, + int dst_width,int dst_height); + void copy_line_pixel_interleaved(unsigned char *dst_pixels_u,unsigned char *dst_pixels_v, + const short * src_pixels,int src_width); + void copy_line_line_interleaved(unsigned char *dst_pixels_u,unsigned char *dst_pixels_v, + const short * src_pixels,int src_width); + void copy_line_single_plane(unsigned char *dst_pixels,const short * src_pixels,int src_width); + void copy_line_single_plane_dec2(unsigned char *dst_pixels,const short * src_pixels,int src_width); + int copy_plane_to_surface (int plane,int noutput_items, + const short * src_pixels); + float d_framerate; + int d_wanted_frametime_ms; + int d_width; + int d_height; + int d_dst_width; + int d_dst_height; + int d_format; + int d_current_line; + SDL_Surface *d_screen; + SDL_Overlay *d_image; + SDL_Rect d_dst_rect; + float d_avg_delay; + unsigned int d_wanted_ticks; + + + public: + ~video_sdl_sink_s (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_VIDEO_SDL_SINK_S_H */ diff --git a/gr-video-sdl/src/video_sdl_sink_uc.cc b/gr-video-sdl/src/video_sdl_sink_uc.cc new file mode 100644 index 00000000..1462d728 --- /dev/null +++ b/gr-video-sdl/src/video_sdl_sink_uc.cc @@ -0,0 +1,291 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +video_sdl_sink_uc::video_sdl_sink_uc (double framerate,int width, int height,unsigned int format,int dst_width,int dst_height) + : gr_sync_block ("video_sdl_sink_uc", + gr_make_io_signature (1, 3, sizeof (unsigned char)), + gr_make_io_signature (0, 0, 0)), + d_chunk_size (width*height), + d_framerate(framerate), + d_wanted_frametime_ms(0), + d_width(width), + d_height (height), + d_dst_width(dst_width), + d_dst_height(dst_height), + d_format(format), + d_current_line(0), + d_screen(NULL), + d_image(NULL), + d_avg_delay(0.0), + d_wanted_ticks(0) +{ + if(framerate<=0.0) + d_wanted_frametime_ms=0;//Go as fast as possible + else + d_wanted_frametime_ms=(int)(1000.0/framerate); + if(dst_width<0) d_dst_width=d_width; + if(dst_height<0) d_dst_height=d_height; + if(0==format) d_format=IMGFMT_YV12; + + atexit(SDL_Quit);//check if this is the way to do this + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + std::cerr << "video_sdl_sink_uc: Couldn't initialize SDL:" << SDL_GetError() << " \n SDL_Init(SDL_INIT_VIDEO) failed\n"; + throw std::runtime_error ("video_sdl_sink_uc"); + }; + + /* accept any depth */ + d_screen = SDL_SetVideoMode(dst_width, dst_height, 0, SDL_SWSURFACE|SDL_RESIZABLE|SDL_ANYFORMAT);//SDL_DOUBLEBUF |SDL_SWSURFACE| SDL_HWSURFACE||SDL_FULLSCREEN + if ( d_screen == NULL ) { + std::cerr << "Unable to set SDL video mode: " << SDL_GetError() <<"\n SDL_SetVideoMode() Failed \n"; + exit(1); + } + if ( d_image ) { + SDL_FreeYUVOverlay(d_image); + } + /* Initialize and create the YUV Overlay used for video out */ + if (!(d_image = SDL_CreateYUVOverlay (d_width, d_height, SDL_YV12_OVERLAY, d_screen))) { + std::cerr << "SDL: Couldn't create a YUV overlay: \n"<< SDL_GetError() <<"\n"; + throw std::runtime_error ("video_sdl_sink_uc"); + } + + printf("SDL screen_mode %d bits-per-pixel\n", + d_screen->format->BitsPerPixel); + printf("SDL overlay_mode %i \n", + d_image->format); + d_chunk_size = std::min(1,16384/width); //width*16; + d_chunk_size = d_chunk_size*width; + //d_chunk_size = (int) (width); + set_output_multiple (d_chunk_size); + /* Set the default playback area */ + d_dst_rect.x = 0; + d_dst_rect.y = 0; + d_dst_rect.w = d_dst_width; + d_dst_rect.h = d_dst_height; + //clear the surface to grey + if ( SDL_LockYUVOverlay( d_image ) ) { + std::cerr << "SDL: Couldn't lock YUV overlay: \n"<< SDL_GetError() <<"\n"; + throw std::runtime_error ("video_sdl_sink_uc"); + } + memset(d_image->pixels[0], 128, d_image->pitches[0]*d_height); + memset(d_image->pixels[1], 128, d_image->pitches[1]*d_height/2); + memset(d_image->pixels[2], 128, d_image->pitches[2]*d_height/2); + SDL_UnlockYUVOverlay( d_image ); +} + +video_sdl_sink_uc::~video_sdl_sink_uc () +{ + SDL_Quit(); +} + +video_sdl_sink_uc_sptr +video_sdl_make_sink_uc (double framerate,int width, int height,unsigned int format,int dst_width,int dst_height) +{ + return video_sdl_sink_uc_sptr (new video_sdl_sink_uc (framerate, width, height,format,dst_width,dst_height)); +} + +void +video_sdl_sink_uc::copy_line_pixel_interleaved(unsigned char *dst_pixels_u,unsigned char *dst_pixels_v,const unsigned char * src_pixels,int src_width) +{ + for(int i=0;ipixels[first_dst_plane]; + dst_pixels=&dst_pixels[current_line*d_image->pitches[first_dst_plane]]; + unsigned char * dst_pixels_2 = (unsigned char *)d_image->pixels[second_dst_plane]; + dst_pixels_2=&dst_pixels_2[current_line*d_image->pitches[second_dst_plane]]; + int src_width=(0==plane || 12==plane || 1122==plane)?d_width:d_width/2; + int noutput_items_produced=0; + int max_height=(0==plane)?d_height-1:d_height/2-1; + for (int i = 0; i < noutput_items; i += src_width){ + //output one line at a time + if(12==plane) + { + copy_line_pixel_interleaved(dst_pixels,dst_pixels_2,src_pixels,src_width); + dst_pixels_2 += d_image->pitches[second_dst_plane]; + } + else if (1122==plane) + { + copy_line_line_interleaved(dst_pixels,dst_pixels_2,src_pixels,src_width); + dst_pixels_2 += d_image->pitches[second_dst_plane]; + src_pixels += src_width; + } + else if (0==plane) + copy_line_single_plane(dst_pixels,src_pixels,src_width); + else /* 1==plane || 2==plane*/ + copy_line_single_plane_dec2(dst_pixels,src_pixels,src_width);//decimate by two horizontally + src_pixels += src_width; + dst_pixels += d_image->pitches[first_dst_plane]; + noutput_items_produced+=src_width; + current_line++; + if (current_line>max_height) + { + //Start new frame + //TODO, do this all in a seperate thread + current_line=0; + dst_pixels=d_image->pixels[first_dst_plane]; + dst_pixels_2=d_image->pixels[second_dst_plane]; + if(0==plane) + { + SDL_DisplayYUVOverlay(d_image, &d_dst_rect); + //SDL_Flip(d_screen); + unsigned int ticks=SDL_GetTicks();//milliseconds + d_wanted_ticks+=d_wanted_frametime_ms; + float avg_alpha=0.1; + int time_diff=d_wanted_ticks-ticks; + d_avg_delay=time_diff*avg_alpha +d_avg_delay*(1.0-avg_alpha); + } + } + } + if(0==plane) d_current_line=current_line; + return noutput_items_produced; +} + +int +video_sdl_sink_uc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned char *src_pixels_0,*src_pixels_1,*src_pixels_2; + int noutput_items_produced=0; + int plane; + int delay=(int)d_avg_delay; + if(0==d_wanted_ticks) + d_wanted_ticks=SDL_GetTicks(); + if(delay>0) + SDL_Delay((unsigned int)delay);//compensate if running too fast + + if ( SDL_LockYUVOverlay( d_image ) ) { + return 0; + } + switch (input_items.size ()){ + case 3: // first channel=Y, second channel is U , third channel is V + src_pixels_0 = (unsigned char *) input_items[0]; + src_pixels_1 = (unsigned char *) input_items[1]; + src_pixels_2 = (unsigned char *) input_items[2]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + copy_plane_to_surface (1,d_chunk_size, src_pixels_1); + copy_plane_to_surface (2,d_chunk_size, src_pixels_2); + noutput_items_produced+=copy_plane_to_surface (0,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + src_pixels_1 += d_chunk_size; + src_pixels_2 += d_chunk_size; + } + break; + case 2: + if(1) //if(pixel_interleaved_uv) + { + // first channel=Y, second channel is alternating pixels U and V + src_pixels_0 = (unsigned char *) input_items[0]; + src_pixels_1 = (unsigned char *) input_items[1]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + copy_plane_to_surface (12,d_chunk_size/2, src_pixels_1); + noutput_items_produced+=copy_plane_to_surface (0,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + src_pixels_1 += d_chunk_size; + } + } else + { + // first channel=Y, second channel is alternating lines U and V + src_pixels_0 = (unsigned char *) input_items[0]; + src_pixels_1 = (unsigned char *) input_items[1]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + copy_plane_to_surface (1222,d_chunk_size/2, src_pixels_1); + noutput_items_produced+=copy_plane_to_surface (0,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + src_pixels_1 += d_chunk_size; + } + } + break; + case 1: // grey (Y) input + /* Y component */ + plane=0; + src_pixels_0 = (unsigned char *) input_items[plane]; + for (int i = 0; i < noutput_items; i += d_chunk_size){ + noutput_items_produced+=copy_plane_to_surface (plane,d_chunk_size, src_pixels_0); + src_pixels_0 += d_chunk_size; + } + break; + default: //0 or more then 3 channels + std::cerr << "video_sdl_sink_uc: Wrong number of channels: "; + std::cerr <<"1, 2 or 3 channels are supported.\n Requested number of channels is "<< input_items.size () <<"\n"; + throw std::runtime_error ("video_sdl_sink_uc"); + } + + SDL_UnlockYUVOverlay( d_image ); + return noutput_items_produced; +} diff --git a/gr-video-sdl/src/video_sdl_sink_uc.h b/gr-video-sdl/src/video_sdl_sink_uc.h new file mode 100644 index 00000000..3f380f3c --- /dev/null +++ b/gr-video-sdl/src/video_sdl_sink_uc.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_VIDEO_SDL_SINK_UC_H +#define INCLUDED_VIDEO_SDL_SINK_UC_H + +#include +#include +#include + +/* fourcc (four character code) */ +#define vid_fourcc(a,b,c,d) (((unsigned)(a)<<0) | ((unsigned)(b)<<8) | ((unsigned)(c)<<16) | ((unsigned)(d)<<24)) +#define IMGFMT_YV12 vid_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ + +class video_sdl_sink_uc; +typedef boost::shared_ptr video_sdl_sink_uc_sptr; + +video_sdl_sink_uc_sptr +video_sdl_make_sink_uc (double framerate,int width=640, int height=480,unsigned int format=IMGFMT_YV12,int dst_width=-1,int dst_height=-1); + +/*! + * \brief video sink using SDL + * + * input signature is one, two or three streams of uchar. + * One stream: stream is grey (Y) + * two streems: first is grey (Y), second is alternating U and V + * Three streams: first is grey (Y), second is U, third is V + * Input samples must be in the range [0,255]. + */ + +class video_sdl_sink_uc : public gr_sync_block { + friend video_sdl_sink_uc_sptr + video_sdl_make_sink_uc (double framerate,int width, int height,unsigned int format,int dst_width,int dst_height); + + int d_chunk_size; + + protected: + video_sdl_sink_uc (double framerate,int width, int height,unsigned int format, + int dst_width,int dst_height); + void copy_line_pixel_interleaved(unsigned char *dst_pixels_u,unsigned char *dst_pixels_v, + const unsigned char * src_pixels,int src_width); + void copy_line_line_interleaved(unsigned char *dst_pixels_u,unsigned char *dst_pixels_v, + const unsigned char * src_pixels,int src_width); + void copy_line_single_plane(unsigned char *dst_pixels,const unsigned char * src_pixels,int src_width); + void copy_line_single_plane_dec2(unsigned char *dst_pixels,const unsigned char * src_pixels,int src_width); + int copy_plane_to_surface (int plane,int noutput_items, + const unsigned char * src_pixels); + float d_framerate; + int d_wanted_frametime_ms; + int d_width; + int d_height; + int d_dst_width; + int d_dst_height; + int d_format; + int d_current_line; + SDL_Surface *d_screen; + SDL_Overlay *d_image; + SDL_Rect d_dst_rect; + float d_avg_delay; + unsigned int d_wanted_ticks; + + + public: + ~video_sdl_sink_uc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_VIDEO_SDL_SINK_UC_H */ diff --git a/gr-wxgui/ChangeLog b/gr-wxgui/ChangeLog new file mode 100644 index 00000000..ed4e5ad5 --- /dev/null +++ b/gr-wxgui/ChangeLog @@ -0,0 +1,171 @@ +2006-07-24 Eric Blossom + + * src/python/powermate.py (powermate._open_device): added additional + name for ID_SHUTTLE_XPRESS per Kwan Hong Lee + +2006-06-15 Eric Blossom + + * src/python/fftsink.py, src/python/waterfallsink.py, + src/python/scopesink.py: added set_sample_rate method. + +2006-04-02 Eric Blossom + + * src/python/fftsink.py (default_fft_rate): query prefs for default. + * src/python/waterfallsink.py (default_fft_rate): query prefs for default. + * src/python/scopesink (default_frame_decim): query prefs for default. + +2006-03-29 Eric Blossom + + * src/python/fftsink.py: updated to use renamed stream_to_vector + instead of serial_to_parallel. Updated ref_level and y_per_div in + builtin test case. + +2006-02-02 Eric Blossom + + * src/python/scopesink.py: now supports manual as well as + autoscaling of the y-axis. Thank to Jon Jacky. + +2005-12-08 Eric Blossom + + * src/python/stdgui.py (stdapp.__init__): added redirect=False arg + to wx.App.__init__ for Mac users. Thanks to Jon Jacky. + +2005-11-15 Eric Blossom + + * src/python/fftsink.py, src/python/scopesink.py: refactored to + use messages and message queues instead of pipes to communicate + with the C++ side. A side benefit is that the C++ side now will + not block when sending data to the gui. + +2005-10-25 Eric Blossom + + * src/python/fftsink.py: added peak_hold function and menu item. + +2005-10-14 Eric Blossom + + * src/python/form.py (quantized_slider_field): new field type, + very nice for quantized floats such as frequency, gain, etc. + +2005-08-28 Eric Blossom + + * src/python/form.py: new. tools for building forms based GUIs. + +2005-08-15 Eric Blossom + + * src/python/waterfallsink.py: fftshift data so it comes out as + expected -- -ve freqs on the left, 0 in the middle, +ve freqs on + right. Thanks to James Smith. + +2005-08-15 Krzysztof Kamieniecki + + * src/python/powermate.py: on GNU/Linux get exclusive access to knob. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac: mods for x86_64, $(NO_UNDEFINED) + +2005-06-19 Eric Blossom + + * src/python/waterfallsink.py: reworked to use latest FFT sink stuff. + * src/python/fftsink.py (fft_sink_f.__init__): added missing call + to set_average. + +2005-06-11 Eric Blossom + + * src/python/fftsink.py: normalized FFT by number of points. + +2005-06-08 Krzysztof Kamieniecki + + * src/python/powermate.py: added support for ShuttlePRO v2. + +2005-05-15 Eric Blossom + + * src/python/powermate.py: new. Support the Griffin PowerMate and + Countour Shuttle/Jog usb knobs. (Revised version of what I got + from Matt.) + +2005-05-11 Eric Blossom + + * src/python/fftsink.py, src/python/scopesink.py: Use + gru.os_read_exactly instead of os.read to avoid problems with + short reads [thanks to Jon Jacky for troubleshooting]. + Added throttle block to demo to keep it from sucking down all CPU. + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-03-16 Eric Blossom + + * src/python/scopesink.py (graph_window.format_data): enabled legend. + +2005-03-13 David Carr + + * src/python/waterfallsink.py: New faster, in color + +2005-03-04 Eric Blossom + + * src/python/slider.py: high level interface to wx.Slider + +2005-02-25 Eric Blossom + + Moved everything from src/python/gnuradio/wxgui to src/python and + removed the unnecessary hierarchy. + +2004-11-15 Matt Ettus + + * src/python/gnuradio/wxgui/waterfallsink.py: new, from David Carr + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 0.1cvs + +2004-10-11 Eric Blossom + + * configure.ac: bumped rev to 0.1, make release + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-09-19 Eric Blossom + + * src/python/gnuradio/wxgui/stdgui.py: reworked to really subclass + wx.App + +2004-09-18 Eric Blossom + + * src/python/gnuradio/wxgui/stdgui.py: new. + * src/python/gnuradio/wxgui/fftsink.py: new. + * src/python/gnuradio/wxgui/scopesink.py: new. Needs work + +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-wxgui/Makefile.am b/gr-wxgui/Makefile.am new file mode 100644 index 00000000..2a0b4b4a --- /dev/null +++ b/gr-wxgui/Makefile.am @@ -0,0 +1,28 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = gr-wxgui.conf +SUBDIRS = src + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gr-wxgui.conf diff --git a/gr-wxgui/README b/gr-wxgui/README new file mode 100644 index 00000000..ebd0d239 --- /dev/null +++ b/gr-wxgui/README @@ -0,0 +1 @@ +This requires wxPython 2.5.2.7 or later. See http://www.wxpython.org diff --git a/gr-wxgui/gr-wxgui.conf b/gr-wxgui/gr-wxgui.conf new file mode 100644 index 00000000..f6b128c6 --- /dev/null +++ b/gr-wxgui/gr-wxgui.conf @@ -0,0 +1,7 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[wxgui] +fft_rate = 15 # fftsink and waterfallsink +frame_decim = 1 # scopesink diff --git a/gr-wxgui/src/Makefile.am b/gr-wxgui/src/Makefile.am new file mode 100644 index 00000000..5da68b9d --- /dev/null +++ b/gr-wxgui/src/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = python diff --git a/gr-wxgui/src/python/Makefile.am b/gr-wxgui/src/python/Makefile.am new file mode 100644 index 00000000..2d25de05 --- /dev/null +++ b/gr-wxgui/src/python/Makefile.am @@ -0,0 +1,40 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.wxgui module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/wxgui + +ourpythondir = $(grpythondir)/wxgui +ourlibdir = $(grpyexecdir)/wxgui + +ourpython_PYTHON = \ + __init__.py \ + form.py \ + fftsink.py \ + plot.py \ + powermate.py \ + scopesink.py \ + waterfallsink.py \ + slider.py \ + stdgui.py diff --git a/gr-wxgui/src/python/__init__.py b/gr-wxgui/src/python/__init__.py new file mode 100644 index 00000000..027150db --- /dev/null +++ b/gr-wxgui/src/python/__init__.py @@ -0,0 +1 @@ +# make this directory a package diff --git a/gr-wxgui/src/python/fftsink.py b/gr-wxgui/src/python/fftsink.py new file mode 100755 index 00000000..8796a1b9 --- /dev/null +++ b/gr-wxgui/src/python/fftsink.py @@ -0,0 +1,488 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, window +from gnuradio.wxgui import stdgui +import wx +import gnuradio.wxgui.plot as plot +import Numeric +import threading +import math + +default_fftsink_size = (640,240) +default_fft_rate = gr.prefs().get_long('wxgui', 'fft_rate', 15) + +class fft_sink_base(object): + def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, ref_level=50, + sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, + average=False, avg_alpha=None, title='', peak_hold=False): + + # initialize common attributes + self.baseband_freq = baseband_freq + self.y_divs = 8 + self.y_per_div=y_per_div + self.ref_level = ref_level + self.sample_rate = sample_rate + self.fft_size = fft_size + self.fft_rate = fft_rate + self.average = average + if avg_alpha is None: + self.avg_alpha = 2.0 / fft_rate + else: + self.avg_alpha = avg_alpha + self.title = title + self.peak_hold = peak_hold + self.input_is_real = input_is_real + self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages + + def set_y_per_div(self, y_per_div): + self.y_per_div = y_per_div + + def set_ref_level(self, ref_level): + self.ref_level = ref_level + + def set_average(self, average): + self.average = average + if average: + self.avg.set_taps(self.avg_alpha) + self.set_peak_hold(False) + else: + self.avg.set_taps(1.0) + + def set_peak_hold(self, enable): + self.peak_hold = enable + if enable: + self.set_average(False) + self.win.set_peak_hold(enable) + + def set_avg_alpha(self, avg_alpha): + self.avg_alpha = avg_alpha + + def set_baseband_freq(self, baseband_freq): + self.baseband_freq = baseband_freq + + def set_sample_rate(self, sample_rate): + self.sample_rate = sample_rate + self._set_n() + + def _set_n(self): + self.one_in_n.set_n(max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + + +class fft_sink_f(gr.hier_block, fft_sink_base): + def __init__(self, fg, parent, baseband_freq=0, + y_per_div=10, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, average=False, avg_alpha=None, + title='', size=default_fftsink_size, peak_hold=False): + + fft_sink_base.__init__(self, input_is_real=True, baseband_freq=baseband_freq, + y_per_div=y_per_div, ref_level=ref_level, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title, + peak_hold=peak_hold) + + s2p = gr.stream_to_vector(gr.sizeof_float, self.fft_size) + self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fft_size, + max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + + mywindow = window.blackmanharris(self.fft_size) + fft = gr.fft_vfc(self.fft_size, True, mywindow) + power = 0 + for tap in mywindow: + power += tap*tap + + c2mag = gr.complex_to_mag(self.fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) + + # FIXME We need to add 3dB to all bins but the DC bin + log = gr.nlog10_ff(20, self.fft_size, + -20*math.log10(self.fft_size)-10*math.log10(power/self.fft_size)) + sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) + + fg.connect (s2p, self.one_in_n, fft, c2mag, self.avg, log, sink) + gr.hier_block.__init__(self, fg, s2p, sink) + + self.win = fft_window(self, parent, size=size) + self.set_average(self.average) + + +class fft_sink_c(gr.hier_block, fft_sink_base): + def __init__(self, fg, parent, baseband_freq=0, + y_per_div=10, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, average=False, avg_alpha=None, + title='', size=default_fftsink_size, peak_hold=False): + + fft_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq, + y_per_div=y_per_div, ref_level=ref_level, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title, + peak_hold=peak_hold) + + s2p = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) + self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fft_size, + max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + mywindow = window.blackmanharris(self.fft_size) + power = 0 + for tap in mywindow: + power += tap*tap + + fft = gr.fft_vcc(self.fft_size, True, mywindow) + c2mag = gr.complex_to_mag(fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, fft_size) + log = gr.nlog10_ff(20, self.fft_size, + -20*math.log10(self.fft_size)-10*math.log10(power/self.fft_size)) + sink = gr.message_sink(gr.sizeof_float * fft_size, self.msgq, True) + + fg.connect(s2p, self.one_in_n, fft, c2mag, self.avg, log, sink) + gr.hier_block.__init__(self, fg, s2p, sink) + + self.win = fft_window(self, parent, size=size) + self.set_average(self.average) + + +# ------------------------------------------------------------------------ + +myDATA_EVENT = wx.NewEventType() +EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0) + + +class DataEvent(wx.PyEvent): + def __init__(self, data): + wx.PyEvent.__init__(self) + self.SetEventType (myDATA_EVENT) + self.data = data + + def Clone (self): + self.__class__ (self.GetId()) + + +class input_watcher (threading.Thread): + def __init__ (self, msgq, fft_size, event_receiver, **kwds): + threading.Thread.__init__ (self, **kwds) + self.setDaemon (1) + self.msgq = msgq + self.fft_size = fft_size + self.event_receiver = event_receiver + self.keep_running = True + self.start () + + def run (self): + while (self.keep_running): + msg = self.msgq.delete_head() # blocking read of message queue + itemsize = int(msg.arg1()) + nitems = int(msg.arg2()) + + s = msg.to_string() # get the body of the msg as a string + + # There may be more than one FFT frame in the message. + # If so, we take only the last one + if nitems > 1: + start = itemsize * (nitems - 1) + s = s[start:start+itemsize] + + complex_data = Numeric.fromstring (s, Numeric.Float32) + de = DataEvent (complex_data) + wx.PostEvent (self.event_receiver, de) + del de + + +class fft_window (plot.PlotCanvas): + def __init__ (self, fftsink, parent, id = -1, + pos = wx.DefaultPosition, size = wx.DefaultSize, + style = wx.DEFAULT_FRAME_STYLE, name = ""): + plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name) + + self.y_range = None + self.fftsink = fftsink + self.peak_hold = False + self.peak_vals = None + + self.SetEnableGrid (True) + # self.SetEnableZoom (True) + # self.SetBackgroundColour ('black') + + self.build_popup_menu() + + EVT_DATA_EVENT (self, self.set_data) + wx.EVT_CLOSE (self, self.on_close_window) + self.Bind(wx.EVT_RIGHT_UP, self.on_right_click) + + self.input_watcher = input_watcher(fftsink.msgq, fftsink.fft_size, self) + + + def on_close_window (self, event): + print "fft_window:on_close_window" + self.keep_running = False + + + def set_data (self, evt): + dB = evt.data + L = len (dB) + + if self.peak_hold: + if self.peak_vals is None: + self.peak_vals = dB + else: + self.peak_vals = Numeric.maximum(dB, self.peak_vals) + dB = self.peak_vals + + x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq)) + if x >= 1e9: + sf = 1e-9 + units = "GHz" + elif x >= 1e6: + sf = 1e-6 + units = "MHz" + else: + sf = 1e-3 + units = "kHz" + + if self.fftsink.input_is_real: # only plot 1/2 the points + x_vals = ((Numeric.arrayrange (L/2) + * (self.fftsink.sample_rate * sf / L)) + + self.fftsink.baseband_freq * sf) + points = Numeric.zeros((len(x_vals), 2), Numeric.Float64) + points[:,0] = x_vals + points[:,1] = dB[0:L/2] + else: + # the "negative freqs" are in the second half of the array + x_vals = ((Numeric.arrayrange (-L/2, L/2) + * (self.fftsink.sample_rate * sf / L)) + + self.fftsink.baseband_freq * sf) + points = Numeric.zeros((len(x_vals), 2), Numeric.Float64) + points[:,0] = x_vals + points[:,1] = Numeric.concatenate ((dB[L/2:], dB[0:L/2])) + + + lines = plot.PolyLine (points, colour='BLUE') + + graphics = plot.PlotGraphics ([lines], + title=self.fftsink.title, + xLabel = units, yLabel = "dB") + + self.Draw (graphics, xAxis=None, yAxis=self.y_range) + self.update_y_range () + + def set_peak_hold(self, enable): + self.peak_hold = enable + self.peak_vals = None + + def update_y_range (self): + ymax = self.fftsink.ref_level + ymin = self.fftsink.ref_level - self.fftsink.y_per_div * self.fftsink.y_divs + self.y_range = self._axisInterval ('min', ymin, ymax) + + def on_average(self, evt): + # print "on_average" + self.fftsink.set_average(evt.IsChecked()) + + def on_peak_hold(self, evt): + # print "on_peak_hold" + self.fftsink.set_peak_hold(evt.IsChecked()) + + def on_incr_ref_level(self, evt): + # print "on_incr_ref_level" + self.fftsink.set_ref_level(self.fftsink.ref_level + + self.fftsink.y_per_div) + + def on_decr_ref_level(self, evt): + # print "on_decr_ref_level" + self.fftsink.set_ref_level(self.fftsink.ref_level + - self.fftsink.y_per_div) + + def on_incr_y_per_div(self, evt): + # print "on_incr_y_per_div" + self.fftsink.set_y_per_div(next_up(self.fftsink.y_per_div, (1,2,5,10,20))) + + def on_decr_y_per_div(self, evt): + # print "on_decr_y_per_div" + self.fftsink.set_y_per_div(next_down(self.fftsink.y_per_div, (1,2,5,10,20))) + + def on_y_per_div(self, evt): + # print "on_y_per_div" + Id = evt.GetId() + if Id == self.id_y_per_div_1: + self.fftsink.set_y_per_div(1) + elif Id == self.id_y_per_div_2: + self.fftsink.set_y_per_div(2) + elif Id == self.id_y_per_div_5: + self.fftsink.set_y_per_div(5) + elif Id == self.id_y_per_div_10: + self.fftsink.set_y_per_div(10) + elif Id == self.id_y_per_div_20: + self.fftsink.set_y_per_div(20) + + + def on_right_click(self, event): + menu = self.popup_menu + for id, pred in self.checkmarks.items(): + item = menu.FindItemById(id) + item.Check(pred()) + self.PopupMenu(menu, event.GetPosition()) + + + def build_popup_menu(self): + self.id_incr_ref_level = wx.NewId() + self.id_decr_ref_level = wx.NewId() + self.id_incr_y_per_div = wx.NewId() + self.id_decr_y_per_div = wx.NewId() + self.id_y_per_div_1 = wx.NewId() + self.id_y_per_div_2 = wx.NewId() + self.id_y_per_div_5 = wx.NewId() + self.id_y_per_div_10 = wx.NewId() + self.id_y_per_div_20 = wx.NewId() + self.id_average = wx.NewId() + self.id_peak_hold = wx.NewId() + + self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) + self.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) + self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) + self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) + self.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) + self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) + self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) + + + # make a menu + menu = wx.Menu() + self.popup_menu = menu + menu.AppendCheckItem(self.id_average, "Average") + menu.AppendCheckItem(self.id_peak_hold, "Peak Hold") + menu.Append(self.id_incr_ref_level, "Incr Ref Level") + menu.Append(self.id_decr_ref_level, "Decr Ref Level") + # menu.Append(self.id_incr_y_per_div, "Incr dB/div") + # menu.Append(self.id_decr_y_per_div, "Decr dB/div") + menu.AppendSeparator() + # we'd use RadioItems for these, but they're not supported on Mac + menu.AppendCheckItem(self.id_y_per_div_1, "1 dB/div") + menu.AppendCheckItem(self.id_y_per_div_2, "2 dB/div") + menu.AppendCheckItem(self.id_y_per_div_5, "5 dB/div") + menu.AppendCheckItem(self.id_y_per_div_10, "10 dB/div") + menu.AppendCheckItem(self.id_y_per_div_20, "20 dB/div") + + self.checkmarks = { + self.id_average : lambda : self.fftsink.average, + self.id_peak_hold : lambda : self.fftsink.peak_hold, + self.id_y_per_div_1 : lambda : self.fftsink.y_per_div == 1, + self.id_y_per_div_2 : lambda : self.fftsink.y_per_div == 2, + self.id_y_per_div_5 : lambda : self.fftsink.y_per_div == 5, + self.id_y_per_div_10 : lambda : self.fftsink.y_per_div == 10, + self.id_y_per_div_20 : lambda : self.fftsink.y_per_div == 20, + } + + +def next_up(v, seq): + """ + Return the first item in seq that is > v. + """ + for s in seq: + if s > v: + return s + return v + +def next_down(v, seq): + """ + Return the last item in seq that is < v. + """ + rseq = list(seq[:]) + rseq.reverse() + + for s in rseq: + if s < v: + return s + return v + + +# ---------------------------------------------------------------- +# Deprecated interfaces +# ---------------------------------------------------------------- + +# returns (block, win). +# block requires a single input stream of float +# win is a subclass of wxWindow + +def make_fft_sink_f(fg, parent, title, fft_size, input_rate, ymin = 0, ymax=50): + + block = fft_sink_f(fg, parent, title=title, fft_size=fft_size, sample_rate=input_rate, + y_per_div=(ymax - ymin)/8, ref_level=ymax) + return (block, block.win) + +# returns (block, win). +# block requires a single input stream of gr_complex +# win is a subclass of wxWindow + +def make_fft_sink_c(fg, parent, title, fft_size, input_rate, ymin=0, ymax=50): + block = fft_sink_c(fg, parent, title=title, fft_size=fft_size, sample_rate=input_rate, + y_per_div=(ymax - ymin)/8, ref_level=ymax) + return (block, block.win) + + +# ---------------------------------------------------------------- +# Standalone test app +# ---------------------------------------------------------------- + +class test_app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + fft_size = 256 + + # build our flow graph + input_rate = 20.48e3 + + # Generate a complex sinusoid + #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1) + src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1) + + # We add these throttle blocks so that this demo doesn't + # suck down all the CPU available. Normally you wouldn't use these. + thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate) + + sink1 = fft_sink_c (self, panel, title="Complex Data", fft_size=fft_size, + sample_rate=input_rate, baseband_freq=100e3, + ref_level=0, y_per_div=20) + vbox.Add (sink1.win, 1, wx.EXPAND) + self.connect (src1, thr1, sink1) + + #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1) + src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1) + thr2 = gr.throttle(gr.sizeof_float, input_rate) + sink2 = fft_sink_f (self, panel, title="Real Data", fft_size=fft_size*2, + sample_rate=input_rate, baseband_freq=100e3, + ref_level=0, y_per_div=20) + vbox.Add (sink2.win, 1, wx.EXPAND) + self.connect (src2, thr2, sink2) + +def main (): + app = stdgui.stdapp (test_app_flow_graph, + "FFT Sink Test App") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gr-wxgui/src/python/form.py b/gr-wxgui/src/python/form.py new file mode 100755 index 00000000..bb41817c --- /dev/null +++ b/gr-wxgui/src/python/form.py @@ -0,0 +1,391 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import wx +from gnuradio import eng_notation + +# ---------------------------------------------------------------- +# Wrappers for certain widgets +# ---------------------------------------------------------------- + +def button_with_callback(parent, label, callback): + new_id = wx.NewId() + btn = wx.Button(parent, new_id, label) + wx.EVT_BUTTON(parent, new_id, lambda evt: callback()) + return btn + + +# ---------------------------------------------------------------- +# Format converters +# ---------------------------------------------------------------- + +class abstract_converter(object): + def value_to_prim(self, v): + """ + Convert from user specified value to value acceptable to underlying primitive. + The underlying primitive usually expects strings. + """ + raise NotImplementedError + def prim_to_value(self, s): + """ + Convert from underlying primitive value to user specified value. + The underlying primitive usually expects strings. + """ + raise NotImplementedError + def help(self): + return "Any string is acceptable" + +class identity_converter(abstract_converter): + def value_to_prim(self,v): + return v + def prim_to_value(self, s): + return s + +class int_converter(abstract_converter): + def value_to_prim(self, v): + return str(v) + def prim_to_value(self, s): + return int(s, 0) + def help(self): + return "Enter an integer. Leading 0x indicates hex" + +class float_converter(abstract_converter): + def value_to_prim(self, v): + return eng_notation.num_to_str(v) + def prim_to_value(self, s): + return eng_notation.str_to_num(s) + def help(self): + return "Enter a float with optional scale suffix. E.g., 100.1M" + + +# ---------------------------------------------------------------- +# Various types of data entry fields +# ---------------------------------------------------------------- + +class field(object): + """ + A field in a form. + """ + def __init__(self, converter, value): + self.converter = converter + if value is not None: + self.set_value(value) + + def set_value(self, v): + self._set_prim_value(self.converter.value_to_prim(v)) + + def get_value(self): + return self.converter.prim_to_value(self._get_prim_value()) + + def get_value_with_check(self): + """ + Returns (value, error_msg), where error_msg is not None if there was problem + """ + try: + return (self.get_value(), None) + except: + return (None, self._error_msg()) + + def _set_prim_value(self, v): + raise NotImplementedError + + def _get_prim_value(self): + raise NotImplementedError + + def _pair_with_label(self, widget, parent=None, sizer=None, label=None, weight=1): + self.label = label + if label is None: + sizer.Add (widget, weight, wx.EXPAND) + return widget + elif 0: + hbox = wx.BoxSizer(wx.HORIZONTAL) + label_widget = wx.StaticText(parent, -1, label + ': ') + hbox.Add(label_widget, 0, wx.EXPAND) + hbox.Add(widget, 1, wx.EXPAND) + sizer.Add(hbox, weight, wx.EXPAND) + return widget + else: + label_widget = wx.StaticText(parent, -1, label + ': ') + sizer.Add(label_widget, 0, wx.EXPAND) + sizer.Add(widget, weight, wx.EXPAND) + return widget + + def _error_msg(self): + prefix = '' + if self.label: + prefix = self.label + ': ' + return "%s%s is invalid. %s" % (prefix, self._get_prim_value(), + self.converter.help()) + +# static (display-only) text fields + +class static_text_field(field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + converter=identity_converter(), weight=0): + self.f = self._pair_with_label(wx.StaticText(parent, -1, ""), + parent=parent, sizer=sizer, label=label, weight=weight) + field.__init__(self, converter, value) + + def _get_prim_value(self): + return self.f.GetLabel() + + def _set_prim_value(self, v): + self.f.SetLabel(v) + + +class static_int_field(static_text_field): + def __init__(self, parent=None, sizer=None, label=None, value=None, weight=0): + static_text_field.__init__(self, parent, sizer, label, value, int_converter(), weight) + +class static_float_field(static_text_field): + def __init__(self, parent=None, sizer=None, label=None, value=None, weight=0): + static_text_field.__init__(self, parent, sizer, label, value, float_converter(), weight) + + +# editable text fields + +class text_field(field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + converter=identity_converter(), callback=None, weight=1): + style = 0 + if callback: + style = wx.TE_PROCESS_ENTER + + new_id = wx.NewId() + w = wx.TextCtrl(parent, new_id, "", style=style) + self.f = self._pair_with_label(w, parent=parent, sizer=sizer, label=label, weight=weight) + if callback: + wx.EVT_TEXT_ENTER(w, new_id, lambda evt: callback()) + field.__init__(self, converter, value) + + def _get_prim_value(self): + return self.f.GetValue() + + def _set_prim_value(self, v): + self.f.SetValue(v) + + +class int_field(text_field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + callback=None, weight=1): + text_field.__init__(self, parent, sizer, label, value, int_converter(), callback, weight) + +class float_field(text_field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + callback=None, weight=1): + text_field.__init__(self, parent, sizer, label, value, float_converter(), callback, weight) + +# other fields + +class slider_field(field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + converter=identity_converter(), callback=None, min=0, max=100, weight=1): + new_id = wx.NewId() + w = wx.Slider(parent, new_id, (max+min)/2, min, max, + size=wx.Size(250, -1), style=wx.SL_HORIZONTAL | wx.SL_LABELS) + self.f = self._pair_with_label(w, parent=parent, sizer=sizer, label=label, weight=weight) + if callback: + wx.EVT_COMMAND_SCROLL(w, new_id, lambda evt: callback(evt.GetInt())) + field.__init__(self, converter, value) + + def _get_prim_value(self): + return self.f.GetValue() + + def _set_prim_value(self, v): + self.f.SetValue(int(v)) + +class quantized_slider_field(field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + converter=identity_converter(), callback=None, range=None, weight=1): + if not isinstance(range, (tuple, list)) or len(range) != 3: + raise ValueError, range + + self.min = range[0] + self.max = range[1] + self.step_size = float(range[2]) + nsteps = int((self.max-self.min)/self.step_size) + + new_id = wx.NewId() + w = wx.Slider(parent, new_id, 0, 0, nsteps, + size=wx.Size(250, -1), style=wx.SL_HORIZONTAL) + self.f = self._pair_with_label(w, parent=parent, sizer=sizer, label=label, weight=weight) + if callback: + wx.EVT_COMMAND_SCROLL(w, new_id, + lambda evt: callback(self._map_out(evt.GetInt()))) + field.__init__(self, converter, value) + + def _get_prim_value(self): + return self._map_out(self.f.GetValue()) + + def _set_prim_value(self, v): + self.f.SetValue(self._map_in(v)) + + def _map_in(self, x): + return int((x-self.min) / self.step_size) + + def _map_out(self, x): + return x * self.step_size + self.min + +class checkbox_field(field): + def __init__(self, parent=None, sizer=None, label=None, value=None, + converter=identity_converter(), callback=None, weight=1): + new_id = wx.NewId() + w = wx.CheckBox(parent, new_id, label, style=wx.CHK_2STATE) + self.f = self._pair_with_label(w, parent=parent, sizer=sizer, label=None, weight=weight) + if callback: + wx.EVT_CHECKBOX(w, new_id, lambda evt: callback(evt.GetInt())) + field.__init__(self, converter, value) + + def _get_prim_value(self): + return self.f.GetValue() + + def _set_prim_value(self, v): + self.f.SetValue(int(v)) + + +class radiobox_field(field): + def __init__(self, parent=None, sizer=None, label="", value=None, + converter=identity_converter(), callback=None, weight=1, + choices=None, major_dimension=1, specify_rows=False): + new_id = wx.NewId() + + if specify_rows: + style=wx.RA_SPECIFY_ROWS | wx.RA_HORIZONTAL + else: + style=wx.RA_SPECIFY_COLS | wx.RA_HORIZONTAL + + w = wx.RadioBox(parent, new_id, label, style=style, majorDimension=major_dimension, + choices=choices) + self.f = self._pair_with_label(w, parent=parent, sizer=sizer, label=label, weight=weight) + if callback: + wx.EVT_RADIOBOX(w, new_id, lambda evt: callback(evt.GetString())) + field.__init__(self, converter, value) + + def _get_prim_value(self): + return self.f.GetStringSelection() + + def _set_prim_value(self, v): + self.f.SetStringSelection(str(v)) + +# ---------------------------------------------------------------- +# the form class +# ---------------------------------------------------------------- + +class form(dict): + def __init__(self): + dict.__init__(self) + + def check_input_for_errors(self): + """ + Returns list of error messages if there's trouble, + else empty list. + """ + vals = [f.get_value_with_check() for f in self.values()] + return [t[1] for t in vals if t[1] is not None] + + def get_key_vals(self): + d = {} + for (key, f) in self.items(): + d[key] = f.get_value() + return d + + + def _nop(*args): pass + + def check_input_and_call(self, callback, status_handler=_nop): + """ + Return a function that checks the form for errors, and then if it's OK, + invokes the user specified callback, passing it the form key/value dictionary. + status_handler is called with a string indicating results. + """ + def doit_callback(*ignore): + errors = self.check_input_for_errors() + if errors: + status_handler(errors[0]) + #print '\n'.join(tuple(errors)) + else: + kv = self.get_key_vals() + if callback(kv): + status_handler("OK") + else: + status_handler("Failed") + + return doit_callback + + + +# ---------------------------------------------------------------- +# Stand-alone example code +# ---------------------------------------------------------------- + +import sys +from gnuradio.wxgui import stdgui + +class demo_app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + def _print_kv(kv): + print "kv =", kv + return True + + self.form = form() + + self.form['static1'] = \ + static_text_field(parent=panel, sizer=vbox, + label="Static Text", + value="The Static Value") + + self.form['text1'] = \ + text_field(parent=panel, sizer=vbox, + label="TextCtrl", + value="The Editable Value") + + self.form['int1'] = \ + int_field(parent=panel, sizer=vbox, + label="Int Field", + value=1234) + + self.form['float1'] = \ + float_field(parent=panel, sizer=vbox, + label="Float Field", + value=3.14159) + + self.doit = button_with_callback( + panel, "Do It!", + self.form.check_input_and_call(_print_kv, self._set_status_msg)) + + vbox.Add(self.doit, 0, wx.CENTER) + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + +def main (): + app = stdgui.stdapp (demo_app_flow_graph, "wxgui form demo", nstatus=1) + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gr-wxgui/src/python/plot.py b/gr-wxgui/src/python/plot.py new file mode 100644 index 00000000..d902d417 --- /dev/null +++ b/gr-wxgui/src/python/plot.py @@ -0,0 +1,1744 @@ +#----------------------------------------------------------------------------- +# Name: wx.lib.plot.py +# Purpose: Line, Bar and Scatter Graphs +# +# Author: Gordon Williams +# +# Created: 2003/11/03 +# RCS-ID: $Id$ +# Copyright: (c) 2002 +# Licence: Use as you wish. +#----------------------------------------------------------------------------- +# 12/15/2003 - Jeff Grimmett (grimmtooth@softhome.net) +# +# o 2.5 compatability update. +# o Renamed to plot.py in the wx.lib directory. +# o Reworked test frame to work with wx demo framework. This saves a bit +# of tedious cut and paste, and the test app is excellent. +# +# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net) +# +# o wxScrolledMessageDialog -> ScrolledMessageDialog +# +# Oct 6, 2004 Gordon Williams (g_will@cyberus.ca) +# - Added bar graph demo +# - Modified line end shape from round to square. +# - Removed FloatDCWrapper for conversion to ints and ints in arguments +# +# Oct 15, 2004 Gordon Williams (g_will@cyberus.ca) +# - Imported modules given leading underscore to name. +# - Added Cursor Line Tracking and User Point Labels. +# - Demo for Cursor Line Tracking and Point Labels. +# - Size of plot preview frame adjusted to show page better. +# - Added helper functions PositionUserToScreen and PositionScreenToUser in PlotCanvas. +# - Added functions GetClosestPoints (all curves) and GetClosestPoint (only closest curve) +# can be in either user coords or screen coords. +# +# + +""" +This is a simple light weight plotting module that can be used with +Boa or easily integrated into your own wxPython application. The +emphasis is on small size and fast plotting for large data sets. It +has a reasonable number of features to do line and scatter graphs +easily as well as simple bar graphs. It is not as sophisticated or +as powerful as SciPy Plt or Chaco. Both of these are great packages +but consume huge amounts of computer resources for simple plots. +They can be found at http://scipy.com + +This file contains two parts; first the re-usable library stuff, then, +after a "if __name__=='__main__'" test, a simple frame and a few default +plots for examples and testing. + +Based on wxPlotCanvas +Written by K.Hinsen, R. Srinivasan; +Ported to wxPython Harm van der Heijden, feb 1999 + +Major Additions Gordon Williams Feb. 2003 (g_will@cyberus.ca) + -More style options + -Zooming using mouse 'rubber band' + -Scroll left, right + -Grid(graticule) + -Printing, preview, and page set up (margins) + -Axis and title labels + -Cursor xy axis values + -Doc strings and lots of comments + -Optimizations for large number of points + -Legends + +Did a lot of work here to speed markers up. Only a factor of 4 +improvement though. Lines are much faster than markers, especially +filled markers. Stay away from circles and triangles unless you +only have a few thousand points. + +Times for 25,000 points +Line - 0.078 sec +Markers +Square - 0.22 sec +dot - 0.10 +circle - 0.87 +cross,plus - 0.28 +triangle, triangle_down - 0.90 + +Thanks to Chris Barker for getting this version working on Linux. + +Zooming controls with mouse (when enabled): + Left mouse drag - Zoom box. + Left mouse double click - reset zoom. + Right mouse click - zoom out centred on click location. +""" + +import string as _string +import time as _time +import wx + +# Needs Numeric or numarray +try: + import Numeric as _Numeric +except: + try: + import numarray as _Numeric #if numarray is used it is renamed Numeric + except: + msg= """ + This module requires the Numeric or numarray module, + which could not be imported. It probably is not installed + (it's not part of the standard Python distribution). See the + Python site (http://www.python.org) for information on + downloading source or binaries.""" + raise ImportError, "Numeric or numarray not found. \n" + msg + + + +# +# Plotting classes... +# +class PolyPoints: + """Base Class for lines and markers + - All methods are private. + """ + + def __init__(self, points, attr): + self.points = _Numeric.array(points) + self.currentScale= (1,1) + self.currentShift= (0,0) + self.scaled = self.points + self.attributes = {} + self.attributes.update(self._attributes) + for name, value in attr.items(): + if name not in self._attributes.keys(): + raise KeyError, "Style attribute incorrect. Should be one of %s" % self._attributes.keys() + self.attributes[name] = value + + def boundingBox(self): + if len(self.points) == 0: + # no curves to draw + # defaults to (-1,-1) and (1,1) but axis can be set in Draw + minXY= _Numeric.array([-1,-1]) + maxXY= _Numeric.array([ 1, 1]) + else: + minXY= _Numeric.minimum.reduce(self.points) + maxXY= _Numeric.maximum.reduce(self.points) + return minXY, maxXY + + def scaleAndShift(self, scale=(1,1), shift=(0,0)): + if len(self.points) == 0: + # no curves to draw + return + if (scale is not self.currentScale) or (shift is not self.currentShift): + # update point scaling + self.scaled = scale*self.points+shift + self.currentScale= scale + self.currentShift= shift + # else unchanged use the current scaling + + def getLegend(self): + return self.attributes['legend'] + + def getClosestPoint(self, pntXY, pointScaled= True): + """Returns the index of closest point on the curve, pointXY, scaledXY, distance + x, y in user coords + if pointScaled == True based on screen coords + if pointScaled == False based on user coords + """ + if pointScaled == True: + #Using screen coords + p = self.scaled + pxy = self.currentScale * _Numeric.array(pntXY)+ self.currentShift + else: + #Using user coords + p = self.points + pxy = _Numeric.array(pntXY) + #determine distance for each point + d= _Numeric.sqrt(_Numeric.add.reduce((p-pxy)**2,1)) #sqrt(dx^2+dy^2) + pntIndex = _Numeric.argmin(d) + dist = d[pntIndex] + return [pntIndex, self.points[pntIndex], self.scaled[pntIndex], dist] + + +class PolyLine(PolyPoints): + """Class to define line type and style + - All methods except __init__ are private. + """ + + _attributes = {'colour': 'black', + 'width': 1, + 'style': wx.SOLID, + 'legend': ''} + + def __init__(self, points, **attr): + """Creates PolyLine object + points - sequence (array, tuple or list) of (x,y) points making up line + **attr - key word attributes + Defaults: + 'colour'= 'black', - wx.Pen Colour any wx.NamedColour + 'width'= 1, - Pen width + 'style'= wx.SOLID, - wx.Pen style + 'legend'= '' - Line Legend to display + """ + PolyPoints.__init__(self, points, attr) + + def draw(self, dc, printerScale, coord= None): + colour = self.attributes['colour'] + width = self.attributes['width'] * printerScale + style= self.attributes['style'] + pen = wx.Pen(wx.NamedColour(colour), width, style) + pen.SetCap(wx.CAP_BUTT) + dc.SetPen(pen) + if coord == None: + dc.DrawLines(self.scaled) + else: + dc.DrawLines(coord) # draw legend line + + def getSymExtent(self, printerScale): + """Width and Height of Marker""" + h= self.attributes['width'] * printerScale + w= 5 * h + return (w,h) + + +class PolyMarker(PolyPoints): + """Class to define marker type and style + - All methods except __init__ are private. + """ + + _attributes = {'colour': 'black', + 'width': 1, + 'size': 2, + 'fillcolour': None, + 'fillstyle': wx.SOLID, + 'marker': 'circle', + 'legend': ''} + + def __init__(self, points, **attr): + """Creates PolyMarker object + points - sequence (array, tuple or list) of (x,y) points + **attr - key word attributes + Defaults: + 'colour'= 'black', - wx.Pen Colour any wx.NamedColour + 'width'= 1, - Pen width + 'size'= 2, - Marker size + 'fillcolour'= same as colour, - wx.Brush Colour any wx.NamedColour + 'fillstyle'= wx.SOLID, - wx.Brush fill style (use wx.TRANSPARENT for no fill) + 'marker'= 'circle' - Marker shape + 'legend'= '' - Marker Legend to display + + Marker Shapes: + - 'circle' + - 'dot' + - 'square' + - 'triangle' + - 'triangle_down' + - 'cross' + - 'plus' + """ + + PolyPoints.__init__(self, points, attr) + + def draw(self, dc, printerScale, coord= None): + colour = self.attributes['colour'] + width = self.attributes['width'] * printerScale + size = self.attributes['size'] * printerScale + fillcolour = self.attributes['fillcolour'] + fillstyle = self.attributes['fillstyle'] + marker = self.attributes['marker'] + + dc.SetPen(wx.Pen(wx.NamedColour(colour), width)) + if fillcolour: + dc.SetBrush(wx.Brush(wx.NamedColour(fillcolour),fillstyle)) + else: + dc.SetBrush(wx.Brush(wx.NamedColour(colour), fillstyle)) + if coord == None: + self._drawmarkers(dc, self.scaled, marker, size) + else: + self._drawmarkers(dc, coord, marker, size) # draw legend marker + + def getSymExtent(self, printerScale): + """Width and Height of Marker""" + s= 5*self.attributes['size'] * printerScale + return (s,s) + + def _drawmarkers(self, dc, coords, marker,size=1): + f = eval('self._' +marker) + f(dc, coords, size) + + def _circle(self, dc, coords, size=1): + fact= 2.5*size + wh= 5.0*size + rect= _Numeric.zeros((len(coords),4),_Numeric.Float)+[0.0,0.0,wh,wh] + rect[:,0:2]= coords-[fact,fact] + dc.DrawEllipseList(rect.astype(_Numeric.Int32)) + + def _dot(self, dc, coords, size=1): + dc.DrawPointList(coords) + + def _square(self, dc, coords, size=1): + fact= 2.5*size + wh= 5.0*size + rect= _Numeric.zeros((len(coords),4),_Numeric.Float)+[0.0,0.0,wh,wh] + rect[:,0:2]= coords-[fact,fact] + dc.DrawRectangleList(rect.astype(_Numeric.Int32)) + + def _triangle(self, dc, coords, size=1): + shape= [(-2.5*size,1.44*size), (2.5*size,1.44*size), (0.0,-2.88*size)] + poly= _Numeric.repeat(coords,3) + poly.shape= (len(coords),3,2) + poly += shape + dc.DrawPolygonList(poly.astype(_Numeric.Int32)) + + def _triangle_down(self, dc, coords, size=1): + shape= [(-2.5*size,-1.44*size), (2.5*size,-1.44*size), (0.0,2.88*size)] + poly= _Numeric.repeat(coords,3) + poly.shape= (len(coords),3,2) + poly += shape + dc.DrawPolygonList(poly.astype(_Numeric.Int32)) + + def _cross(self, dc, coords, size=1): + fact= 2.5*size + for f in [[-fact,-fact,fact,fact],[-fact,fact,fact,-fact]]: + lines= _Numeric.concatenate((coords,coords),axis=1)+f + dc.DrawLineList(lines.astype(_Numeric.Int32)) + + def _plus(self, dc, coords, size=1): + fact= 2.5*size + for f in [[-fact,0,fact,0],[0,-fact,0,fact]]: + lines= _Numeric.concatenate((coords,coords),axis=1)+f + dc.DrawLineList(lines.astype(_Numeric.Int32)) + +class PlotGraphics: + """Container to hold PolyXXX objects and graph labels + - All methods except __init__ are private. + """ + + def __init__(self, objects, title='', xLabel='', yLabel= ''): + """Creates PlotGraphics object + objects - list of PolyXXX objects to make graph + title - title shown at top of graph + xLabel - label shown on x-axis + yLabel - label shown on y-axis + """ + if type(objects) not in [list,tuple]: + raise TypeError, "objects argument should be list or tuple" + self.objects = objects + self.title= title + self.xLabel= xLabel + self.yLabel= yLabel + + def boundingBox(self): + p1, p2 = self.objects[0].boundingBox() + for o in self.objects[1:]: + p1o, p2o = o.boundingBox() + p1 = _Numeric.minimum(p1, p1o) + p2 = _Numeric.maximum(p2, p2o) + return p1, p2 + + def scaleAndShift(self, scale=(1,1), shift=(0,0)): + for o in self.objects: + o.scaleAndShift(scale, shift) + + def setPrinterScale(self, scale): + """Thickens up lines and markers only for printing""" + self.printerScale= scale + + def setXLabel(self, xLabel= ''): + """Set the X axis label on the graph""" + self.xLabel= xLabel + + def setYLabel(self, yLabel= ''): + """Set the Y axis label on the graph""" + self.yLabel= yLabel + + def setTitle(self, title= ''): + """Set the title at the top of graph""" + self.title= title + + def getXLabel(self): + """Get x axis label string""" + return self.xLabel + + def getYLabel(self): + """Get y axis label string""" + return self.yLabel + + def getTitle(self, title= ''): + """Get the title at the top of graph""" + return self.title + + def draw(self, dc): + for o in self.objects: + #t=_time.clock() # profile info + o.draw(dc, self.printerScale) + #dt= _time.clock()-t + #print o, "time=", dt + + def getSymExtent(self, printerScale): + """Get max width and height of lines and markers symbols for legend""" + symExt = self.objects[0].getSymExtent(printerScale) + for o in self.objects[1:]: + oSymExt = o.getSymExtent(printerScale) + symExt = _Numeric.maximum(symExt, oSymExt) + return symExt + + def getLegendNames(self): + """Returns list of legend names""" + lst = [None]*len(self) + for i in range(len(self)): + lst[i]= self.objects[i].getLegend() + return lst + + def __len__(self): + return len(self.objects) + + def __getitem__(self, item): + return self.objects[item] + + +#------------------------------------------------------------------------------- +# Main window that you will want to import into your application. + +class PlotCanvas(wx.Window): + """Subclass of a wx.Window to allow simple general plotting + of data with zoom, labels, and automatic axis scaling.""" + + def __init__(self, parent, id = -1, pos=wx.DefaultPosition, + size=wx.DefaultSize, style= wx.DEFAULT_FRAME_STYLE, name= ""): + """Constucts a window, which can be a child of a frame, dialog or + any other non-control window""" + + wx.Window.__init__(self, parent, id, pos, size, style, name) + self.border = (1,1) + + self.SetBackgroundColour("white") + + # Create some mouse events for zooming + self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown) + self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp) + self.Bind(wx.EVT_MOTION, self.OnMotion) + self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseDoubleClick) + self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown) + + # set curser as cross-hairs + self.SetCursor(wx.CROSS_CURSOR) + + # Things for printing + self.print_data = wx.PrintData() + self.print_data.SetPaperId(wx.PAPER_LETTER) + self.print_data.SetOrientation(wx.LANDSCAPE) + self.pageSetupData= wx.PageSetupDialogData() + self.pageSetupData.SetMarginBottomRight((25,25)) + self.pageSetupData.SetMarginTopLeft((25,25)) + self.pageSetupData.SetPrintData(self.print_data) + self.printerScale = 1 + self.parent= parent + + # Zooming variables + self._zoomInFactor = 0.5 + self._zoomOutFactor = 2 + self._zoomCorner1= _Numeric.array([0.0, 0.0]) # left mouse down corner + self._zoomCorner2= _Numeric.array([0.0, 0.0]) # left mouse up corner + self._zoomEnabled= False + self._hasDragged= False + + # Drawing Variables + self.last_draw = None + self._pointScale= 1 + self._pointShift= 0 + self._xSpec= 'auto' + self._ySpec= 'auto' + self._gridEnabled= False + self._legendEnabled= False + self._xUseScopeTicks= False + + # Fonts + self._fontCache = {} + self._fontSizeAxis= 10 + self._fontSizeTitle= 15 + self._fontSizeLegend= 7 + + # pointLabels + self._pointLabelEnabled= False + self.last_PointLabel= None + self._pointLabelFunc= None + self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave) + + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_SIZE, self.OnSize) + # OnSize called to make sure the buffer is initialized. + # This might result in OnSize getting called twice on some + # platforms at initialization, but little harm done. + self.OnSize(None) # sets the initial size based on client size + # UNCONDITIONAL, needed to create self._Buffer + + # SaveFile + def SaveFile(self, fileName= ''): + """Saves the file to the type specified in the extension. If no file + name is specified a dialog box is provided. Returns True if sucessful, + otherwise False. + + .bmp Save a Windows bitmap file. + .xbm Save an X bitmap file. + .xpm Save an XPM bitmap file. + .png Save a Portable Network Graphics file. + .jpg Save a Joint Photographic Experts Group file. + """ + if _string.lower(fileName[-3:]) not in ['bmp','xbm','xpm','png','jpg']: + dlg1 = wx.FileDialog( + self, + "Choose a file with extension bmp, gif, xbm, xpm, png, or jpg", ".", "", + "BMP files (*.bmp)|*.bmp|XBM files (*.xbm)|*.xbm|XPM file (*.xpm)|*.xpm|PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg", + wx.SAVE|wx.OVERWRITE_PROMPT + ) + try: + while 1: + if dlg1.ShowModal() == wx.ID_OK: + fileName = dlg1.GetPath() + # Check for proper exension + if _string.lower(fileName[-3:]) not in ['bmp','xbm','xpm','png','jpg']: + dlg2 = wx.MessageDialog(self, 'File name extension\n' + 'must be one of\n' + 'bmp, xbm, xpm, png, or jpg', + 'File Name Error', wx.OK | wx.ICON_ERROR) + try: + dlg2.ShowModal() + finally: + dlg2.Destroy() + else: + break # now save file + else: # exit without saving + return False + finally: + dlg1.Destroy() + + # File name has required extension + fType = _string.lower(fileName[-3:]) + if fType == "bmp": + tp= wx.BITMAP_TYPE_BMP # Save a Windows bitmap file. + elif fType == "xbm": + tp= wx.BITMAP_TYPE_XBM # Save an X bitmap file. + elif fType == "xpm": + tp= wx.BITMAP_TYPE_XPM # Save an XPM bitmap file. + elif fType == "jpg": + tp= wx.BITMAP_TYPE_JPEG # Save a JPG file. + else: + tp= wx.BITMAP_TYPE_PNG # Save a PNG file. + # Save Bitmap + res= self._Buffer.SaveFile(fileName, tp) + return res + + def PageSetup(self): + """Brings up the page setup dialog""" + data = self.pageSetupData + data.SetPrintData(self.print_data) + dlg = wx.PageSetupDialog(self.parent, data) + try: + if dlg.ShowModal() == wx.ID_OK: + data = dlg.GetPageSetupData() # returns wx.PageSetupDialogData + # updates page parameters from dialog + self.pageSetupData.SetMarginBottomRight(data.GetMarginBottomRight()) + self.pageSetupData.SetMarginTopLeft(data.GetMarginTopLeft()) + self.pageSetupData.SetPrintData(data.GetPrintData()) + self.print_data=data.GetPrintData() # updates print_data + finally: + dlg.Destroy() + + def Printout(self, paper=None): + """Print current plot.""" + if paper != None: + self.print_data.SetPaperId(paper) + pdd = wx.PrintDialogData() + pdd.SetPrintData(self.print_data) + printer = wx.Printer(pdd) + out = PlotPrintout(self) + print_ok = printer.Print(self.parent, out) + if print_ok: + self.print_data = printer.GetPrintDialogData().GetPrintData() + out.Destroy() + + def PrintPreview(self): + """Print-preview current plot.""" + printout = PlotPrintout(self) + printout2 = PlotPrintout(self) + self.preview = wx.PrintPreview(printout, printout2, self.print_data) + if not self.preview.Ok(): + wx.MessageDialog(self, "Print Preview failed.\n" \ + "Check that default printer is configured\n", \ + "Print error", wx.OK|wx.CENTRE).ShowModal() + self.preview.SetZoom(40) + # search up tree to find frame instance + frameInst= self + while not isinstance(frameInst, wx.Frame): + frameInst= frameInst.GetParent() + frame = wx.PreviewFrame(self.preview, frameInst, "Preview") + frame.Initialize() + frame.SetPosition(self.GetPosition()) + frame.SetSize((600,550)) + frame.Centre(wx.BOTH) + frame.Show(True) + + def SetFontSizeAxis(self, point= 10): + """Set the tick and axis label font size (default is 10 point)""" + self._fontSizeAxis= point + + def GetFontSizeAxis(self): + """Get current tick and axis label font size in points""" + return self._fontSizeAxis + + def SetFontSizeTitle(self, point= 15): + """Set Title font size (default is 15 point)""" + self._fontSizeTitle= point + + def GetFontSizeTitle(self): + """Get current Title font size in points""" + return self._fontSizeTitle + + def SetFontSizeLegend(self, point= 7): + """Set Legend font size (default is 7 point)""" + self._fontSizeLegend= point + + def GetFontSizeLegend(self): + """Get current Legend font size in points""" + return self._fontSizeLegend + + def SetEnableZoom(self, value): + """Set True to enable zooming.""" + if value not in [True,False]: + raise TypeError, "Value should be True or False" + self._zoomEnabled= value + + def GetEnableZoom(self): + """True if zooming enabled.""" + return self._zoomEnabled + + def SetEnableGrid(self, value): + """Set True to enable grid.""" + if value not in [True,False]: + raise TypeError, "Value should be True or False" + self._gridEnabled= value + self.Redraw() + + def GetEnableGrid(self): + """True if grid enabled.""" + return self._gridEnabled + + def SetEnableLegend(self, value): + """Set True to enable legend.""" + if value not in [True,False]: + raise TypeError, "Value should be True or False" + self._legendEnabled= value + self.Redraw() + + def GetEnableLegend(self): + """True if Legend enabled.""" + return self._legendEnabled + + def SetEnablePointLabel(self, value): + """Set True to enable pointLabel.""" + if value not in [True,False]: + raise TypeError, "Value should be True or False" + self._pointLabelEnabled= value + self.Redraw() #will erase existing pointLabel if present + self.last_PointLabel = None + + def GetEnablePointLabel(self): + """True if pointLabel enabled.""" + return self._pointLabelEnabled + + def SetPointLabelFunc(self, func): + """Sets the function with custom code for pointLabel drawing + ******** more info needed *************** + """ + self._pointLabelFunc= func + + def GetPointLabelFunc(self): + """Returns pointLabel Drawing Function""" + return self._pointLabelFunc + + def Reset(self): + """Unzoom the plot.""" + self.last_PointLabel = None #reset pointLabel + if self.last_draw is not None: + self.Draw(self.last_draw[0]) + + def ScrollRight(self, units): + """Move view right number of axis units.""" + self.last_PointLabel = None #reset pointLabel + if self.last_draw is not None: + graphics, xAxis, yAxis= self.last_draw + xAxis= (xAxis[0]+units, xAxis[1]+units) + self.Draw(graphics,xAxis,yAxis) + + def ScrollUp(self, units): + """Move view up number of axis units.""" + self.last_PointLabel = None #reset pointLabel + if self.last_draw is not None: + graphics, xAxis, yAxis= self.last_draw + yAxis= (yAxis[0]+units, yAxis[1]+units) + self.Draw(graphics,xAxis,yAxis) + + def GetXY(self,event): + """Takes a mouse event and returns the XY user axis values.""" + x,y= self.PositionScreenToUser(event.GetPosition()) + return x,y + + def PositionUserToScreen(self, pntXY): + """Converts User position to Screen Coordinates""" + userPos= _Numeric.array(pntXY) + x,y= userPos * self._pointScale + self._pointShift + return x,y + + def PositionScreenToUser(self, pntXY): + """Converts Screen position to User Coordinates""" + screenPos= _Numeric.array(pntXY) + x,y= (screenPos-self._pointShift)/self._pointScale + return x,y + + def SetXSpec(self, type= 'auto'): + """xSpec- defines x axis type. Can be 'none', 'min' or 'auto' + where: + 'none' - shows no axis or tick mark values + 'min' - shows min bounding box values + 'auto' - rounds axis range to sensible values + """ + self._xSpec= type + + def SetYSpec(self, type= 'auto'): + """ySpec- defines x axis type. Can be 'none', 'min' or 'auto' + where: + 'none' - shows no axis or tick mark values + 'min' - shows min bounding box values + 'auto' - rounds axis range to sensible values + """ + self._ySpec= type + + def GetXSpec(self): + """Returns current XSpec for axis""" + return self._xSpec + + def GetYSpec(self): + """Returns current YSpec for axis""" + return self._ySpec + + def GetXMaxRange(self): + """Returns (minX, maxX) x-axis range for displayed graph""" + graphics= self.last_draw[0] + p1, p2 = graphics.boundingBox() # min, max points of graphics + xAxis = self._axisInterval(self._xSpec, p1[0], p2[0]) # in user units + return xAxis + + def GetYMaxRange(self): + """Returns (minY, maxY) y-axis range for displayed graph""" + graphics= self.last_draw[0] + p1, p2 = graphics.boundingBox() # min, max points of graphics + yAxis = self._axisInterval(self._ySpec, p1[1], p2[1]) + return yAxis + + def GetXCurrentRange(self): + """Returns (minX, maxX) x-axis for currently displayed portion of graph""" + return self.last_draw[1] + + def GetYCurrentRange(self): + """Returns (minY, maxY) y-axis for currently displayed portion of graph""" + return self.last_draw[2] + + def SetXUseScopeTicks(self, v=False): + """Always 10 divisions, no labels""" + self._xUseScopeTicks = v + + def GetXUseScopeTicks(self): + return self._xUseScopeTicks + + def Draw(self, graphics, xAxis = None, yAxis = None, dc = None): + """Draw objects in graphics with specified x and y axis. + graphics- instance of PlotGraphics with list of PolyXXX objects + xAxis - tuple with (min, max) axis range to view + yAxis - same as xAxis + dc - drawing context - doesn't have to be specified. + If it's not, the offscreen buffer is used + """ + # check Axis is either tuple or none + if type(xAxis) not in [type(None),tuple]: + raise TypeError, "xAxis should be None or (minX,maxX)" + if type(yAxis) not in [type(None),tuple]: + raise TypeError, "yAxis should be None or (minY,maxY)" + + # check case for axis = (a,b) where a==b caused by improper zooms + if xAxis != None: + if xAxis[0] == xAxis[1]: + return + if yAxis != None: + if yAxis[0] == yAxis[1]: + return + + if dc == None: + # sets new dc and clears it + dc = wx.BufferedDC(wx.ClientDC(self), self._Buffer) + dc.Clear() + + dc.BeginDrawing() + # dc.Clear() + + # set font size for every thing but title and legend + dc.SetFont(self._getFont(self._fontSizeAxis)) + + # sizes axis to axis type, create lower left and upper right corners of plot + if xAxis == None or yAxis == None: + # One or both axis not specified in Draw + p1, p2 = graphics.boundingBox() # min, max points of graphics + if xAxis == None: + xAxis = self._axisInterval(self._xSpec, p1[0], p2[0]) # in user units + if yAxis == None: + yAxis = self._axisInterval(self._ySpec, p1[1], p2[1]) + # Adjust bounding box for axis spec + p1[0],p1[1] = xAxis[0], yAxis[0] # lower left corner user scale (xmin,ymin) + p2[0],p2[1] = xAxis[1], yAxis[1] # upper right corner user scale (xmax,ymax) + else: + # Both axis specified in Draw + p1= _Numeric.array([xAxis[0], yAxis[0]]) # lower left corner user scale (xmin,ymin) + p2= _Numeric.array([xAxis[1], yAxis[1]]) # upper right corner user scale (xmax,ymax) + + self.last_draw = (graphics, xAxis, yAxis) # saves most recient values + + # Get ticks and textExtents for axis if required + if self._xSpec is not 'none': + if self._xUseScopeTicks: + xticks = self._scope_ticks(xAxis[0], xAxis[1]) + else: + xticks = self._ticks(xAxis[0], xAxis[1]) + xTextExtent = dc.GetTextExtent(xticks[-1][1])# w h of x axis text last number on axis + else: + xticks = None + xTextExtent= (0,0) # No text for ticks + if self._ySpec is not 'none': + yticks = self._ticks(yAxis[0], yAxis[1]) + yTextExtentBottom= dc.GetTextExtent(yticks[0][1]) + yTextExtentTop = dc.GetTextExtent(yticks[-1][1]) + yTextExtent= (max(yTextExtentBottom[0],yTextExtentTop[0]), + max(yTextExtentBottom[1],yTextExtentTop[1])) + else: + yticks = None + yTextExtent= (0,0) # No text for ticks + + # TextExtents for Title and Axis Labels + titleWH, xLabelWH, yLabelWH= self._titleLablesWH(dc, graphics) + + # TextExtents for Legend + legendBoxWH, legendSymExt, legendTextExt = self._legendWH(dc, graphics) + + # room around graph area + rhsW= max(xTextExtent[0], legendBoxWH[0]) # use larger of number width or legend width + lhsW= yTextExtent[0]+ yLabelWH[1] + bottomH= max(xTextExtent[1], yTextExtent[1]/2.)+ xLabelWH[1] + topH= yTextExtent[1]/2. + titleWH[1] + textSize_scale= _Numeric.array([rhsW+lhsW,bottomH+topH]) # make plot area smaller by text size + textSize_shift= _Numeric.array([lhsW, bottomH]) # shift plot area by this amount + + # drawing title and labels text + dc.SetFont(self._getFont(self._fontSizeTitle)) + titlePos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- titleWH[0]/2., + self.plotbox_origin[1]- self.plotbox_size[1]) + dc.DrawText(graphics.getTitle(),titlePos[0],titlePos[1]) + dc.SetFont(self._getFont(self._fontSizeAxis)) + xLabelPos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- xLabelWH[0]/2., + self.plotbox_origin[1]- xLabelWH[1]) + dc.DrawText(graphics.getXLabel(),xLabelPos[0],xLabelPos[1]) + yLabelPos= (self.plotbox_origin[0], + self.plotbox_origin[1]- bottomH- (self.plotbox_size[1]-bottomH-topH)/2.+ yLabelWH[0]/2.) + if graphics.getYLabel(): # bug fix for Linux + dc.DrawRotatedText(graphics.getYLabel(),yLabelPos[0],yLabelPos[1],90) + + # drawing legend makers and text + if self._legendEnabled: + self._drawLegend(dc,graphics,rhsW,topH,legendBoxWH, legendSymExt, legendTextExt) + + # allow for scaling and shifting plotted points + scale = (self.plotbox_size-textSize_scale) / (p2-p1)* _Numeric.array((1,-1)) + shift = -p1*scale + self.plotbox_origin + textSize_shift * _Numeric.array((1,-1)) + self._pointScale= scale # make available for mouse events + self._pointShift= shift + self._drawAxes(dc, p1, p2, scale, shift, xticks, yticks) + + graphics.scaleAndShift(scale, shift) + graphics.setPrinterScale(self.printerScale) # thicken up lines and markers if printing + + # set clipping area so drawing does not occur outside axis box + ptx,pty,rectWidth,rectHeight= self._point2ClientCoord(p1, p2) + dc.SetClippingRegion(ptx,pty,rectWidth,rectHeight) + # Draw the lines and markers + #start = _time.clock() + graphics.draw(dc) + # print "entire graphics drawing took: %f second"%(_time.clock() - start) + # remove the clipping region + dc.DestroyClippingRegion() + dc.EndDrawing() + + def Redraw(self, dc= None): + """Redraw the existing plot.""" + if self.last_draw is not None: + graphics, xAxis, yAxis= self.last_draw + self.Draw(graphics,xAxis,yAxis,dc) + + def Clear(self): + """Erase the window.""" + self.last_PointLabel = None #reset pointLabel + dc = wx.BufferedDC(wx.ClientDC(self), self._Buffer) + dc.Clear() + self.last_draw = None + + def Zoom(self, Center, Ratio): + """ Zoom on the plot + Centers on the X,Y coords given in Center + Zooms by the Ratio = (Xratio, Yratio) given + """ + self.last_PointLabel = None #reset maker + x,y = Center + if self.last_draw != None: + (graphics, xAxis, yAxis) = self.last_draw + w = (xAxis[1] - xAxis[0]) * Ratio[0] + h = (yAxis[1] - yAxis[0]) * Ratio[1] + xAxis = ( x - w/2, x + w/2 ) + yAxis = ( y - h/2, y + h/2 ) + self.Draw(graphics, xAxis, yAxis) + + def GetClosestPoints(self, pntXY, pointScaled= True): + """Returns list with + [curveNumber, legend, index of closest point, pointXY, scaledXY, distance] + list for each curve. + Returns [] if no curves are being plotted. + + x, y in user coords + if pointScaled == True based on screen coords + if pointScaled == False based on user coords + """ + if self.last_draw == None: + #no graph available + return [] + graphics, xAxis, yAxis= self.last_draw + l = [] + for curveNum,obj in enumerate(graphics): + #check there are points in the curve + if len(obj.points) == 0: + continue #go to next obj + #[curveNumber, legend, index of closest point, pointXY, scaledXY, distance] + cn = [curveNum]+ [obj.getLegend()]+ obj.getClosestPoint( pntXY, pointScaled) + l.append(cn) + return l + + def GetClosetPoint(self, pntXY, pointScaled= True): + """Returns list with + [curveNumber, legend, index of closest point, pointXY, scaledXY, distance] + list for only the closest curve. + Returns [] if no curves are being plotted. + + x, y in user coords + if pointScaled == True based on screen coords + if pointScaled == False based on user coords + """ + #closest points on screen based on screen scaling (pointScaled= True) + #list [curveNumber, index, pointXY, scaledXY, distance] for each curve + closestPts= self.GetClosestPoints(pntXY, pointScaled) + if closestPts == []: + return [] #no graph present + #find one with least distance + dists = [c[-1] for c in closestPts] + mdist = min(dists) #Min dist + i = dists.index(mdist) #index for min dist + return closestPts[i] #this is the closest point on closest curve + + def UpdatePointLabel(self, mDataDict): + """Updates the pointLabel point on screen with data contained in + mDataDict. + + mDataDict will be passed to your function set by + SetPointLabelFunc. It can contain anything you + want to display on the screen at the scaledXY point + you specify. + + This function can be called from parent window with onClick, + onMotion events etc. + """ + if self.last_PointLabel != None: + #compare pointXY + if mDataDict["pointXY"] != self.last_PointLabel["pointXY"]: + #closest changed + self._drawPointLabel(self.last_PointLabel) #erase old + self._drawPointLabel(mDataDict) #plot new + else: + #just plot new with no erase + self._drawPointLabel(mDataDict) #plot new + #save for next erase + self.last_PointLabel = mDataDict + + # event handlers ********************************** + def OnMotion(self, event): + if self._zoomEnabled and event.LeftIsDown(): + if self._hasDragged: + self._drawRubberBand(self._zoomCorner1, self._zoomCorner2) # remove old + else: + self._hasDragged= True + self._zoomCorner2[0], self._zoomCorner2[1] = self.GetXY(event) + self._drawRubberBand(self._zoomCorner1, self._zoomCorner2) # add new + + def OnMouseLeftDown(self,event): + self._zoomCorner1[0], self._zoomCorner1[1]= self.GetXY(event) + + def OnMouseLeftUp(self, event): + if self._zoomEnabled: + if self._hasDragged == True: + self._drawRubberBand(self._zoomCorner1, self._zoomCorner2) # remove old + self._zoomCorner2[0], self._zoomCorner2[1]= self.GetXY(event) + self._hasDragged = False # reset flag + minX, minY= _Numeric.minimum( self._zoomCorner1, self._zoomCorner2) + maxX, maxY= _Numeric.maximum( self._zoomCorner1, self._zoomCorner2) + self.last_PointLabel = None #reset pointLabel + if self.last_draw != None: + self.Draw(self.last_draw[0], xAxis = (minX,maxX), yAxis = (minY,maxY), dc = None) + #else: # A box has not been drawn, zoom in on a point + ## this interfered with the double click, so I've disables it. + # X,Y = self.GetXY(event) + # self.Zoom( (X,Y), (self._zoomInFactor,self._zoomInFactor) ) + + def OnMouseDoubleClick(self,event): + if self._zoomEnabled: + self.Reset() + + def OnMouseRightDown(self,event): + if self._zoomEnabled: + X,Y = self.GetXY(event) + self.Zoom( (X,Y), (self._zoomOutFactor, self._zoomOutFactor) ) + + def OnPaint(self, event): + # All that is needed here is to draw the buffer to screen + if self.last_PointLabel != None: + self._drawPointLabel(self.last_PointLabel) #erase old + self.last_PointLabel = None + dc = wx.BufferedPaintDC(self, self._Buffer) + + def OnSize(self,event): + # The Buffer init is done here, to make sure the buffer is always + # the same size as the Window + Size = self.GetClientSize() + + # Make new offscreen bitmap: this bitmap will always have the + # current drawing in it, so it can be used to save the image to + # a file, or whatever. + self._Buffer = wx.EmptyBitmap(Size[0],Size[1]) + self._setSize() + + self.last_PointLabel = None #reset pointLabel + + if self.last_draw is None: + self.Clear() + else: + graphics, xSpec, ySpec = self.last_draw + self.Draw(graphics,xSpec,ySpec) + + def OnLeave(self, event): + """Used to erase pointLabel when mouse outside window""" + if self.last_PointLabel != None: + self._drawPointLabel(self.last_PointLabel) #erase old + self.last_PointLabel = None + + + # Private Methods ************************************************** + def _setSize(self, width=None, height=None): + """DC width and height.""" + if width == None: + (self.width,self.height) = self.GetClientSize() + else: + self.width, self.height= width,height + self.plotbox_size = 0.97*_Numeric.array([self.width, self.height]) + xo = 0.5*(self.width-self.plotbox_size[0]) + yo = self.height-0.5*(self.height-self.plotbox_size[1]) + self.plotbox_origin = _Numeric.array([xo, yo]) + + def _setPrinterScale(self, scale): + """Used to thicken lines and increase marker size for print out.""" + # line thickness on printer is very thin at 600 dot/in. Markers small + self.printerScale= scale + + def _printDraw(self, printDC): + """Used for printing.""" + if self.last_draw != None: + graphics, xSpec, ySpec= self.last_draw + self.Draw(graphics,xSpec,ySpec,printDC) + + def _drawPointLabel(self, mDataDict): + """Draws and erases pointLabels""" + width = self._Buffer.GetWidth() + height = self._Buffer.GetHeight() + tmp_Buffer = wx.EmptyBitmap(width,height) + dcs = wx.MemoryDC() + dcs.SelectObject(tmp_Buffer) + dcs.Clear() + dcs.BeginDrawing() + self._pointLabelFunc(dcs,mDataDict) #custom user pointLabel function + dcs.EndDrawing() + + dc = wx.ClientDC( self ) + #this will erase if called twice + dc.Blit(0, 0, width, height, dcs, 0, 0, wx.EQUIV) #(NOT src) XOR dst + + + def _drawLegend(self,dc,graphics,rhsW,topH,legendBoxWH, legendSymExt, legendTextExt): + """Draws legend symbols and text""" + # top right hand corner of graph box is ref corner + trhc= self.plotbox_origin+ (self.plotbox_size-[rhsW,topH])*[1,-1] + legendLHS= .091* legendBoxWH[0] # border space between legend sym and graph box + lineHeight= max(legendSymExt[1], legendTextExt[1]) * 1.1 #1.1 used as space between lines + dc.SetFont(self._getFont(self._fontSizeLegend)) + for i in range(len(graphics)): + o = graphics[i] + s= i*lineHeight + if isinstance(o,PolyMarker): + # draw marker with legend + pnt= (trhc[0]+legendLHS+legendSymExt[0]/2., trhc[1]+s+lineHeight/2.) + o.draw(dc, self.printerScale, coord= _Numeric.array([pnt])) + elif isinstance(o,PolyLine): + # draw line with legend + pnt1= (trhc[0]+legendLHS, trhc[1]+s+lineHeight/2.) + pnt2= (trhc[0]+legendLHS+legendSymExt[0], trhc[1]+s+lineHeight/2.) + o.draw(dc, self.printerScale, coord= _Numeric.array([pnt1,pnt2])) + else: + raise TypeError, "object is neither PolyMarker or PolyLine instance" + # draw legend txt + pnt= (trhc[0]+legendLHS+legendSymExt[0], trhc[1]+s+lineHeight/2.-legendTextExt[1]/2) + dc.DrawText(o.getLegend(),pnt[0],pnt[1]) + dc.SetFont(self._getFont(self._fontSizeAxis)) # reset + + def _titleLablesWH(self, dc, graphics): + """Draws Title and labels and returns width and height for each""" + # TextExtents for Title and Axis Labels + dc.SetFont(self._getFont(self._fontSizeTitle)) + title= graphics.getTitle() + titleWH= dc.GetTextExtent(title) + dc.SetFont(self._getFont(self._fontSizeAxis)) + xLabel, yLabel= graphics.getXLabel(),graphics.getYLabel() + xLabelWH= dc.GetTextExtent(xLabel) + yLabelWH= dc.GetTextExtent(yLabel) + return titleWH, xLabelWH, yLabelWH + + def _legendWH(self, dc, graphics): + """Returns the size in screen units for legend box""" + if self._legendEnabled != True: + legendBoxWH= symExt= txtExt= (0,0) + else: + # find max symbol size + symExt= graphics.getSymExtent(self.printerScale) + # find max legend text extent + dc.SetFont(self._getFont(self._fontSizeLegend)) + txtList= graphics.getLegendNames() + txtExt= dc.GetTextExtent(txtList[0]) + for txt in graphics.getLegendNames()[1:]: + txtExt= _Numeric.maximum(txtExt,dc.GetTextExtent(txt)) + maxW= symExt[0]+txtExt[0] + maxH= max(symExt[1],txtExt[1]) + # padding .1 for lhs of legend box and space between lines + maxW= maxW* 1.1 + maxH= maxH* 1.1 * len(txtList) + dc.SetFont(self._getFont(self._fontSizeAxis)) + legendBoxWH= (maxW,maxH) + return (legendBoxWH, symExt, txtExt) + + def _drawRubberBand(self, corner1, corner2): + """Draws/erases rect box from corner1 to corner2""" + ptx,pty,rectWidth,rectHeight= self._point2ClientCoord(corner1, corner2) + # draw rectangle + dc = wx.ClientDC( self ) + dc.BeginDrawing() + dc.SetPen(wx.Pen(wx.BLACK)) + dc.SetBrush(wx.Brush( wx.WHITE, wx.TRANSPARENT ) ) + dc.SetLogicalFunction(wx.INVERT) + dc.DrawRectangle( ptx,pty, rectWidth,rectHeight) + dc.SetLogicalFunction(wx.COPY) + dc.EndDrawing() + + def _getFont(self,size): + """Take font size, adjusts if printing and returns wx.Font""" + s = size*self.printerScale + of = self.GetFont() + # Linux speed up to get font from cache rather than X font server + key = (int(s), of.GetFamily (), of.GetStyle (), of.GetWeight ()) + font = self._fontCache.get (key, None) + if font: + return font # yeah! cache hit + else: + font = wx.Font(int(s), of.GetFamily(), of.GetStyle(), of.GetWeight()) + self._fontCache[key] = font + return font + + + def _point2ClientCoord(self, corner1, corner2): + """Converts user point coords to client screen int coords x,y,width,height""" + c1= _Numeric.array(corner1) + c2= _Numeric.array(corner2) + # convert to screen coords + pt1= c1*self._pointScale+self._pointShift + pt2= c2*self._pointScale+self._pointShift + # make height and width positive + pul= _Numeric.minimum(pt1,pt2) # Upper left corner + plr= _Numeric.maximum(pt1,pt2) # Lower right corner + rectWidth, rectHeight= plr-pul + ptx,pty= pul + return ptx, pty, rectWidth, rectHeight + + def _axisInterval(self, spec, lower, upper): + """Returns sensible axis range for given spec""" + if spec == 'none' or spec == 'min': + if lower == upper: + return lower-0.5, upper+0.5 + else: + return lower, upper + elif spec == 'auto': + range = upper-lower + # if range == 0.: + if abs(range) < 1e-36: + return lower-0.5, upper+0.5 + log = _Numeric.log10(range) + power = _Numeric.floor(log) + fraction = log-power + if fraction <= 0.05: + power = power-1 + grid = 10.**power + lower = lower - lower % grid + mod = upper % grid + if mod != 0: + upper = upper - mod + grid + return lower, upper + elif type(spec) == type(()): + lower, upper = spec + if lower <= upper: + return lower, upper + else: + return upper, lower + else: + raise ValueError, str(spec) + ': illegal axis specification' + + def _drawAxes(self, dc, p1, p2, scale, shift, xticks, yticks): + + penWidth= self.printerScale # increases thickness for printing only + dc.SetPen(wx.Pen(wx.NamedColour('BLACK'), penWidth)) + + # set length of tick marks--long ones make grid + if self._gridEnabled: + x,y,width,height= self._point2ClientCoord(p1,p2) + yTickLength= width/2.0 +1 + xTickLength= height/2.0 +1 + else: + yTickLength= 3 * self.printerScale # lengthens lines for printing + xTickLength= 3 * self.printerScale + + if self._xSpec is not 'none': + lower, upper = p1[0],p2[0] + text = 1 + for y, d in [(p1[1], -xTickLength), (p2[1], xTickLength)]: # miny, maxy and tick lengths + a1 = scale*_Numeric.array([lower, y])+shift + a2 = scale*_Numeric.array([upper, y])+shift + dc.DrawLine(a1[0],a1[1],a2[0],a2[1]) # draws upper and lower axis line + for x, label in xticks: + pt = scale*_Numeric.array([x, y])+shift + dc.DrawLine(pt[0],pt[1],pt[0],pt[1] + d) # draws tick mark d units + if text: + dc.DrawText(label,pt[0],pt[1]) + text = 0 # axis values not drawn on top side + + if self._ySpec is not 'none': + lower, upper = p1[1],p2[1] + text = 1 + h = dc.GetCharHeight() + for x, d in [(p1[0], -yTickLength), (p2[0], yTickLength)]: + a1 = scale*_Numeric.array([x, lower])+shift + a2 = scale*_Numeric.array([x, upper])+shift + dc.DrawLine(a1[0],a1[1],a2[0],a2[1]) + for y, label in yticks: + pt = scale*_Numeric.array([x, y])+shift + dc.DrawLine(pt[0],pt[1],pt[0]-d,pt[1]) + if text: + dc.DrawText(label,pt[0]-dc.GetTextExtent(label)[0], + pt[1]-0.5*h) + text = 0 # axis values not drawn on right side + + def _ticks(self, lower, upper): + ideal = (upper-lower)/7. + log = _Numeric.log10(ideal) + power = _Numeric.floor(log) + fraction = log-power + factor = 1. + error = fraction + for f, lf in self._multiples: + e = _Numeric.fabs(fraction-lf) + if e < error: + error = e + factor = f + grid = factor * 10.**power + if power > 4 or power < -4: + format = '%+7.1e' + elif power >= 0: + digits = max(1, int(power)) + format = '%' + `digits`+'.0f' + else: + digits = -int(power) + format = '%'+`digits+2`+'.'+`digits`+'f' + ticks = [] + t = -grid*_Numeric.floor(-lower/grid) + while t <= upper: + ticks.append( (t, format % (t,)) ) + t = t + grid + return ticks + + def _scope_ticks (self, lower, upper): + '''Always 10 divisions, no labels''' + grid = (upper - lower) / 10.0 + ticks = [] + t = lower + while t <= upper: + ticks.append( (t, "")) + t = t + grid + return ticks + + _multiples = [(2., _Numeric.log10(2.)), (5., _Numeric.log10(5.))] + + +#------------------------------------------------------------------------------- +# Used to layout the printer page + +class PlotPrintout(wx.Printout): + """Controls how the plot is made in printing and previewing""" + # Do not change method names in this class, + # we have to override wx.Printout methods here! + def __init__(self, graph): + """graph is instance of plotCanvas to be printed or previewed""" + wx.Printout.__init__(self) + self.graph = graph + + def HasPage(self, page): + if page == 1: + return True + else: + return False + + def GetPageInfo(self): + return (1, 1, 1, 1) # disable page numbers + + def OnPrintPage(self, page): + dc = self.GetDC() # allows using floats for certain functions +## print "PPI Printer",self.GetPPIPrinter() +## print "PPI Screen", self.GetPPIScreen() +## print "DC GetSize", dc.GetSize() +## print "GetPageSizePixels", self.GetPageSizePixels() + # Note PPIScreen does not give the correct number + # Calulate everything for printer and then scale for preview + PPIPrinter= self.GetPPIPrinter() # printer dots/inch (w,h) + #PPIScreen= self.GetPPIScreen() # screen dots/inch (w,h) + dcSize= dc.GetSize() # DC size + pageSize= self.GetPageSizePixels() # page size in terms of pixcels + clientDcSize= self.graph.GetClientSize() + + # find what the margins are (mm) + margLeftSize,margTopSize= self.graph.pageSetupData.GetMarginTopLeft() + margRightSize, margBottomSize= self.graph.pageSetupData.GetMarginBottomRight() + + # calculate offset and scale for dc + pixLeft= margLeftSize*PPIPrinter[0]/25.4 # mm*(dots/in)/(mm/in) + pixRight= margRightSize*PPIPrinter[0]/25.4 + pixTop= margTopSize*PPIPrinter[1]/25.4 + pixBottom= margBottomSize*PPIPrinter[1]/25.4 + + plotAreaW= pageSize[0]-(pixLeft+pixRight) + plotAreaH= pageSize[1]-(pixTop+pixBottom) + + # ratio offset and scale to screen size if preview + if self.IsPreview(): + ratioW= float(dcSize[0])/pageSize[0] + ratioH= float(dcSize[1])/pageSize[1] + pixLeft *= ratioW + pixTop *= ratioH + plotAreaW *= ratioW + plotAreaH *= ratioH + + # rescale plot to page or preview plot area + self.graph._setSize(plotAreaW,plotAreaH) + + # Set offset and scale + dc.SetDeviceOrigin(pixLeft,pixTop) + + # Thicken up pens and increase marker size for printing + ratioW= float(plotAreaW)/clientDcSize[0] + ratioH= float(plotAreaH)/clientDcSize[1] + aveScale= (ratioW+ratioH)/2 + self.graph._setPrinterScale(aveScale) # tickens up pens for printing + + self.graph._printDraw(dc) + # rescale back to original + self.graph._setSize() + self.graph._setPrinterScale(1) + self.graph.Redraw() #to get point label scale and shift correct + + return True + + + + +#--------------------------------------------------------------------------- +# if running standalone... +# +# ...a sample implementation using the above +# + +def _draw1Objects(): + # 100 points sin function, plotted as green circles + data1 = 2.*_Numeric.pi*_Numeric.arange(200)/200. + data1.shape = (100, 2) + data1[:,1] = _Numeric.sin(data1[:,0]) + markers1 = PolyMarker(data1, legend='Green Markers', colour='green', marker='circle',size=1) + + # 50 points cos function, plotted as red line + data1 = 2.*_Numeric.pi*_Numeric.arange(100)/100. + data1.shape = (50,2) + data1[:,1] = _Numeric.cos(data1[:,0]) + lines = PolyLine(data1, legend= 'Red Line', colour='red') + + # A few more points... + pi = _Numeric.pi + markers2 = PolyMarker([(0., 0.), (pi/4., 1.), (pi/2, 0.), + (3.*pi/4., -1)], legend='Cross Legend', colour='blue', + marker='cross') + + return PlotGraphics([markers1, lines, markers2],"Graph Title", "X Axis", "Y Axis") + +def _draw2Objects(): + # 100 points sin function, plotted as green dots + data1 = 2.*_Numeric.pi*_Numeric.arange(200)/200. + data1.shape = (100, 2) + data1[:,1] = _Numeric.sin(data1[:,0]) + line1 = PolyLine(data1, legend='Green Line', colour='green', width=6, style=wx.DOT) + + # 50 points cos function, plotted as red dot-dash + data1 = 2.*_Numeric.pi*_Numeric.arange(100)/100. + data1.shape = (50,2) + data1[:,1] = _Numeric.cos(data1[:,0]) + line2 = PolyLine(data1, legend='Red Line', colour='red', width=3, style= wx.DOT_DASH) + + # A few more points... + pi = _Numeric.pi + markers1 = PolyMarker([(0., 0.), (pi/4., 1.), (pi/2, 0.), + (3.*pi/4., -1)], legend='Cross Hatch Square', colour='blue', width= 3, size= 6, + fillcolour= 'red', fillstyle= wx.CROSSDIAG_HATCH, + marker='square') + + return PlotGraphics([markers1, line1, line2], "Big Markers with Different Line Styles") + +def _draw3Objects(): + markerList= ['circle', 'dot', 'square', 'triangle', 'triangle_down', + 'cross', 'plus', 'circle'] + m=[] + for i in range(len(markerList)): + m.append(PolyMarker([(2*i+.5,i+.5)], legend=markerList[i], colour='blue', + marker=markerList[i])) + return PlotGraphics(m, "Selection of Markers", "Minimal Axis", "No Axis") + +def _draw4Objects(): + # 25,000 point line + data1 = _Numeric.arange(5e5,1e6,10) + data1.shape = (25000, 2) + line1 = PolyLine(data1, legend='Wide Line', colour='green', width=5) + + # A few more points... + markers2 = PolyMarker(data1, legend='Square', colour='blue', + marker='square') + return PlotGraphics([line1, markers2], "25,000 Points", "Value X", "") + +def _draw5Objects(): + # Empty graph with axis defined but no points/lines + points=[] + line1 = PolyLine(points, legend='Wide Line', colour='green', width=5) + return PlotGraphics([line1], "Empty Plot With Just Axes", "Value X", "Value Y") + +def _draw6Objects(): + # Bar graph + points1=[(1,0), (1,10)] + line1 = PolyLine(points1, colour='green', legend='Feb.', width=10) + points1g=[(2,0), (2,4)] + line1g = PolyLine(points1g, colour='red', legend='Mar.', width=10) + points1b=[(3,0), (3,6)] + line1b = PolyLine(points1b, colour='blue', legend='Apr.', width=10) + + points2=[(4,0), (4,12)] + line2 = PolyLine(points2, colour='Yellow', legend='May', width=10) + points2g=[(5,0), (5,8)] + line2g = PolyLine(points2g, colour='orange', legend='June', width=10) + points2b=[(6,0), (6,4)] + line2b = PolyLine(points2b, colour='brown', legend='July', width=10) + + return PlotGraphics([line1, line1g, line1b, line2, line2g, line2b], + "Bar Graph - (Turn on Grid, Legend)", "Months", "Number of Students") + + +class TestFrame(wx.Frame): + def __init__(self, parent, id, title): + wx.Frame.__init__(self, parent, id, title, + wx.DefaultPosition, (600, 400)) + + # Now Create the menu bar and items + self.mainmenu = wx.MenuBar() + + menu = wx.Menu() + menu.Append(200, 'Page Setup...', 'Setup the printer page') + self.Bind(wx.EVT_MENU, self.OnFilePageSetup, id=200) + + menu.Append(201, 'Print Preview...', 'Show the current plot on page') + self.Bind(wx.EVT_MENU, self.OnFilePrintPreview, id=201) + + menu.Append(202, 'Print...', 'Print the current plot') + self.Bind(wx.EVT_MENU, self.OnFilePrint, id=202) + + menu.Append(203, 'Save Plot...', 'Save current plot') + self.Bind(wx.EVT_MENU, self.OnSaveFile, id=203) + + menu.Append(205, 'E&xit', 'Enough of this already!') + self.Bind(wx.EVT_MENU, self.OnFileExit, id=205) + self.mainmenu.Append(menu, '&File') + + menu = wx.Menu() + menu.Append(206, 'Draw1', 'Draw plots1') + self.Bind(wx.EVT_MENU,self.OnPlotDraw1, id=206) + menu.Append(207, 'Draw2', 'Draw plots2') + self.Bind(wx.EVT_MENU,self.OnPlotDraw2, id=207) + menu.Append(208, 'Draw3', 'Draw plots3') + self.Bind(wx.EVT_MENU,self.OnPlotDraw3, id=208) + menu.Append(209, 'Draw4', 'Draw plots4') + self.Bind(wx.EVT_MENU,self.OnPlotDraw4, id=209) + menu.Append(210, 'Draw5', 'Draw plots5') + self.Bind(wx.EVT_MENU,self.OnPlotDraw5, id=210) + menu.Append(260, 'Draw6', 'Draw plots6') + self.Bind(wx.EVT_MENU,self.OnPlotDraw6, id=260) + + + menu.Append(211, '&Redraw', 'Redraw plots') + self.Bind(wx.EVT_MENU,self.OnPlotRedraw, id=211) + menu.Append(212, '&Clear', 'Clear canvas') + self.Bind(wx.EVT_MENU,self.OnPlotClear, id=212) + menu.Append(213, '&Scale', 'Scale canvas') + self.Bind(wx.EVT_MENU,self.OnPlotScale, id=213) + menu.Append(214, 'Enable &Zoom', 'Enable Mouse Zoom', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU,self.OnEnableZoom, id=214) + menu.Append(215, 'Enable &Grid', 'Turn on Grid', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU,self.OnEnableGrid, id=215) + menu.Append(220, 'Enable &Legend', 'Turn on Legend', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU,self.OnEnableLegend, id=220) + menu.Append(222, 'Enable &Point Label', 'Show Closest Point', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU,self.OnEnablePointLabel, id=222) + + menu.Append(225, 'Scroll Up 1', 'Move View Up 1 Unit') + self.Bind(wx.EVT_MENU,self.OnScrUp, id=225) + menu.Append(230, 'Scroll Rt 2', 'Move View Right 2 Units') + self.Bind(wx.EVT_MENU,self.OnScrRt, id=230) + menu.Append(235, '&Plot Reset', 'Reset to original plot') + self.Bind(wx.EVT_MENU,self.OnReset, id=235) + + self.mainmenu.Append(menu, '&Plot') + + menu = wx.Menu() + menu.Append(300, '&About', 'About this thing...') + self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=300) + self.mainmenu.Append(menu, '&Help') + + self.SetMenuBar(self.mainmenu) + + # A status bar to tell people what's happening + self.CreateStatusBar(1) + + self.client = PlotCanvas(self) + #define the function for drawing pointLabels + self.client.SetPointLabelFunc(self.DrawPointLabel) + # Create mouse event for showing cursor coords in status bar + self.client.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown) + # Show closest point when enabled + self.client.Bind(wx.EVT_MOTION, self.OnMotion) + + self.Show(True) + + def DrawPointLabel(self, dc, mDataDict): + """This is the fuction that defines how the pointLabels are plotted + dc - DC that will be passed + mDataDict - Dictionary of data that you want to use for the pointLabel + + As an example I have decided I want a box at the curve point + with some text information about the curve plotted below. + Any wxDC method can be used. + """ + # ---------- + dc.SetPen(wx.Pen(wx.BLACK)) + dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) ) + + sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point + dc.DrawRectangle( sx-5,sy-5, 10, 10) #10by10 square centered on point + px,py = mDataDict["pointXY"] + cNum = mDataDict["curveNum"] + pntIn = mDataDict["pIndex"] + legend = mDataDict["legend"] + #make a string to display + s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn) + dc.DrawText(s, sx , sy+1) + # ----------- + + def OnMouseLeftDown(self,event): + s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.client.GetXY(event) + self.SetStatusText(s) + event.Skip() #allows plotCanvas OnMouseLeftDown to be called + + def OnMotion(self, event): + #show closest point (when enbled) + if self.client.GetEnablePointLabel() == True: + #make up dict with info for the pointLabel + #I've decided to mark the closest point on the closest curve + dlst= self.client.GetClosetPoint( self.client.GetXY(event), pointScaled= True) + if dlst != []: #returns [] if none + curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst + #make up dictionary to pass to my user function (see DrawPointLabel) + mDataDict= {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\ + "pointXY":pointXY, "scaledXY":scaledXY} + #pass dict to update the pointLabel + self.client.UpdatePointLabel(mDataDict) + event.Skip() #go to next handler + + def OnFilePageSetup(self, event): + self.client.PageSetup() + + def OnFilePrintPreview(self, event): + self.client.PrintPreview() + + def OnFilePrint(self, event): + self.client.Printout() + + def OnSaveFile(self, event): + self.client.SaveFile() + + def OnFileExit(self, event): + self.Close() + + def OnPlotDraw1(self, event): + self.resetDefaults() + self.client.Draw(_draw1Objects()) + + def OnPlotDraw2(self, event): + self.resetDefaults() + self.client.Draw(_draw2Objects()) + + def OnPlotDraw3(self, event): + self.resetDefaults() + self.client.SetFont(wx.Font(10,wx.SCRIPT,wx.NORMAL,wx.NORMAL)) + self.client.SetFontSizeAxis(20) + self.client.SetFontSizeLegend(12) + self.client.SetXSpec('min') + self.client.SetYSpec('none') + self.client.Draw(_draw3Objects()) + + def OnPlotDraw4(self, event): + self.resetDefaults() + drawObj= _draw4Objects() + self.client.Draw(drawObj) +## # profile +## start = _time.clock() +## for x in range(10): +## self.client.Draw(drawObj) +## print "10 plots of Draw4 took: %f sec."%(_time.clock() - start) +## # profile end + + def OnPlotDraw5(self, event): + # Empty plot with just axes + self.resetDefaults() + drawObj= _draw5Objects() + # make the axis X= (0,5), Y=(0,10) + # (default with None is X= (-1,1), Y= (-1,1)) + self.client.Draw(drawObj, xAxis= (0,5), yAxis= (0,10)) + + def OnPlotDraw6(self, event): + #Bar Graph Example + self.resetDefaults() + #self.client.SetEnableLegend(True) #turn on Legend + #self.client.SetEnableGrid(True) #turn on Grid + self.client.SetXSpec('none') #turns off x-axis scale + self.client.SetYSpec('auto') + self.client.Draw(_draw6Objects(), xAxis= (0,7)) + + def OnPlotRedraw(self,event): + self.client.Redraw() + + def OnPlotClear(self,event): + self.client.Clear() + + def OnPlotScale(self, event): + if self.client.last_draw != None: + graphics, xAxis, yAxis= self.client.last_draw + self.client.Draw(graphics,(1,3.05),(0,1)) + + def OnEnableZoom(self, event): + self.client.SetEnableZoom(event.IsChecked()) + + def OnEnableGrid(self, event): + self.client.SetEnableGrid(event.IsChecked()) + + def OnEnableLegend(self, event): + self.client.SetEnableLegend(event.IsChecked()) + + def OnEnablePointLabel(self, event): + self.client.SetEnablePointLabel(event.IsChecked()) + + def OnScrUp(self, event): + self.client.ScrollUp(1) + + def OnScrRt(self,event): + self.client.ScrollRight(2) + + def OnReset(self,event): + self.client.Reset() + + def OnHelpAbout(self, event): + from wx.lib.dialogs import ScrolledMessageDialog + about = ScrolledMessageDialog(self, __doc__, "About...") + about.ShowModal() + + def resetDefaults(self): + """Just to reset the fonts back to the PlotCanvas defaults""" + self.client.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL)) + self.client.SetFontSizeAxis(10) + self.client.SetFontSizeLegend(7) + self.client.SetXSpec('auto') + self.client.SetYSpec('auto') + + +def __test(): + + class MyApp(wx.App): + def OnInit(self): + wx.InitAllImageHandlers() + frame = TestFrame(None, -1, "PlotCanvas") + #frame.Show(True) + self.SetTopWindow(frame) + return True + + + app = MyApp(0) + app.MainLoop() + +if __name__ == '__main__': + __test() diff --git a/gr-wxgui/src/python/powermate.py b/gr-wxgui/src/python/powermate.py new file mode 100755 index 00000000..36be408c --- /dev/null +++ b/gr-wxgui/src/python/powermate.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Handler for Griffin PowerMate, Contour ShuttlePro & ShuttleXpress USB knobs + +This is Linux and wxPython specific. +""" +import select +import os +import fcntl +import struct +import exceptions +import threading +import sys +import wx +from gnuradio import gru + +# First a little bit of background: +# +# The Griffin PowerMate has +# * a single knob which rotates +# * a single button (pressing the knob) +# +# The Contour ShuttleXpress (aka SpaceShuttle) has +# * "Jog Wheel" -- the knob (rotary encoder) on the inside +# * "Shuttle Ring" -- the spring loaded rubber covered ring +# * 5 buttons +# +# The Contour ShuttlePro has +# * "Jog Wheel" -- the knob (rotary encoder) on the inside +# * "Shuttle Ring" -- the spring loaded rubber covered ring +# * 13 buttons +# +# The Contour ShuttlePro V2 has +# *"Jog Wheel" -- the knob (rotary encoder) on the inside +# * "Shuttle Ring" -- the spring loaded rubber covered ring +# * 15 buttons + +# We remap all the buttons on the devices so that they start at zero. + +# For the ShuttleXpress the buttons are 0 to 4 (left to right) + +# For the ShuttlePro, we number the buttons immediately above +# the ring 0 to 4 (left to right) so that they match our numbering +# on the ShuttleXpress. The top row is 5, 6, 7, 8. The first row below +# the ring is 9, 10, and the bottom row is 11, 12. + +# For the ShuttlePro V2, buttons 13 & 14 are to the +# left and right of the wheel respectively. + +# We generate 3 kinds of events: +# +# button press/release (button_number, press/release) +# knob rotation (relative_clicks) # typically -1, +1 +# shuttle position (absolute_position) # -7,-6,...,0,...,6,7 + +# ---------------------------------------------------------------- +# Our ID's for the devices: +# Not to be confused with anything related to magic hardware numbers. + +ID_POWERMATE = 'powermate' +ID_SHUTTLE_XPRESS = 'shuttle xpress' +ID_SHUTTLE_PRO = 'shuttle pro' +ID_SHUTTLE_PRO_V2 = 'shuttle pro v2' + +# ------------------------------------------------------------------------ +# format of messages that we read from /dev/input/event* +# See /usr/include/linux/input.h for more info +# +#struct input_event { +# struct timeval time; = {long seconds, long microseconds} +# unsigned short type; +# unsigned short code; +# unsigned int value; +#}; + +input_event_struct = "@llHHi" +input_event_size = struct.calcsize(input_event_struct) + +# ------------------------------------------------------------------------ +# input_event types +# ------------------------------------------------------------------------ + +IET_SYN = 0x00 # aka RESET +IET_KEY = 0x01 # key or button press/release +IET_REL = 0x02 # relative movement (knob rotation) +IET_ABS = 0x03 # absolute position (graphics pad, etc) +IET_MSC = 0x04 +IET_LED = 0x11 +IET_SND = 0x12 +IET_REP = 0x14 +IET_FF = 0x15 +IET_PWR = 0x16 +IET_FF_STATUS = 0x17 +IET_MAX = 0x1f + +# ------------------------------------------------------------------------ +# input_event codes (there are a zillion of them, we only define a few) +# ------------------------------------------------------------------------ + +# these are valid for IET_KEY + +IEC_BTN_0 = 0x100 +IEC_BTN_1 = 0x101 +IEC_BTN_2 = 0x102 +IEC_BTN_3 = 0x103 +IEC_BTN_4 = 0x104 +IEC_BTN_5 = 0x105 +IEC_BTN_6 = 0x106 +IEC_BTN_7 = 0x107 +IEC_BTN_8 = 0x108 +IEC_BTN_9 = 0x109 +IEC_BTN_10 = 0x10a +IEC_BTN_11 = 0x10b +IEC_BTN_12 = 0x10c +IEC_BTN_13 = 0x10d +IEC_BTN_14 = 0x10e +IEC_BTN_15 = 0x10f + +# these are valid for IET_REL (Relative axes) + +IEC_REL_X = 0x00 +IEC_REL_Y = 0x01 +IEC_REL_Z = 0x02 +IEC_REL_HWHEEL = 0x06 +IEC_REL_DIAL = 0x07 # rotating the knob +IEC_REL_WHEEL = 0x08 # moving the shuttle ring +IEC_REL_MISC = 0x09 +IEC_REL_MAX = 0x0f + +# ------------------------------------------------------------------------ + +class powermate(threading.Thread): + """ + Interface to Griffin PowerMate and Contour Shuttles + """ + def __init__(self, event_receiver=None, filename=None, **kwargs): + self.event_receiver = event_receiver + self.handle = -1 + if filename: + if not self._open_device(filename): + raise exceptions.RuntimeError, 'Unable to find powermate' + else: + ok = False + for d in range(0, 16): + if self._open_device("/dev/input/event%d" % d): + ok = True + break + if not ok: + raise exceptions.RuntimeError, 'Unable to find powermate' + + threading.Thread.__init__(self, **kwargs) + self.setDaemon (1) + self.keep_running = True + self.start () + + def __del__(self): + self.keep_running = False + if self.handle >= 0: + os.close(self.handle) + self.handle = -1 + + def _open_device(self, filename): + try: + self.handle = os.open(filename, os.O_RDWR) + if self.handle < 0: + return False + + # read event device name + name = fcntl.ioctl(self.handle, gru.hexint(0x80ff4506), chr(0) * 256) + name = name.replace(chr(0), '') + + # do we see anything we recognize? + if name == 'Griffin PowerMate' or name == 'Griffin SoundKnob': + self.id = ID_POWERMATE + self.mapper = _powermate_remapper() + elif name == 'CAVS SpaceShuttle A/V' or name == 'Contour Design ShuttleXpress': + self.id = ID_SHUTTLE_XPRESS + self.mapper = _contour_remapper() + elif name == 'Contour Design ShuttlePRO': + self.id = ID_SHUTTLE_PRO + self.mapper = _contour_remapper() + elif name == 'Contour Design ShuttlePRO v2': + self.id = ID_SHUTTLE_PRO_V2 + self.mapper = _contour_remapper() + else: + os.close(self.handle) + self.handle = -1 + return False + + # get exclusive control of the device, using ioctl EVIOCGRAB + # there may be an issue with this on non x86 platforms and if + # the _IOW,_IOC,... macros in are changed + fcntl.ioctl(self.handle,gru.hexint(0x40044590), 1) + return True + except exceptions.OSError: + return False + + + def set_event_receiver(self, obj): + self.event_receiver = obj + + + def set_led_state(self, static_brightness, pulse_speed=0, + pulse_table=0, pulse_on_sleep=0, pulse_on_wake=0): + """ + What do these magic values mean... + """ + if self.id != ID_POWERMATE: + return False + + static_brightness &= 0xff; + if pulse_speed < 0: + pulse_speed = 0 + if pulse_speed > 510: + pulse_speed = 510 + if pulse_table < 0: + pulse_table = 0 + if pulse_table > 2: + pulse_table = 2 + pulse_on_sleep = not not pulse_on_sleep # not not = convert to 0/1 + pulse_on_wake = not not pulse_on_wake + magic = (static_brightness + | (pulse_speed << 8) + | (pulse_table << 17) + | (pulse_on_sleep << 19) + | (pulse_on_wake << 20)) + data = struct.pack(input_event_struct, 0, 0, 0x04, 0x01, magic) + os.write(self.handle, data) + return True + + def run (self): + while (self.keep_running): + s = os.read (self.handle, input_event_size) + if not s: + self.keep_running = False + break + + raw_input_event = struct.unpack(input_event_struct,s) + sec, usec, type, code, val = self.mapper(raw_input_event) + + if self.event_receiver is None: + continue + + if type == IET_SYN: # ignore + pass + elif type == IET_MSC: # ignore (seems to be PowerMate reporting led brightness) + pass + elif type == IET_REL and code == IEC_REL_DIAL: + #print "Dial: %d" % (val,) + wx.PostEvent(self.event_receiver, PMRotateEvent(val)) + elif type == IET_REL and code == IEC_REL_WHEEL: + #print "Shuttle: %d" % (val,) + wx.PostEvent(self.event_receiver, PMShuttleEvent(val)) + elif type == IET_KEY: + #print "Key: Btn%d %d" % (code - IEC_BTN_0, val) + wx.PostEvent(self.event_receiver, + PMButtonEvent(code - IEC_BTN_0, val)) + else: + print "powermate: unrecognized event: type = 0x%x code = 0x%x val = %d" % (type, code, val) + + +class _powermate_remapper(object): + def __init__(self): + pass + def __call__(self, event): + """ + Notice how nice and simple this is... + """ + return event + +class _contour_remapper(object): + def __init__(self): + self.prev = None + def __call__(self, event): + """ + ...and how screwed up this is + """ + sec, usec, type, code, val = event + if type == IET_REL and code == IEC_REL_WHEEL: + # === Shuttle ring === + # First off, this really ought to be IET_ABS, not IET_REL! + # They never generate a zero value so you can't + # tell when the shuttle ring is back in the center. + # We kludge around this by calling both -1 and 1 zero. + if val == -1 or val == 1: + return (sec, usec, type, code, 0) + return event + + if type == IET_REL and code == IEC_REL_DIAL: + # === Jog knob (rotary encoder) === + # Dim wits got it wrong again! This one should return a + # a relative value, e.g., -1, +1. Instead they return + # a total that runs modulo 256 (almost!). For some + # reason they count like this 253, 254, 255, 1, 2, 3 + + if self.prev is None: # first time call + self.prev = val + return (sec, usec, IET_SYN, 0, 0) # will be ignored above + + diff = val - self.prev + if diff == 0: # sometimes it just sends stuff... + return (sec, usec, IET_SYN, 0, 0) # will be ignored above + + if abs(diff) > 100: # crossed into the twilight zone + if self.prev > val: # we've wrapped going forward + self.prev = val + return (sec, usec, type, code, +1) + else: # we've wrapped going backward + self.prev = val + return (sec, usec, type, code, -1) + + self.prev = val + return (sec, usec, type, code, diff) + + if type == IET_KEY: + # remap keys so that all 3 gadgets have buttons 0 to 4 in common + return (sec, usec, type, + (IEC_BTN_5, IEC_BTN_6, IEC_BTN_7, IEC_BTN_8, + IEC_BTN_0, IEC_BTN_1, IEC_BTN_2, IEC_BTN_3, IEC_BTN_4, + IEC_BTN_9, IEC_BTN_10, + IEC_BTN_11, IEC_BTN_12, + IEC_BTN_13, IEC_BTN_14)[code - IEC_BTN_0], val) + + return event + +# ------------------------------------------------------------------------ +# new wxPython event classes +# ------------------------------------------------------------------------ + +grEVT_POWERMATE_BUTTON = wx.NewEventType() +grEVT_POWERMATE_ROTATE = wx.NewEventType() +grEVT_POWERMATE_SHUTTLE = wx.NewEventType() + +EVT_POWERMATE_BUTTON = wx.PyEventBinder(grEVT_POWERMATE_BUTTON, 0) +EVT_POWERMATE_ROTATE = wx.PyEventBinder(grEVT_POWERMATE_ROTATE, 0) +EVT_POWERMATE_SHUTTLE = wx.PyEventBinder(grEVT_POWERMATE_SHUTTLE, 0) + +class PMButtonEvent(wx.PyEvent): + def __init__(self, button, value): + wx.PyEvent.__init__(self) + self.SetEventType(grEVT_POWERMATE_BUTTON) + self.button = button + self.value = value + + def Clone (self): + self.__class__(self.GetId()) + + +class PMRotateEvent(wx.PyEvent): + def __init__(self, delta): + wx.PyEvent.__init__(self) + self.SetEventType (grEVT_POWERMATE_ROTATE) + self.delta = delta + + def Clone (self): + self.__class__(self.GetId()) + + +class PMShuttleEvent(wx.PyEvent): + def __init__(self, position): + wx.PyEvent.__init__(self) + self.SetEventType (grEVT_POWERMATE_SHUTTLE) + self.position = position + + def Clone (self): + self.__class__(self.GetId()) + +# ------------------------------------------------------------------------ +# Example usage +# ------------------------------------------------------------------------ + +if __name__ == '__main__': + class Frame(wx.Frame): + def __init__(self,parent=None,id=-1,title='Title', + pos=wx.DefaultPosition, size=(400,200)): + wx.Frame.__init__(self,parent,id,title,pos,size) + EVT_POWERMATE_BUTTON(self, self.on_button) + EVT_POWERMATE_ROTATE(self, self.on_rotate) + EVT_POWERMATE_SHUTTLE(self, self.on_shuttle) + self.brightness = 128 + self.pulse_speed = 0 + + try: + self.pm = powermate(self) + except: + sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n") + sys.exit(1) + + self.pm.set_led_state(self.brightness, self.pulse_speed) + + + def on_button(self, evt): + print "Button %d %s" % (evt.button, + ("Released", "Pressed")[evt.value]) + + def on_rotate(self, evt): + print "Rotated %d" % (evt.delta,) + if 0: + new = max(0, min(255, self.brightness + evt.delta)) + if new != self.brightness: + self.brightness = new + self.pm.set_led_state(self.brightness, self.pulse_speed) + + def on_shuttle(self, evt): + print "Shuttle %d" % (evt.position,) + + class App(wx.App): + def OnInit(self): + title='PowerMate Demo' + self.frame = Frame(parent=None,id=-1,title=title) + self.frame.Show() + self.SetTopWindow(self.frame) + return True + + app = App() + app.MainLoop () diff --git a/gr-wxgui/src/python/scopesink.py b/gr-wxgui/src/python/scopesink.py new file mode 100755 index 00000000..f231b3b7 --- /dev/null +++ b/gr-wxgui/src/python/scopesink.py @@ -0,0 +1,650 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, eng_notation +from gnuradio.wxgui import stdgui +import wx +import gnuradio.wxgui.plot as plot +import Numeric +import threading +import struct + +default_scopesink_size = (640, 240) +default_v_scale = 1000 +default_frame_decim = gr.prefs().get_long('wxgui', 'frame_decim', 1) + +class scope_sink_f(gr.hier_block): + def __init__(self, fg, parent, title='', sample_rate=1, + size=default_scopesink_size, frame_decim=default_frame_decim, + v_scale=default_v_scale, t_scale=None): + msgq = gr.msg_queue(2) # message queue that holds at most 2 messages + self.guts = gr.oscope_sink_f(sample_rate, msgq) + gr.hier_block.__init__(self, fg, self.guts, self.guts) + self.win = scope_window(win_info (msgq, sample_rate, frame_decim, + v_scale, t_scale, self.guts, title), parent) + + def set_sample_rate(self, sample_rate): + self.guts.set_sample_rate(sample_rate) + self.win.info.set_sample_rate(sample_rate) + +class scope_sink_c(gr.hier_block): + def __init__(self, fg, parent, title='', sample_rate=1, + size=default_scopesink_size, frame_decim=default_frame_decim, + v_scale=default_v_scale, t_scale=None): + msgq = gr.msg_queue(2) # message queue that holds at most 2 messages + c2f = gr.complex_to_float() + self.guts = gr.oscope_sink_f(sample_rate, msgq) + fg.connect((c2f, 0), (self.guts, 0)) + fg.connect((c2f, 1), (self.guts, 1)) + gr.hier_block.__init__(self, fg, c2f, self.guts) + self.win = scope_window(win_info(msgq, sample_rate, frame_decim, + v_scale, t_scale, self.guts, title), parent) + + def set_sample_rate(self, sample_rate): + self.guts.set_sample_rate(sample_rate) + self.win.info.set_sample_rate(sample_rate) + +# ======================================================================== +# This is the deprecated interface, retained for compatibility... +# +# returns (block, win). +# block requires a N input stream of float +# win is a subclass of wxWindow + +def make_scope_sink_f (fg, parent, label, input_rate): + block = scope_sink_f(fg, parent, title=label, sample_rate=input_rate) + return (block, block.win) + +# ======================================================================== + + +time_base_list = [ # time / division + 1.0e-7, # 100ns / div + 2.5e-7, + 5.0e-7, + 1.0e-6, # 1us / div + 2.5e-6, + 5.0e-6, + 1.0e-5, # 10us / div + 2.5e-5, + 5.0e-5, + 1.0e-4, # 100us / div + 2.5e-4, + 5.0e-4, + 1.0e-3, # 1ms / div + 2.5e-3, + 5.0e-3, + 1.0e-2, # 10ms / div + 2.5e-2, + 5.0e-2 + ] + +v_scale_list = [ # counts / div, LARGER gains are SMALLER /div, appear EARLIER + 2.0e-3, # 2m / div, don't call it V/div it's actually counts/div + 5.0e-3, + 1.0e-2, + 2.0e-2, + 5.0e-2, + 1.0e-1, + 2.0e-1, + 5.0e-1, + 1.0e+0, + 2.0e+0, + 5.0e+0, + 1.0e+1, + 2.0e+1, + 5.0e+1, + 1.0e+2, + 2.0e+2, + 5.0e+2, + 1.0e+3, + 2.0e+3, + 5.0e+3, + 1.0e+4 # 10000 /div, USRP full scale is -/+ 32767 + ] + + +wxDATA_EVENT = wx.NewEventType() + +def EVT_DATA_EVENT(win, func): + win.Connect(-1, -1, wxDATA_EVENT, func) + +class DataEvent(wx.PyEvent): + def __init__(self, data): + wx.PyEvent.__init__(self) + self.SetEventType (wxDATA_EVENT) + self.data = data + + def Clone (self): + self.__class__ (self.GetId()) + + +class win_info (object): + __slots__ = ['msgq', 'sample_rate', 'frame_decim', 'v_scale', + 'scopesink', 'title', + 'time_scale_cursor', 'v_scale_cursor', 'marker', 'xy', + 'autorange', 'running'] + + def __init__ (self, msgq, sample_rate, frame_decim, v_scale, t_scale, + scopesink, title = "Oscilloscope"): + self.msgq = msgq + self.sample_rate = sample_rate + self.frame_decim = frame_decim + self.scopesink = scopesink + self.title = title; + + self.time_scale_cursor = gru.seq_with_cursor(time_base_list, initial_value = t_scale) + self.v_scale_cursor = gru.seq_with_cursor(v_scale_list, initial_value = v_scale) + + self.marker = 'line' + self.xy = False + if v_scale == None: # 0 and None are both False, but 0 != None + self.autorange = True + else: + self.autorange = False # 0 is a valid v_scale + self.running = True + + def get_time_per_div (self): + return self.time_scale_cursor.current () + + def get_volts_per_div (self): + return self.v_scale_cursor.current () + + def set_sample_rate(self, sample_rate): + self.sample_rate = sample_rate + + def get_sample_rate (self): + return self.sample_rate + + def get_decimation_rate (self): + return 1.0 + + def set_marker (self, s): + self.marker = s + + def get_marker (self): + return self.marker + + +class input_watcher (threading.Thread): + def __init__ (self, msgq, event_receiver, frame_decim, **kwds): + threading.Thread.__init__ (self, **kwds) + self.setDaemon (1) + self.msgq = msgq + self.event_receiver = event_receiver + self.frame_decim = frame_decim + self.iscan = 0 + self.keep_running = True + self.start () + + def run (self): + # print "input_watcher: pid = ", os.getpid () + while (self.keep_running): + msg = self.msgq.delete_head() # blocking read of message queue + if self.iscan == 0: # only display at frame_decim + self.iscan = self.frame_decim + + nchan = int(msg.arg1()) # number of channels of data in msg + nsamples = int(msg.arg2()) # number of samples in each channel + + s = msg.to_string() # get the body of the msg as a string + + bytes_per_chan = nsamples * gr.sizeof_float + + records = [] + for ch in range (nchan): + + start = ch * bytes_per_chan + chan_data = s[start:start+bytes_per_chan] + rec = Numeric.fromstring (chan_data, Numeric.Float32) + records.append (rec) + + # print "nrecords = %d, reclen = %d" % (len (records),nsamples) + + de = DataEvent (records) + wx.PostEvent (self.event_receiver, de) + records = [] + del de + + # end if iscan == 0 + self.iscan -= 1 + + +class scope_window (wx.Panel): + + def __init__ (self, info, parent, id = -1, + pos = wx.DefaultPosition, size = wx.DefaultSize, name = ""): + wx.Panel.__init__ (self, parent, -1) + self.info = info + + vbox = wx.BoxSizer (wx.VERTICAL) + + self.graph = graph_window (info, self, -1) + + vbox.Add (self.graph, 1, wx.EXPAND) + vbox.Add (self.make_control_box(), 0, wx.EXPAND) + vbox.Add (self.make_control2_box(), 0, wx.EXPAND) + + self.sizer = vbox + self.SetSizer (self.sizer) + self.SetAutoLayout (True) + self.sizer.Fit (self) + self.set_autorange(self.info.autorange) + + + # second row of control buttons etc. appears BELOW control_box + def make_control2_box (self): + ctrlbox = wx.BoxSizer (wx.HORIZONTAL) + + self.inc_v_button = wx.Button (self, 1101, " < ", style=wx.BU_EXACTFIT) + self.inc_v_button.SetToolTipString ("Increase vertical range") + wx.EVT_BUTTON (self, 1101, self.incr_v_scale) # ID matches button ID above + + self.dec_v_button = wx.Button (self, 1100, " > ", style=wx.BU_EXACTFIT) + self.dec_v_button.SetToolTipString ("Decrease vertical range") + wx.EVT_BUTTON (self, 1100, self.decr_v_scale) + + self.v_scale_label = wx.StaticText (self, 1002, "None") # vertical /div + self.update_v_scale_label () + + self.autorange_checkbox = wx.CheckBox (self, 1102, "Autorange") + self.autorange_checkbox.SetToolTipString ("Select autorange on/off") + wx.EVT_CHECKBOX(self, 1102, self.autorange_checkbox_event) + + ctrlbox.Add ((5,0) ,0) # left margin space + ctrlbox.Add (self.inc_v_button, 0, wx.EXPAND) + ctrlbox.Add (self.dec_v_button, 0, wx.EXPAND) + ctrlbox.Add (self.v_scale_label, 0, wx.ALIGN_CENTER) + ctrlbox.Add ((20,0) ,0) # spacer + ctrlbox.Add (self.autorange_checkbox, 0, wx.ALIGN_CENTER) + + return ctrlbox + + def make_control_box (self): + ctrlbox = wx.BoxSizer (wx.HORIZONTAL) + + tb_left = wx.Button (self, 1001, " < ", style=wx.BU_EXACTFIT) + tb_left.SetToolTipString ("Increase time base") + wx.EVT_BUTTON (self, 1001, self.incr_timebase) + + + tb_right = wx.Button (self, 1000, " > ", style=wx.BU_EXACTFIT) + tb_right.SetToolTipString ("Decrease time base") + wx.EVT_BUTTON (self, 1000, self.decr_timebase) + + self.time_base_label = wx.StaticText (self, 1002, "") + self.update_timebase_label () + + ctrlbox.Add ((5,0) ,0) + # ctrlbox.Add (wx.StaticText (self, -1, "Horiz Scale: "), 0, wx.ALIGN_CENTER) + ctrlbox.Add (tb_left, 0, wx.EXPAND) + ctrlbox.Add (tb_right, 0, wx.EXPAND) + ctrlbox.Add (self.time_base_label, 0, wx.ALIGN_CENTER) + + ctrlbox.Add ((10,0) ,1) # stretchy space + + ctrlbox.Add (wx.StaticText (self, -1, "Trig: "), 0, wx.ALIGN_CENTER) + self.trig_chan_choice = wx.Choice (self, 1004, + choices = ['Ch1', 'Ch2', 'Ch3', 'Ch4']) + self.trig_chan_choice.SetToolTipString ("Select channel for trigger") + wx.EVT_CHOICE (self, 1004, self.trig_chan_choice_event) + ctrlbox.Add (self.trig_chan_choice, 0, wx.ALIGN_CENTER) + + self.trig_mode_choice = wx.Choice (self, 1005, + choices = ['Pos', 'Neg', 'Auto']) + self.trig_mode_choice.SetToolTipString ("Select trigger slope or Auto (untriggered roll)") + wx.EVT_CHOICE (self, 1005, self.trig_mode_choice_event) + ctrlbox.Add (self.trig_mode_choice, 0, wx.ALIGN_CENTER) + + trig_level50 = wx.Button (self, 1006, "50%") + trig_level50.SetToolTipString ("Set trigger level to 50%") + wx.EVT_BUTTON (self, 1006, self.set_trig_level50) + ctrlbox.Add (trig_level50, 0, wx.EXPAND) + + run_stop = wx.Button (self, 1007, "Run/Stop") + run_stop.SetToolTipString ("Toggle Run/Stop mode") + wx.EVT_BUTTON (self, 1007, self.run_stop) + ctrlbox.Add (run_stop, 0, wx.EXPAND) + + ctrlbox.Add ((10, 0) ,1) # stretchy space + + ctrlbox.Add (wx.StaticText (self, -1, "Fmt: "), 0, wx.ALIGN_CENTER) + self.marker_choice = wx.Choice (self, 1002, choices = self._marker_choices) + self.marker_choice.SetToolTipString ("Select plotting with lines, pluses or dots") + wx.EVT_CHOICE (self, 1002, self.marker_choice_event) + ctrlbox.Add (self.marker_choice, 0, wx.ALIGN_CENTER) + + self.xy_choice = wx.Choice (self, 1003, choices = ['X:t', 'X:Y']) + self.xy_choice.SetToolTipString ("Select X vs time or X vs Y display") + wx.EVT_CHOICE (self, 1003, self.xy_choice_event) + ctrlbox.Add (self.xy_choice, 0, wx.ALIGN_CENTER) + + return ctrlbox + + _marker_choices = ['line', 'plus', 'dot'] + + def update_timebase_label (self): + time_per_div = self.info.get_time_per_div () + s = ' ' + eng_notation.num_to_str (time_per_div) + 's/div' + self.time_base_label.SetLabel (s) + + def decr_timebase (self, evt): + self.info.time_scale_cursor.prev () + self.update_timebase_label () + + def incr_timebase (self, evt): + self.info.time_scale_cursor.next () + self.update_timebase_label () + + def update_v_scale_label (self): + volts_per_div = self.info.get_volts_per_div () + s = ' ' + eng_notation.num_to_str (volts_per_div) + '/div' # Not V/div + self.v_scale_label.SetLabel (s) + + def decr_v_scale (self, evt): + self.info.v_scale_cursor.prev () + self.update_v_scale_label () + + def incr_v_scale (self, evt): + self.info.v_scale_cursor.next () + self.update_v_scale_label () + + def marker_choice_event (self, evt): + s = evt.GetString () + self.set_marker (s) + + def set_autorange(self, on): + if on: + self.v_scale_label.SetLabel(" (auto)") + self.info.autorange = True + self.autorange_checkbox.SetValue(True) + self.inc_v_button.Enable(False) + self.dec_v_button.Enable(False) + else: + if self.graph.y_range: + (l,u) = self.graph.y_range # found by autorange + self.info.v_scale_cursor.set_index_by_value((u-l)/8.0) + self.update_v_scale_label() + self.info.autorange = False + self.autorange_checkbox.SetValue(False) + self.inc_v_button.Enable(True) + self.dec_v_button.Enable(True) + + def autorange_checkbox_event(self, evt): + if evt.Checked(): + self.set_autorange(True) + else: + self.set_autorange(False) + + def set_marker (self, s): + self.info.set_marker (s) # set info for drawing routines + i = self.marker_choice.FindString (s) + assert i >= 0, "Hmmm, set_marker problem" + self.marker_choice.SetSelection (i) + + def set_format_line (self): + self.set_marker ('line') + + def set_format_dot (self): + self.set_marker ('dot') + + def set_format_plus (self): + self.set_marker ('plus') + + def xy_choice_event (self, evt): + s = evt.GetString () + self.info.xy = s == 'X:Y' + + def trig_chan_choice_event (self, evt): + s = evt.GetString () + ch = int (s[-1]) - 1 + self.info.scopesink.set_trigger_channel (ch) + + def trig_mode_choice_event (self, evt): + sink = self.info.scopesink + s = evt.GetString () + if s == 'Pos': + sink.set_trigger_mode (gr.gr_TRIG_POS_SLOPE) + elif s == 'Neg': + sink.set_trigger_mode (gr.gr_TRIG_NEG_SLOPE) + elif s == 'Auto': + sink.set_trigger_mode (gr.gr_TRIG_AUTO) + else: + assert 0, "Bad trig_mode_choice string" + + def set_trig_level50 (self, evt): + self.info.scopesink.set_trigger_level_auto () + + def run_stop (self, evt): + self.info.running = not self.info.running + + +class graph_window (plot.PlotCanvas): + + channel_colors = ['BLUE', 'RED', + 'CYAN', 'MAGENTA', 'GREEN', 'YELLOW'] + + def __init__ (self, info, parent, id = -1, + pos = wx.DefaultPosition, size = (640, 240), + style = wx.DEFAULT_FRAME_STYLE, name = ""): + plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name) + + self.SetXUseScopeTicks (True) + self.SetEnableGrid (True) + self.SetEnableZoom (True) + self.SetEnableLegend(True) + # self.SetBackgroundColour ('black') + + self.info = info; + self.y_range = None + self.x_range = None + self.avg_y_min = None + self.avg_y_max = None + self.avg_x_min = None + self.avg_x_max = None + + EVT_DATA_EVENT (self, self.format_data) + + self.input_watcher = input_watcher (info.msgq, self, info.frame_decim) + + def channel_color (self, ch): + return self.channel_colors[ch % len(self.channel_colors)] + + def format_data (self, evt): + if not self.info.running: + return + + if self.info.xy: + self.format_xy_data (evt) + return + + info = self.info + records = evt.data + nchannels = len (records) + npoints = len (records[0]) + + objects = [] + + Ts = 1.0 / (info.get_sample_rate () / info.get_decimation_rate ()) + x_vals = Ts * Numeric.arrayrange (-npoints/2, npoints/2) + + # preliminary clipping based on time axis here, instead of in graphics code + time_per_window = self.info.get_time_per_div () * 10 + n = int (time_per_window / Ts + 0.5) + n = n & ~0x1 # make even + n = max (2, min (n, npoints)) + + self.SetXUseScopeTicks (True) # use 10 divisions, no labels + + for ch in range(nchannels): + r = records[ch] + + # plot middle n points of record + + lb = npoints/2 - n/2 + ub = npoints/2 + n/2 + # points = zip (x_vals[lb:ub], r[lb:ub]) + points = Numeric.zeros ((ub-lb, 2), Numeric.Float64) + points[:,0] = x_vals[lb:ub] + points[:,1] = r[lb:ub] + + m = info.get_marker () + if m == 'line': + objects.append (plot.PolyLine (points, + colour=self.channel_color (ch), + legend=('Ch%d' % (ch+1,)))) + else: + objects.append (plot.PolyMarker (points, + marker=m, + colour=self.channel_color (ch), + legend=('Ch%d' % (ch+1,)))) + + graphics = plot.PlotGraphics (objects, + title=self.info.title, + xLabel = '', yLabel = '') + + time_per_div = info.get_time_per_div () + x_range = (-5.0 * time_per_div, 5.0 * time_per_div) # ranges are tuples! + volts_per_div = info.get_volts_per_div () + if not self.info.autorange: + self.y_range = (-4.0 * volts_per_div, 4.0 * volts_per_div) + self.Draw (graphics, xAxis=x_range, yAxis=self.y_range) + self.update_y_range () # autorange to self.y_range + + + def format_xy_data (self, evt): + info = self.info + records = evt.data + nchannels = len (records) + npoints = len (records[0]) + + if nchannels < 2: + return + + objects = [] + # points = zip (records[0], records[1]) + points = Numeric.zeros ((len(records[0]), 2), Numeric.Float32) + points[:,0] = records[0] + points[:,1] = records[1] + + self.SetXUseScopeTicks (False) + + m = info.get_marker () + if m == 'line': + objects.append (plot.PolyLine (points, + colour=self.channel_color (0))) + else: + objects.append (plot.PolyMarker (points, + marker=m, + colour=self.channel_color (0))) + + graphics = plot.PlotGraphics (objects, + title=self.info.title, + xLabel = 'I', yLabel = 'Q') + + self.Draw (graphics, xAxis=self.x_range, yAxis=self.y_range) + self.update_y_range () + self.update_x_range () + + + def update_y_range (self): + alpha = 1.0/25 + graphics = self.last_draw[0] + p1, p2 = graphics.boundingBox () # min, max points of graphics + + if self.avg_y_min: # prevent vertical scale from jumping abruptly --? + self.avg_y_min = p1[1] * alpha + self.avg_y_min * (1 - alpha) + self.avg_y_max = p2[1] * alpha + self.avg_y_max * (1 - alpha) + else: # initial guess + self.avg_y_min = p1[1] # -500.0 workaround, sometimes p1 is ~ 10^35 + self.avg_y_max = p2[1] # 500.0 + + self.y_range = self._axisInterval ('auto', self.avg_y_min, self.avg_y_max) + # print "p1 %s p2 %s y_min %s y_max %s y_range %s" \ + # % (p1, p2, self.avg_y_min, self.avg_y_max, self.y_range) + + + def update_x_range (self): + alpha = 1.0/25 + graphics = self.last_draw[0] + p1, p2 = graphics.boundingBox () # min, max points of graphics + + if self.avg_x_min: + self.avg_x_min = p1[0] * alpha + self.avg_x_min * (1 - alpha) + self.avg_x_max = p2[0] * alpha + self.avg_x_max * (1 - alpha) + else: + self.avg_x_min = p1[0] + self.avg_x_max = p2[0] + + self.x_range = self._axisInterval ('auto', self.avg_x_min, self.avg_x_max) + + +# ---------------------------------------------------------------- +# Stand-alone test application +# ---------------------------------------------------------------- + +class test_app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + if len(argv) > 1: + frame_decim = int(argv[1]) + else: + frame_decim = 1 + + if len(argv) > 2: + v_scale = float(argv[2]) # start up at this v_scale value + else: + v_scale = None # start up in autorange mode, default + + if len(argv) > 3: + t_scale = float(argv[3]) # start up at this t_scale value + else: + t_scale = None # old behavior + + print "frame decim %s v_scale %s t_scale %s" % (frame_decim,v_scale,t_scale) + + input_rate = 1e6 + + # Generate a complex sinusoid + src0 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 25.1e3, 1e3) + + # We add this throttle block so that this demo doesn't suck down + # all the CPU available. You normally wouldn't use it... + throttle = gr.throttle(gr.sizeof_gr_complex, input_rate) + + scope = scope_sink_c (self, panel,"Secret Data",sample_rate=input_rate, + frame_decim=frame_decim, + v_scale=v_scale, t_scale=t_scale) + vbox.Add (scope.win, 1, wx.EXPAND) + + # wire the blocks together + self.connect (src0, throttle, scope) + +def main (): + app = stdgui.stdapp (test_app_flow_graph, "O'Scope Test App") + app.MainLoop () + +if __name__ == '__main__': + main () + +# ---------------------------------------------------------------- diff --git a/gr-wxgui/src/python/slider.py b/gr-wxgui/src/python/slider.py new file mode 100755 index 00000000..e8cdcfca --- /dev/null +++ b/gr-wxgui/src/python/slider.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import wx + +def slider(parent, min, max, callback): + """ + Return a wx.Slider object. + + @param min: minimum slider value + @type min: float + @param max: maximum slider value + @type max: float + @param callback: function of one arg invoked when slider moves. + @rtype: wx.Slider + """ + new_id = wx.NewId() + s = wx.Slider(parent, new_id, (max+min)/2, min, max, wx.DefaultPosition, + wx.Size(250,-1), wx.SL_HORIZONTAL | wx.SL_LABELS) + wx.EVT_COMMAND_SCROLL(parent, new_id, + lambda evt : callback(evt.GetInt())) + return s + + +# ---------------------------------------------------------------- +# Demo app +# ---------------------------------------------------------------- +if __name__ == '__main__': + + from gnuradio.wxgui import stdgui + + class demo_graph(stdgui.gui_flow_graph): + + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + vbox.Add(slider(panel, 23, 47, self.my_callback1), 1, wx.ALIGN_CENTER) + vbox.Add(slider(panel, -100, 100, self.my_callback2), 1, wx.ALIGN_CENTER) + + def my_callback1(self, val): + print "cb1 = ", val + + def my_callback2(self, val): + print "cb2 = ", val + + def main (): + app = stdgui.stdapp (demo_graph, "Slider Demo") + app.MainLoop () + + main () diff --git a/gr-wxgui/src/python/stdgui.py b/gr-wxgui/src/python/stdgui.py new file mode 100644 index 00000000..76cc1773 --- /dev/null +++ b/gr-wxgui/src/python/stdgui.py @@ -0,0 +1,90 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +'''A simple wx gui for GNU Radio applications''' + +import wx +import sys +from gnuradio import gr + + +class stdapp (wx.App): + def __init__ (self, flow_graph_maker, title="GNU Radio", nstatus=2): + self.flow_graph_maker = flow_graph_maker + self.title = title + self._nstatus = nstatus + # All our initialization must come before calling wx.App.__init__. + # OnInit is called from somewhere in the guts of __init__. + wx.App.__init__ (self, redirect=False) + + def OnInit (self): + frame = stdframe (self.flow_graph_maker, self.title, self._nstatus) + frame.Show (True) + self.SetTopWindow (frame) + return True + + +class stdframe (wx.Frame): + def __init__ (self, flow_graph_maker, title="GNU Radio", nstatus=2): + # print "stdframe.__init__" + wx.Frame.__init__(self, None, -1, title) + + self.CreateStatusBar (nstatus) + mainmenu = wx.MenuBar () + + menu = wx.Menu () + item = menu.Append (200, 'E&xit', 'Exit') + self.Bind (wx.EVT_MENU, self.OnCloseWindow, item) + mainmenu.Append (menu, "&File") + self.SetMenuBar (mainmenu) + + self.Bind (wx.EVT_CLOSE, self.OnCloseWindow) + self.panel = stdpanel (self, self, flow_graph_maker) + vbox = wx.BoxSizer(wx.VERTICAL) + vbox.Add(self.panel, 1, wx.EXPAND) + self.SetSizer(vbox) + self.SetAutoLayout(True) + vbox.Fit(self) + + def OnCloseWindow (self, event): + self.flow_graph().stop() + self.Destroy () + + def flow_graph (self): + return self.panel.fg + +class stdpanel (wx.Panel): + def __init__ (self, parent, frame, flow_graph_maker): + # print "stdpanel.__init__" + wx.Panel.__init__ (self, parent, -1) + self.frame = frame + + vbox = wx.BoxSizer (wx.VERTICAL) + self.fg = flow_graph_maker (frame, self, vbox, sys.argv) + self.SetSizer (vbox) + self.SetAutoLayout (True) + vbox.Fit (self) + + self.fg.start () + +class gui_flow_graph (gr.flow_graph): + def __init__ (self, *ignore): + gr.flow_graph.__init__ (self) diff --git a/gr-wxgui/src/python/waterfallsink.py b/gr-wxgui/src/python/waterfallsink.py new file mode 100755 index 00000000..f5a6d243 --- /dev/null +++ b/gr-wxgui/src/python/waterfallsink.py @@ -0,0 +1,469 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru, window +from gnuradio.wxgui import stdgui +import wx +import gnuradio.wxgui.plot as plot +import Numeric +import os +import threading +import math + +default_fftsink_size = (640,240) +default_fft_rate = gr.prefs().get_long('wxgui', 'fft_rate', 15) + +class waterfall_sink_base(object): + def __init__(self, input_is_real=False, baseband_freq=0, + sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, + average=False, avg_alpha=None, title=''): + + # initialize common attributes + self.baseband_freq = baseband_freq + self.sample_rate = sample_rate + self.fft_size = fft_size + self.fft_rate = fft_rate + self.average = average + if avg_alpha is None: + self.avg_alpha = 2.0 / fft_rate + else: + self.avg_alpha = avg_alpha + self.title = title + self.input_is_real = input_is_real + (self.r_fd, self.w_fd) = os.pipe() + + def set_average(self, average): + self.average = average + if average: + self.avg.set_taps(self.avg_alpha) + else: + self.avg.set_taps(1.0) + + def set_avg_alpha(self, avg_alpha): + self.avg_alpha = avg_alpha + + def set_baseband_freq(self, baseband_freq): + self.baseband_freq = baseband_freq + + def set_sample_rate(self, sample_rate): + self.sample_rate = sample_rate + self._set_n() + + def _set_n(self): + self.one_in_n.set_n(max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + +class waterfall_sink_f(gr.hier_block, waterfall_sink_base): + def __init__(self, fg, parent, baseband_freq=0, + y_per_div=10, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, average=False, avg_alpha=None, + title='', size=default_fftsink_size): + + waterfall_sink_base.__init__(self, input_is_real=True, baseband_freq=baseband_freq, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title) + + s2p = gr.serial_to_parallel(gr.sizeof_float, self.fft_size) + self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fft_size, + max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + mywindow = window.blackmanharris(self.fft_size) + fft = gr.fft_vfc(self.fft_size, True, mywindow) + c2mag = gr.complex_to_mag(self.fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) + log = gr.nlog10_ff(20, self.fft_size, -20*math.log10(self.fft_size)) + sink = gr.file_descriptor_sink(gr.sizeof_float * self.fft_size, self.w_fd) + + fg.connect (s2p, self.one_in_n, fft, c2mag, self.avg, log, sink) + gr.hier_block.__init__(self, fg, s2p, sink) + + self.win = waterfall_window(self, parent, size=size) + self.set_average(self.average) + + +class waterfall_sink_c(gr.hier_block, waterfall_sink_base): + def __init__(self, fg, parent, baseband_freq=0, + y_per_div=10, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, average=False, avg_alpha=None, + title='', size=default_fftsink_size): + + waterfall_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title) + + s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, self.fft_size) + self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fft_size, + max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + + mywindow = window.blackmanharris(self.fft_size) + fft = gr.fft_vcc(self.fft_size, True, mywindow) + c2mag = gr.complex_to_mag(self.fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) + log = gr.nlog10_ff(20, self.fft_size, -20*math.log10(self.fft_size)) + sink = gr.file_descriptor_sink(gr.sizeof_float * self.fft_size, self.w_fd) + + fg.connect(s2p, self.one_in_n, fft, c2mag, self.avg, log, sink) + gr.hier_block.__init__(self, fg, s2p, sink) + + self.win = waterfall_window(self, parent, size=size) + self.set_average(self.average) + + +# ------------------------------------------------------------------------ + +myDATA_EVENT = wx.NewEventType() +EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0) + + +class DataEvent(wx.PyEvent): + def __init__(self, data): + wx.PyEvent.__init__(self) + self.SetEventType (myDATA_EVENT) + self.data = data + + def Clone (self): + self.__class__ (self.GetId()) + + +class input_watcher (threading.Thread): + def __init__ (self, file_descriptor, fft_size, event_receiver, **kwds): + threading.Thread.__init__ (self, **kwds) + self.setDaemon (1) + self.file_descriptor = file_descriptor + self.fft_size = fft_size + self.event_receiver = event_receiver + self.keep_running = True + self.start () + + def run (self): + while (self.keep_running): + s = gru.os_read_exactly (self.file_descriptor, + gr.sizeof_float * self.fft_size) + if not s: + self.keep_running = False + break + + complex_data = Numeric.fromstring (s, Numeric.Float32) + de = DataEvent (complex_data) + wx.PostEvent (self.event_receiver, de) + del de + + +class waterfall_window (wx.Panel): + def __init__ (self, fftsink, parent, id = -1, + pos = wx.DefaultPosition, size = wx.DefaultSize, + style = wx.DEFAULT_FRAME_STYLE, name = ""): + wx.Panel.__init__(self, parent, id, pos, size, style, name) + + self.fftsink = fftsink + self.bm = wx.EmptyBitmap(self.fftsink.fft_size, 300, -1) + + self.scale_factor = 5.0 # FIXME should autoscale, or set this + + dc1 = wx.MemoryDC() + dc1.SelectObject(self.bm) + dc1.Clear() + + self.pens = self.make_pens() + + wx.EVT_PAINT( self, self.OnPaint ) + wx.EVT_CLOSE (self, self.on_close_window) + EVT_DATA_EVENT (self, self.set_data) + + self.build_popup_menu() + + wx.EVT_CLOSE (self, self.on_close_window) + self.Bind(wx.EVT_RIGHT_UP, self.on_right_click) + + self.input_watcher = input_watcher(fftsink.r_fd, fftsink.fft_size, self) + + + def on_close_window (self, event): + print "waterfall_window: on_close_window" + self.keep_running = False + + def const_list(self,const,len): + return [const] * len + + def make_colormap(self): + r = [] + r.extend(self.const_list(0,96)) + r.extend(range(0,255,4)) + r.extend(self.const_list(255,64)) + r.extend(range(255,128,-4)) + + g = [] + g.extend(self.const_list(0,32)) + g.extend(range(0,255,4)) + g.extend(self.const_list(255,64)) + g.extend(range(255,0,-4)) + g.extend(self.const_list(0,32)) + + b = range(128,255,4) + b.extend(self.const_list(255,64)) + b.extend(range(255,0,-4)) + b.extend(self.const_list(0,96)) + return (r,g,b) + + def make_pens(self): + (r,g,b) = self.make_colormap() + pens = [] + for i in range(0,256): + colour = wx.Colour(r[i], g[i], b[i]) + pens.append( wx.Pen(colour, 2, wx.SOLID)) + return pens + + def OnPaint(self, event): + dc = wx.PaintDC(self) + self.DoDrawing(dc) + + def DoDrawing(self, dc=None): + if dc is None: + dc = wx.ClientDC(self) + dc.DrawBitmap(self.bm, 0, 0, False ) + + + def const_list(self,const,len): + a = [const] + for i in range(1,len): + a.append(const) + return a + + def make_colormap(self): + r = [] + r.extend(self.const_list(0,96)) + r.extend(range(0,255,4)) + r.extend(self.const_list(255,64)) + r.extend(range(255,128,-4)) + + g = [] + g.extend(self.const_list(0,32)) + g.extend(range(0,255,4)) + g.extend(self.const_list(255,64)) + g.extend(range(255,0,-4)) + g.extend(self.const_list(0,32)) + + b = range(128,255,4) + b.extend(self.const_list(255,64)) + b.extend(range(255,0,-4)) + b.extend(self.const_list(0,96)) + return (r,g,b) + + def set_data (self, evt): + dB = evt.data + L = len (dB) + + dc1 = wx.MemoryDC() + dc1.SelectObject(self.bm) + dc1.Blit(0,1,self.fftsink.fft_size,300,dc1,0,0,wx.COPY,False,-1,-1) + + x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq)) + if x >= 1e9: + sf = 1e-9 + units = "GHz" + elif x >= 1e6: + sf = 1e-6 + units = "MHz" + else: + sf = 1e-3 + units = "kHz" + + + if self.fftsink.input_is_real: # only plot 1/2 the points + d_max = L/2 + p_width = 2 + else: + d_max = L/2 + p_width = 1 + + scale_factor = self.scale_factor + if self.fftsink.input_is_real: # real fft + for x_pos in range(0, d_max): + value = int(dB[x_pos] * scale_factor) + value = min(255, max(0, value)) + dc1.SetPen(self.pens[value]) + dc1.DrawRectangle(x_pos*p_width, 0, p_width, 1) + else: # complex fft + for x_pos in range(0, d_max): # positive freqs + value = int(dB[x_pos] * scale_factor) + value = min(255, max(0, value)) + dc1.SetPen(self.pens[value]) + dc1.DrawRectangle(x_pos*p_width + d_max, 0, p_width, 1) + for x_pos in range(0 , d_max): # negative freqs + value = int(dB[x_pos+d_max] * scale_factor) + value = min(255, max(0, value)) + dc1.SetPen(self.pens[value]) + dc1.DrawRectangle(x_pos*p_width, 0, p_width, 1) + + self.DoDrawing (None) + + def on_average(self, evt): + # print "on_average" + self.fftsink.set_average(evt.IsChecked()) + + def on_right_click(self, event): + menu = self.popup_menu + for id, pred in self.checkmarks.items(): + item = menu.FindItemById(id) + item.Check(pred()) + self.PopupMenu(menu, event.GetPosition()) + + + def build_popup_menu(self): + self.id_incr_ref_level = wx.NewId() + self.id_decr_ref_level = wx.NewId() + self.id_incr_y_per_div = wx.NewId() + self.id_decr_y_per_div = wx.NewId() + self.id_y_per_div_1 = wx.NewId() + self.id_y_per_div_2 = wx.NewId() + self.id_y_per_div_5 = wx.NewId() + self.id_y_per_div_10 = wx.NewId() + self.id_y_per_div_20 = wx.NewId() + self.id_average = wx.NewId() + + self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) + #self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) + #self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) + #self.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) + #self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) + #self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) + #self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) + #self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) + #self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) + #self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) + + + # make a menu + menu = wx.Menu() + self.popup_menu = menu + menu.AppendCheckItem(self.id_average, "Average") + # menu.Append(self.id_incr_ref_level, "Incr Ref Level") + # menu.Append(self.id_decr_ref_level, "Decr Ref Level") + # menu.Append(self.id_incr_y_per_div, "Incr dB/div") + # menu.Append(self.id_decr_y_per_div, "Decr dB/div") + # menu.AppendSeparator() + # we'd use RadioItems for these, but they're not supported on Mac + #menu.AppendCheckItem(self.id_y_per_div_1, "1 dB/div") + #menu.AppendCheckItem(self.id_y_per_div_2, "2 dB/div") + #menu.AppendCheckItem(self.id_y_per_div_5, "5 dB/div") + #menu.AppendCheckItem(self.id_y_per_div_10, "10 dB/div") + #menu.AppendCheckItem(self.id_y_per_div_20, "20 dB/div") + + self.checkmarks = { + self.id_average : lambda : self.fftsink.average + #self.id_y_per_div_1 : lambda : self.fftsink.y_per_div == 1, + #self.id_y_per_div_2 : lambda : self.fftsink.y_per_div == 2, + #self.id_y_per_div_5 : lambda : self.fftsink.y_per_div == 5, + #self.id_y_per_div_10 : lambda : self.fftsink.y_per_div == 10, + #self.id_y_per_div_20 : lambda : self.fftsink.y_per_div == 20, + } + + +def next_up(v, seq): + """ + Return the first item in seq that is > v. + """ + for s in seq: + if s > v: + return s + return v + +def next_down(v, seq): + """ + Return the last item in seq that is < v. + """ + rseq = list(seq[:]) + rseq.reverse() + + for s in rseq: + if s < v: + return s + return v + + +# ---------------------------------------------------------------- +# Deprecated interfaces +# ---------------------------------------------------------------- + +# returns (block, win). +# block requires a single input stream of float +# win is a subclass of wxWindow + +def make_waterfall_sink_f(fg, parent, title, fft_size, input_rate): + + block = waterfall_sink_f(fg, parent, title=title, fft_size=fft_size, + sample_rate=input_rate) + return (block, block.win) + +# returns (block, win). +# block requires a single input stream of gr_complex +# win is a subclass of wxWindow + +def make_waterfall_sink_c(fg, parent, title, fft_size, input_rate): + block = waterfall_sink_c(fg, parent, title=title, fft_size=fft_size, + sample_rate=input_rate) + return (block, block.win) + + +# ---------------------------------------------------------------- +# Standalone test app +# ---------------------------------------------------------------- + +class test_app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + fft_size = 512 + + # build our flow graph + input_rate = 20.000e3 + + # Generate a complex sinusoid + src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 5.75e3, 1000) + #src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1000) + + # We add these throttle blocks so that this demo doesn't + # suck down all the CPU available. Normally you wouldn't use these. + thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate) + + sink1 = waterfall_sink_c (self, panel, title="Complex Data", fft_size=fft_size, + sample_rate=input_rate, baseband_freq=100e3) + vbox.Add (sink1.win, 1, wx.EXPAND) + self.connect (src1, thr1, sink1) + + # generate a real sinusoid + src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 5.75e3, 1000) + #src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1000) + thr2 = gr.throttle(gr.sizeof_float, input_rate) + sink2 = waterfall_sink_f (self, panel, title="Real Data", fft_size=fft_size, + sample_rate=input_rate, baseband_freq=100e3) + vbox.Add (sink2.win, 1, wx.EXPAND) + self.connect (src2, thr2, sink2) + +def main (): + app = stdgui.stdapp (test_app_flow_graph, + "Waterfall Sink Test App") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/pmt/AUTHORS b/pmt/AUTHORS new file mode 100644 index 00000000..ee4560a5 --- /dev/null +++ b/pmt/AUTHORS @@ -0,0 +1 @@ +Eric Blossom diff --git a/pmt/ChangeLog b/pmt/ChangeLog new file mode 100644 index 00000000..385dbc6d --- /dev/null +++ b/pmt/ChangeLog @@ -0,0 +1,20 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/pmt/Makefile.am b/pmt/Makefile.am new file mode 100644 index 00000000..d16c4691 --- /dev/null +++ b/pmt/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src +DIST_SUBDIRS = src doc diff --git a/pmt/README b/pmt/README new file mode 100644 index 00000000..a5785061 --- /dev/null +++ b/pmt/README @@ -0,0 +1,45 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +This directory hierarchy contains an implementation of +polymorphic types. These are similar to lisp or python data objects, +and implement transparent reference counting using the boost shared_ptr +templates. + +To build the examples from the tarball use the normal recipe: + + $ ./configure + $ make + $ make check + +If you're building from CVS, you'll need to use this sequence, since +CVS doesn't contain configure or the generated Makefiles. + + $ ./bootstrap + $ ./configure + $ make + $ make check + + +The doc directory is not built by default. This is to avoid spurious +build problems on systems that don't have xmlto installed. If you +have xmlto and its dependencies installed, you can build the html +version of the howto article by cd'ing to doc and invoking make. diff --git a/pmt/doc/Makefile.am b/pmt/doc/Makefile.am new file mode 100644 index 00000000..2774a844 --- /dev/null +++ b/pmt/doc/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +TARGETS = + + +# To avoid build problems for folks who don't have xmlto installed, we +# don't build the docs by default. + +# html: $(TARGETS) +all: $(TARGETS) + + +EXTRA_DIST = + +BUILT_XML_FILES = + + +# ---------------------------------------------------------------- + +clean: + -rm -f $(TARGETS) $(BUILT_XML_FILES) + +%.html : %.xml + xmlto html-nochunks $< diff --git a/pmt/src/Makefile.am b/pmt/src/Makefile.am new file mode 100644 index 00000000..8b32a223 --- /dev/null +++ b/pmt/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = lib diff --git a/pmt/src/lib/Makefile.am b/pmt/src/lib/Makefile.am new file mode 100644 index 00000000..2f3eab73 --- /dev/null +++ b/pmt/src/lib/Makefile.am @@ -0,0 +1,71 @@ +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +TESTS = test_pmt + +lib_LTLIBRARIES = libpmt.la libpmt-qa.la + +# These are the source files that go into the pmt shared library +libpmt_la_SOURCES = \ + pmt.cc + +# magic flags +libpmt_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version + +# link the library against the c++ standard library +libpmt_la_LIBADD = \ + -lstdc++ + +include_HEADERS = \ + pmt.h + +noinst_HEADERS = \ + pmt_int.h \ + qa_pmt.h \ + qa_pmt_prims.h + + +# Build the qa code into its own library + +libpmt_qa_la_SOURCES = \ + qa_pmt.cc \ + qa_pmt_prims.cc + +# magic flags +libpmt_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version + +# link the library against the c++ standard library +libpmt_qa_la_LIBADD = \ + $(CPPUNIT_LIBS) \ + -lstdc++ + + +noinst_PROGRAMS = \ + test_pmt + + +LIBPMT = libpmt.la +LIBPMTQA = libpmt-qa.la $(LIBPMT) + +test_pmt_SOURCES = test_pmt.cc +test_pmt_LDADD = $(LIBPMTQA) diff --git a/pmt/src/lib/pmt.cc b/pmt/src/lib/pmt.cc new file mode 100644 index 00000000..a1569e41 --- /dev/null +++ b/pmt/src/lib/pmt.cc @@ -0,0 +1,705 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include "pmt_int.h" + +pmt_base::~pmt_base() +{ + // nop -- out of line virtual destructor +} + +//////////////////////////////////////////////////////////////////////////// +// Exceptions +//////////////////////////////////////////////////////////////////////////// + +pmt_exception::pmt_exception(const char *msg, pmt_t obj) + : d_msg(msg), d_obj(obj) +{ +} + +pmt_wrong_type::pmt_wrong_type(const char *msg, pmt_t obj) + : pmt_exception(msg, obj) +{ +} + +pmt_out_of_range::pmt_out_of_range(const char *msg, pmt_t obj) + : pmt_exception(msg, obj) +{ +} + +//////////////////////////////////////////////////////////////////////////// +// Dynamic Casts +//////////////////////////////////////////////////////////////////////////// + +static pmt_symbol * +_symbol(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +static pmt_integer * +_integer(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +static pmt_real * +_real(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +static pmt_complex * +_complex(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +static pmt_pair * +_pair(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +static pmt_vector * +_vector(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +static pmt_dict * +_dict(pmt_t x) +{ + return dynamic_cast(x.get()); +} + +//////////////////////////////////////////////////////////////////////////// +// Booleans +//////////////////////////////////////////////////////////////////////////// + +const pmt_t PMT_BOOL_T = pmt_t(new pmt_bool()); // singleton +const pmt_t PMT_BOOL_F = pmt_t(new pmt_bool()); // singleton + +pmt_bool::pmt_bool(){} + +bool +pmt_is_true(pmt_t obj) +{ + return obj != PMT_BOOL_F; +} + +bool +pmt_is_false(pmt_t obj) +{ + return obj == PMT_BOOL_F; +} + +bool +pmt_is_bool(pmt_t obj) +{ + return obj->is_bool(); +} + +pmt_t +pmt_from_bool(bool val) +{ + return val ? PMT_BOOL_T : PMT_BOOL_F; +} + +bool +pmt_to_bool(pmt_t val) +{ + if (val == PMT_BOOL_T) + return true; + if (val == PMT_BOOL_F) + return false; + throw pmt_wrong_type("pmt_to_bool", val); +} + +//////////////////////////////////////////////////////////////////////////// +// Symbols +//////////////////////////////////////////////////////////////////////////// + +static const unsigned int SYMBOL_HASH_TABLE_SIZE = 701; +static std::vector s_symbol_hash_table(SYMBOL_HASH_TABLE_SIZE); + +pmt_symbol::pmt_symbol(const std::string &name) : d_name(name){} + + +static unsigned int +hash_string(const std::string &s) +{ + unsigned int h = 0; + unsigned int g = 0; + + for (std::string::const_iterator p = s.begin(); p != s.end(); p++){ + h = (h << 4) + (*p & 0xff); + g = h & 0xf0000000; + if (g){ + h = h ^ (g >> 24); + h = h ^ g; + } + } + return h; +} + +bool +pmt_is_symbol(pmt_t obj) +{ + return obj->is_symbol(); +} + +pmt_t +pmt_string_to_symbol(const std::string &name) +{ + unsigned hash = hash_string(name) % SYMBOL_HASH_TABLE_SIZE; + + // Does a symbol with this name already exist? + for (pmt_t sym = s_symbol_hash_table[hash]; sym; sym = _symbol(sym)->next()){ + if (name == _symbol(sym)->name()) + return sym; // Yes. Return it + } + + // Nope. Make a new one. + pmt_t sym = pmt_t(new pmt_symbol(name)); + _symbol(sym)->set_next(s_symbol_hash_table[hash]); + s_symbol_hash_table[hash] = sym; + return sym; +} + +const std::string +pmt_symbol_to_string(pmt_t sym) +{ + if (!sym->is_symbol()) + throw pmt_wrong_type("pmt_symbol_to_string", sym); + + return _symbol(sym)->name(); +} + +//////////////////////////////////////////////////////////////////////////// +// Number +//////////////////////////////////////////////////////////////////////////// + +bool +pmt_is_number(pmt_t x) +{ + return x->is_number(); +} + +//////////////////////////////////////////////////////////////////////////// +// Integer +//////////////////////////////////////////////////////////////////////////// + +pmt_integer::pmt_integer(long value) : d_value(value) {} + +bool +pmt_is_integer(pmt_t x) +{ + return x->is_integer(); +} + + +pmt_t +pmt_from_long(long x) +{ + return pmt_t(new pmt_integer(x)); +} + +long +pmt_to_long(pmt_t x) +{ + if (x->is_integer()) + return _integer(x)->value(); + + throw pmt_wrong_type("pmt_to_long", x); +} + +//////////////////////////////////////////////////////////////////////////// +// Real +//////////////////////////////////////////////////////////////////////////// + +pmt_real::pmt_real(double value) : d_value(value) {} + +bool +pmt_is_real(pmt_t x) +{ + return x->is_real(); +} + +pmt_t +pmt_from_double(double x) +{ + return pmt_t(new pmt_real(x)); +} + +double +pmt_to_double(pmt_t x) +{ + if (x->is_real()) + return _real(x)->value(); + if (x->is_integer()) + return _integer(x)->value(); + + throw pmt_wrong_type("pmt_to_double", x); +} + +//////////////////////////////////////////////////////////////////////////// +// Complex +//////////////////////////////////////////////////////////////////////////// + +pmt_complex::pmt_complex(std::complex value) : d_value(value) {} + +bool +pmt_is_complex(pmt_t x) +{ + return x->is_complex(); +} + +pmt_t +pmt_make_rectangular(double re, double im) +{ + return pmt_t(new pmt_complex(std::complex(re, im))); +} + +std::complex +pmt_to_complex(pmt_t x) +{ + if (x->is_complex()) + return _complex(x)->value(); + if (x->is_real()) + return _real(x)->value(); + if (x->is_integer()) + return _integer(x)->value(); + + throw pmt_wrong_type("pmt_to_complex", x); +} + +//////////////////////////////////////////////////////////////////////////// +// Pairs +//////////////////////////////////////////////////////////////////////////// + +const pmt_t PMT_NIL = pmt_t(new pmt_null()); // singleton + +pmt_null::pmt_null() {} +pmt_pair::pmt_pair(pmt_t car, pmt_t cdr) : d_car(car), d_cdr(cdr) {} + +bool +pmt_is_null(pmt_t x) +{ + return x == PMT_NIL; +} + +bool +pmt_is_pair(pmt_t obj) +{ + return obj->is_pair(); +} + +pmt_t +pmt_cons(pmt_t x, pmt_t y) +{ + return pmt_t(new pmt_pair(x, y)); +} + +pmt_t +pmt_car(pmt_t pair) +{ + if (pair->is_pair()) + return _pair(pair)->car(); + + throw pmt_wrong_type("pmt_car", pair); +} + +pmt_t +pmt_cdr(pmt_t pair) +{ + if (pair->is_pair()) + return _pair(pair)->cdr(); + + throw pmt_wrong_type("pmt_cdr", pair); +} + +void +pmt_set_car(pmt_t pair, pmt_t obj) +{ + if (pair->is_pair()) + _pair(pair)->set_car(obj); + else + throw pmt_wrong_type("pmt_set_car", pair); +} + +void +pmt_set_cdr(pmt_t pair, pmt_t obj) +{ + if (pair->is_pair()) + _pair(pair)->set_cdr(obj); + else + throw pmt_wrong_type("pmt_set_cdr", pair); +} + +//////////////////////////////////////////////////////////////////////////// +// Vectors +//////////////////////////////////////////////////////////////////////////// + +pmt_vector::pmt_vector(size_t len, pmt_t fill) + : d_v(len) +{ + for (size_t i = 0; i < len; i++) + d_v[i] = fill; +} + +pmt_t +pmt_vector::ref(size_t k) const +{ + if (k >= length()) + throw pmt_out_of_range("pmt_vector_ref", pmt_from_long(k)); + return d_v[k]; +} + +void +pmt_vector::set(size_t k, pmt_t obj) +{ + if (k >= length()) + throw pmt_out_of_range("pmt_vector_set", pmt_from_long(k)); + d_v[k] = obj; +} + +void +pmt_vector::fill(pmt_t obj) +{ + for (size_t i = 0; i < length(); i++) + d_v[i] = obj; +} + +bool +pmt_is_vector(pmt_t obj) +{ + return obj->is_vector(); +} + +pmt_t +pmt_make_vector(size_t k, pmt_t fill) +{ + return pmt_t(new pmt_vector(k, fill)); +} + +pmt_t +pmt_vector_ref(pmt_t vector, size_t k) +{ + if (!vector->is_vector()) + throw pmt_wrong_type("pmt_vector_ref", vector); + return _vector(vector)->ref(k); +} + +void +pmt_vector_set(pmt_t vector, size_t k, pmt_t obj) +{ + if (!vector->is_vector()) + throw pmt_wrong_type("pmt_vector_set", vector); + _vector(vector)->set(k, obj); +} + +void +pmt_vector_fill(pmt_t vector, pmt_t obj) +{ + if (!vector->is_vector()) + throw pmt_wrong_type("pmt_vector_set", vector); + _vector(vector)->fill(obj); +} + +//////////////////////////////////////////////////////////////////////////// +// Dictionaries +//////////////////////////////////////////////////////////////////////////// + +pmt_dict::pmt_dict() + : d_alist(PMT_NIL) +{ +} + +void +pmt_dict::set(pmt_t key, pmt_t value) +{ + pmt_t p = pmt_assv(key, d_alist); // look for (key . value) pair + if (pmt_is_pair(p)){ // found existing pair... + pmt_set_cdr(p, value); // overrwrite cdr with new value + } + else { // not in the dict + d_alist = pmt_cons(pmt_cons(key, value), d_alist); // add new (key . value) pair + } +} + +pmt_t +pmt_dict::ref(pmt_t key, pmt_t not_found) const +{ + pmt_t p = pmt_assv(key, d_alist); // look for (key . value) pair + if (pmt_is_pair(p)) + return pmt_cdr(p); + else + return not_found; +} + +bool +pmt_dict::has_key(pmt_t key) const +{ + return pmt_is_pair(pmt_assv(key, d_alist)); +} + +pmt_t +pmt_dict::items() const +{ + return d_alist; +} + +pmt_t +pmt_dict::keys() const +{ + return pmt_map(pmt_car, d_alist); +} + +pmt_t +pmt_dict::values() const +{ + return pmt_map(pmt_cdr, d_alist); +} + +bool +pmt_is_dict(pmt_t obj) +{ + return obj->is_dict(); +} + +pmt_t +pmt_make_dict() +{ + return pmt_t(new pmt_dict()); +} + +void +pmt_dict_set(pmt_t dict, pmt_t key, pmt_t value) +{ + if (!dict->is_dict()) + throw pmt_wrong_type("pmt_dict_set", dict); + + _dict(dict)->set(key, value); +} + +bool +pmt_dict_has_key(pmt_t dict, pmt_t key) +{ + if (!dict->is_dict()) + throw pmt_wrong_type("pmt_dict_has_key", dict); + + return _dict(dict)->has_key(key); +} + +pmt_t +pmt_dict_ref(pmt_t dict, pmt_t key, pmt_t not_found) +{ + if (!dict->is_dict()) + throw pmt_wrong_type("pmt_dict_ref", dict); + + return _dict(dict)->ref(key, not_found); +} + +pmt_t +pmt_dict_items(pmt_t dict) +{ + if (!dict->is_dict()) + throw pmt_wrong_type("pmt_dict_items", dict); + + return _dict(dict)->items(); +} + +pmt_t +pmt_dict_keys(pmt_t dict) +{ + if (!dict->is_dict()) + throw pmt_wrong_type("pmt_dict_keys", dict); + + return _dict(dict)->keys(); +} + +pmt_t +pmt_dict_values(pmt_t dict) +{ + if (!dict->is_dict()) + throw pmt_wrong_type("pmt_dict_values", dict); + + return _dict(dict)->values(); +} + +//////////////////////////////////////////////////////////////////////////// +// General Functions +//////////////////////////////////////////////////////////////////////////// + +bool +pmt_eq(pmt_t x, pmt_t y) +{ + return x == y; +} + +bool +pmt_eqv(pmt_t x, pmt_t y) +{ + if (x == y) + return true; + + if (x->is_integer() && y->is_integer()) + return _integer(x)->value() == _integer(y)->value(); + + if (x->is_real() && y->is_real()) + return _real(x)->value() == _real(y)->value(); + + if (x->is_complex() && y->is_complex()) + return _complex(x)->value() == _complex(y)->value(); + + return false; +} + +bool +pmt_equal(pmt_t x, pmt_t y) +{ + if (pmt_eqv(x, y)) + return true; + + if (x->is_pair() && y->is_pair()) + return pmt_equal(pmt_car(x), pmt_car(y)) && pmt_equal(pmt_cdr(x), pmt_cdr(y)); + + if (x->is_vector() && y->is_vector()){ + pmt_vector *xv = _vector(x); + pmt_vector *yv = _vector(y); + if (xv->length() != yv->length()) + return false; + + for (unsigned i = 0; i < xv->length(); i++) + if (!pmt_equal(xv->_ref(i), yv->_ref(i))) + return false; + + return true; + } + + // FIXME add other cases here... + + return false; +} + +size_t +pmt_length(pmt_t x) +{ + if (x->is_vector()) + return _vector(x)->length(); + + // FIXME list length + // FIXME uniform vector length + // FIXME dictionary length (number of entries) + + throw pmt_wrong_type("pmt_length", x); +} + +pmt_t +pmt_assq(pmt_t obj, pmt_t alist) +{ + while (pmt_is_pair(alist)){ + pmt_t p = pmt_car(alist); + if (!pmt_is_pair(p)) // malformed alist + return PMT_BOOL_F; + + if (pmt_eq(obj, pmt_car(p))) + return p; + + alist = pmt_cdr(alist); + } + return PMT_BOOL_F; +} + +pmt_t +pmt_assv(pmt_t obj, pmt_t alist) +{ + while (pmt_is_pair(alist)){ + pmt_t p = pmt_car(alist); + if (!pmt_is_pair(p)) // malformed alist + return PMT_BOOL_F; + + if (pmt_eqv(obj, pmt_car(p))) + return p; + + alist = pmt_cdr(alist); + } + return PMT_BOOL_F; +} + +pmt_t +pmt_assoc(pmt_t obj, pmt_t alist) +{ + while (pmt_is_pair(alist)){ + pmt_t p = pmt_car(alist); + if (!pmt_is_pair(p)) // malformed alist + return PMT_BOOL_F; + + if (pmt_equal(obj, pmt_car(p))) + return p; + + alist = pmt_cdr(alist); + } + return PMT_BOOL_F; +} + +pmt_t +pmt_map(pmt_t proc(pmt_t), pmt_t list) +{ + pmt_t r = PMT_NIL; + + while(pmt_is_pair(list)){ + r = pmt_cons(proc(pmt_car(list)), r); + list = pmt_cdr(list); + } + + return pmt_reverse_x(r); +} + +pmt_t +pmt_reverse(pmt_t listx) +{ + pmt_t list = listx; + pmt_t r = PMT_NIL; + + while(pmt_is_pair(list)){ + r = pmt_cons(pmt_car(list), r); + list = pmt_cdr(list); + } + if (pmt_is_null(list)) + return r; + else + throw pmt_wrong_type("pmt_reverse", listx); +} + +pmt_t +pmt_reverse_x(pmt_t list) +{ + // FIXME do it destructively + return pmt_reverse(list); +} diff --git a/pmt/src/lib/pmt.h b/pmt/src/lib/pmt.h new file mode 100644 index 00000000..b27b7ce1 --- /dev/null +++ b/pmt/src/lib/pmt.h @@ -0,0 +1,554 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_PMT_H +#define INCLUDED_PMT_H + +#include +#include +#include +#include +#include + +/*! + * This file defines a polymorphic type and the operations on it. + * + * It draws heavily on the idea of scheme and lisp data types. + * The interface parallels that in Guile 1.8, with the notable + * exception that these objects are transparently reference counted. + */ + +/*! + * \brief base class of all pmt types + */ +class pmt_base; + +/*! + * \brief typedef for shared pointer (transparent reference counting). + * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + */ +typedef boost::shared_ptr pmt_t; + + +class pmt_exception +{ + const char *d_msg; + pmt_t d_obj; + +public: + pmt_exception(const char *msg, pmt_t obj); + const char *msg() { return d_msg; } + pmt_t obj() { return d_obj; } +}; + +class pmt_wrong_type : public pmt_exception +{ +public: + pmt_wrong_type(const char *msg, pmt_t obj); +}; + +class pmt_out_of_range : public pmt_exception +{ +public: + pmt_out_of_range(const char *msg, pmt_t obj); +}; + +/* + * ------------------------------------------------------------------------ + * Booleans. Two constants, #t and #f. + * + * In predicates, anything that is not #f is considered true. + * I.e., there is a single false value, #f. + * ------------------------------------------------------------------------ + */ +extern const pmt_t PMT_BOOL_T; //< #t : boolean true constant +extern const pmt_t PMT_BOOL_F; //< #f : boolean false constant + +//! Return true if obj is #t or #f, else return false. +bool pmt_is_bool(pmt_t obj); + +//! Return false if obj is #f, else return true. +bool pmt_is_true(pmt_t obj); + +//! Return true if obj is #f, else return true. +bool pmt_is_false(pmt_t obj); + +//! Return #f is val is false, else return #t. +pmt_t pmt_from_bool(bool val); + +//! Return true if val is PMT_BOOL_T, return false when val is PMT_BOOL_F, +// else raise wrong_type exception. +bool pmt_to_bool(pmt_t val); + +/* + * ------------------------------------------------------------------------ + * Symbols + * ------------------------------------------------------------------------ + */ + +//! Return true if obj is a symbol, else false. +bool pmt_is_symbol(pmt_t obj); + +//! Return the symbol whose name is \p s. +pmt_t pmt_string_to_symbol(const std::string &s); + +/*! + * If \p is a symbol, return the name of the symbol as a string. + * Otherwise, raise the wrong_type exception. + */ +const std::string pmt_symbol_to_string(pmt_t sym); + +/* + * ------------------------------------------------------------------------ + * Numbers: we support integer, real and complex + * ------------------------------------------------------------------------ + */ + +//! Return true if obj is any kind of number, else false. +bool pmt_is_number(pmt_t obj); + +/* + * ------------------------------------------------------------------------ + * Integers + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is an integer number, else false +bool pmt_is_integer(pmt_t x); + +//! Return the pmt value that represents the integer \p x. +pmt_t pmt_from_long(long x); + +/*! + * \brief Convert pmt to long if possible. + * + * When \p x represents an exact integer that fits in a long, + * return that integer. Else raise an exception, either wrong_type + * when x is not an exact integer, or out_of_range when it doesn't fit. + */ +long pmt_to_long(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * Reals + * ------------------------------------------------------------------------ + */ + +/* + * \brief Return true if \p obj is a real number, else false. + */ +bool pmt_is_real(pmt_t obj); + +//! Return the pmt value that represents double \p x. +pmt_t pmt_from_double(double x); + +/*! + * \brief Convert pmt to double if possible. + * + * Returns the number closest to \p val that is representable + * as a double. The argument \p val must be a real or integer, otherwise + * a wrong_type exception is raised. + */ +double pmt_to_double(pmt_t x); + +/* + * ------------------------------------------------------------------------ + * Complex + * ------------------------------------------------------------------------ + */ + +/*! + * \brief return true if \p obj is a complex number, false otherwise. + */ +bool pmt_is_complex(pmt_t obj); + +//! Return a complex number constructed of the given real and imaginary parts. +pmt_t pmt_make_rectangular(double re, double im); + +/*! + * If \p z is complex, real or integer, return the closest complex. + * Otherwise, raise the wrong_type exception. + */ +std::complex pmt_to_complex(pmt_t z); + +/* + * ------------------------------------------------------------------------ + * Pairs + * ------------------------------------------------------------------------ + */ + +extern const pmt_t PMT_NIL; //< the empty list + +//! Return true if \p x is the empty list, otherwise return false. +bool pmt_is_null(pmt_t x); + +//! Return true if \p obj is a pair, else false. +bool pmt_is_pair(pmt_t obj); + +//! Return a newly allocated pair whose car is \p x and whose cdr is \p y. +pmt_t pmt_cons(pmt_t x, pmt_t y); + +//! If \p pair is a pair, return the car of the \p pair, otherwise raise wrong_type. +pmt_t pmt_car(pmt_t pair); + +//! If \p pair is a pair, return the cdr of the \p pair, otherwise raise wrong_type. +pmt_t pmt_cdr(pmt_t pair); + +//! Stores \p value in the car field of \p pair. +void pmt_set_car(pmt_t pair, pmt_t value); + +//! Stores \p value in the cdr field of \p pair. +void pmt_set_cdr(pmt_t pair, pmt_t value); + +/* + * ------------------------------------------------------------------------ + * Vectors + * + * These vectors can hold any kind of objects. Indexing is zero based. + * ------------------------------------------------------------------------ + */ + +//! Return true if \p x is a vector, othewise false. +bool pmt_is_vector(pmt_t x); + +//! Make a vector of length \p k, with initial values set to \p fill +pmt_t pmt_make_vector(size_t k, pmt_t fill); + +/*! + * Return the contents of position \p k of \p vector. + * \p k must be a valid index of \p vector. + */ +pmt_t pmt_vector_ref(pmt_t vector, size_t k); + +//! Store \p obj in position \p k. +void pmt_vector_set(pmt_t vector, size_t k, pmt_t obj); + +//! Store \p fill in every position of \p vector +void pmt_vector_fill(pmt_t vector, pmt_t fill); + +/*! + *
+ * ------------------------------------------------------------------------
+ *		       Uniform Numeric Vectors
+ *
+ * A uniform numeric vector is a vector whose elements are all of single
+ * numeric type.  pmt offers uniform numeric vectors for signed and
+ * unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of
+ * floating point values, and complex floating-point numbers of these
+ * two sizes.  Indexing is zero based.
+ *
+ * The names of the functions include these tags in their names:
+ *
+ *    u8  unsigned 8-bit integers
+ *    s8  signed 8-bit integers
+ *   u16  unsigned 16-bit integers
+ *   s16  signed 16-bit integers
+ *   u32  unsigned 32-bit integers
+ *   s32  signed 32-bit integers
+ *   u64  unsigned 64-bit integers
+ *   s64  signed 64-bit integers
+ *   f32  the C++ type float
+ *   f64  the C++ type double
+ *   c32  the C++ type complex
+ *   c64  the C++ type complex
+ * ------------------------------------------------------------------------
+ * 
+ */ + +//! true if \p x is any kind of uniform numeric vector +bool pmt_is_uniform_vector(pmt_t x); + +bool pmt_is_u8vector(pmt_t x); +bool pmt_is_s8vector(pmt_t x); +bool pmt_is_u16vector(pmt_t x); +bool pmt_is_s16vector(pmt_t x); +bool pmt_is_u32vector(pmt_t x); +bool pmt_is_s32vector(pmt_t x); +bool pmt_is_u64vector(pmt_t x); +bool pmt_is_s64vector(pmt_t x); +bool pmt_is_f32vector(pmt_t x); +bool pmt_is_f64vector(pmt_t x); +bool pmt_is_c32vector(pmt_t x); +bool pmt_is_c64vector(pmt_t x); + +pmt_t pmt_make_u8vector(size_t k, uint8_t fill); +pmt_t pmt_make_s8vector(size_t k, int8_t fill); +pmt_t pmt_make_u16vector(size_t k, uint16_t fill); +pmt_t pmt_make_s16vector(size_t k, int16_t fill); +pmt_t pmt_make_u32vector(size_t k, uint32_t fill); +pmt_t pmt_make_s32vector(size_t k, int32_t fill); +pmt_t pmt_make_u64vector(size_t k, uint64_t fill); +pmt_t pmt_make_s64vector(size_t k, int64_t fill); +pmt_t pmt_make_f32vector(size_t k, float fill); +pmt_t pmt_make_f64vector(size_t k, double fill); +pmt_t pmt_make_c32vector(size_t k, std::complex fill); +pmt_t pmt_make_c64vector(size_t k, std::complex fill); + +pmt_t pmt_init_u8vector(size_t k, uint8_t *data); +pmt_t pmt_init_s8vector(size_t k, int8_t *data); +pmt_t pmt_init_u16vector(size_t k, uint16_t *data); +pmt_t pmt_init_s16vector(size_t k, int16_t *data); +pmt_t pmt_init_u32vector(size_t k, uint32_t *data); +pmt_t pmt_init_s32vector(size_t k, int32_t *data); +pmt_t pmt_init_u64vector(size_t k, uint64_t *data); +pmt_t pmt_init_s64vector(size_t k, int64_t *data); +pmt_t pmt_init_f32vector(size_t k, float *data); +pmt_t pmt_init_f64vector(size_t k, double *data); +pmt_t pmt_init_c32vector(size_t k, std::complex *data); +pmt_t pmt_init_c64vector(size_t k, std::complex *data); + +uint8_t pmt_u8vector_ref(pmt_t v, size_t k); +int8_t pmt_s8vector_ref(pmt_t v, size_t k); +uint16_t pmt_u16vector_ref(pmt_t v, size_t k); +int16_t pmt_s16vector_ref(pmt_t v, size_t k); +uint32_t pmt_u32vector_ref(pmt_t v, size_t k); +int32_t pmt_s32vector_ref(pmt_t v, size_t k); +uint64_t pmt_u64vector_ref(pmt_t v, size_t k); +int64_t pmt_s64vector_ref(pmt_t v, size_t k); +float pmt_f32vector_ref(pmt_t v, size_t k); +double pmt_f64vector_ref(pmt_t v, size_t k); +std::complex pmt_c32vector_ref(pmt_t v, size_t k); +std::complex pmt_c64vector_ref(pmt_t v, size_t k); + +void pmt_u8vector_set(pmt_t v, size_t k, uint8_t x); //< v[k] = x +void pmt_s8vector_set(pmt_t v, size_t k, int8_t x); +void pmt_u16vector_set(pmt_t v, size_t k, uint16_t x); +void pmt_s16vector_set(pmt_t v, size_t k, int16_t x); +void pmt_u32vector_set(pmt_t v, size_t k, uint32_t x); +void pmt_s32vector_set(pmt_t v, size_t k, int32_t x); +void pmt_u64vector_set(pmt_t v, size_t k, uint64_t x); +void pmt_s64vector_set(pmt_t v, size_t k, int64_t x); +void pmt_f32vector_set(pmt_t v, size_t k, float x); +void pmt_f64vector_set(pmt_t v, size_t k, double x); +void pmt_c32vector_set(pmt_t v, size_t k, std::complex x); +void pmt_c64vector_set(pmt_t v, size_t k, std::complex x); + +// Return const pointers to the elements + +const void *pmt_uniform_vector_elements(pmt_t v, size_t &len); //< works with any; len is in bytes + +const uint8_t *pmt_u8vector_elements(pmt_t v, size_t &len); //< len is in elements +const int8_t *pmt_s8vector_elements(pmt_t v, size_t &len); //< len is in elements +const uint16_t *pmt_u16vector_elements(pmt_t v, size_t &len); //< len is in elements +const int16_t *pmt_s16vector_elements(pmt_t v, size_t &len); //< len is in elements +const uint32_t *pmt_u32vector_elements(pmt_t v, size_t &len); //< len is in elements +const int32_t *pmt_s32vector_elements(pmt_t v, size_t &len); //< len is in elements +const uint64_t *pmt_u64vector_elements(pmt_t v, size_t &len); //< len is in elements +const int64_t *pmt_s64vector_elements(pmt_t v, size_t &len); //< len is in elements +const float *pmt_f32vector_elements(pmt_t v, size_t &len); //< len is in elements +const double *pmt_f64vector_elements(pmt_t v, size_t &len); //< len is in elements +const std::complex *pmt_c32vector_elements(pmt_t v, size_t &len); //< len is in elements +const std::complex *pmt_c64vector_elements(pmt_t v, size_t &len); //< len is in elements + +// Return non-const pointers to the elements + +void *pmt_uniform_vector_writeable_elements(pmt_t v, size_t &len); //< works with any; len is in bytes + +uint8_t *pmt_u8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int8_t *pmt_s8vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +uint16_t *pmt_u16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int16_t *pmt_s16vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +uint32_t *pmt_u32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int32_t *pmt_s32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +uint64_t *pmt_u64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +int64_t *pmt_s64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +float *pmt_f32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +double *pmt_f64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +std::complex *pmt_c32vector_writable_elements(pmt_t v, size_t &len); //< len is in elements +std::complex *pmt_c64vector_writable_elements(pmt_t v, size_t &len); //< len is in elements + +/* + * ------------------------------------------------------------------------ + * Dictionary (a.k.a associative array, hash, map) + * ------------------------------------------------------------------------ + */ + +//! Return true if \p obj is a dictionary +bool pmt_is_dict(pmt_t obj); + +//! make an empty dictionary +pmt_t pmt_make_dict(); + +//! dict[key] = value +void pmt_dict_set(pmt_t dict, pmt_t key, pmt_t value); + +//! Return true if \p key exists in \p dict +bool pmt_dict_has_key(pmt_t dict, pmt_t key); + +//! If \p key exists in \p dict, return associated value; otherwise return \p not_found. +pmt_t pmt_dict_ref(pmt_t dict, pmt_t key, pmt_t not_found); + +//! Return list of (key . value) pairs +pmt_t pmt_dict_items(pmt_t dict); + +//! Return list of keys +pmt_t pmt_dict_keys(pmt_t dict); + +//! Return list of values +pmt_t pmt_dict_values(pmt_t dict); + +/* + * ------------------------------------------------------------------------ + * General functions + * ------------------------------------------------------------------------ + */ + +//! Return true if x and y are the same object; otherwise return false. +bool pmt_eq(pmt_t x, pmt_t y); + +/*! + * \brief Return true if x and y should normally be regarded as the same object, else false. + * + *
+ * eqv returns true if:
+ *   x and y are the same object.
+ *   x and y are both #t or both #f.
+ *   x and y are both symbols and their names are the same.
+ *   x and y are both numbers, and are numerically equal.
+ *   x and y are both the empty list (nil).
+ *   x and y are pairs or vectors that denote same location in store.
+ * 
+ */ +bool pmt_eqv(pmt_t x, pmt_t y); + +/*! + * pmt_equal recursively compares the contents of pairs and vectors, + * applying pmt_eqv on other objects such as numbers and symbols. + * pmt_equal may fail to terminate if its arguments are circular data + * structures. + */ +bool pmt_equal(pmt_t x, pmt_t y); + + +//! Return the number of elements in v +size_t pmt_length(pmt_t v); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then #f is returned. + * Uses pmt_eq to compare \p obj with car fields of the pairs in \p alist. + */ +pmt_t pmt_assq(pmt_t obj, pmt_t alist); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then #f is returned. + * Uses pmt_eqv to compare \p obj with car fields of the pairs in \p alist. + */ +pmt_t pmt_assv(pmt_t obj, pmt_t alist); + +/*! + * \brief Find the first pair in \p alist whose car field is \p obj + * and return that pair. + * + * \p alist (for "association list") must be a list of pairs. If no pair + * in \p alist has \p obj as its car then #f is returned. + * Uses pmt_equal to compare \p obj with car fields of the pairs in \p alist. + */ +pmt_t pmt_assoc(pmt_t obj, pmt_t alist); + +/*! + * \brief Apply \p proc element-wise to the elements of list and returns + * a list of the results, in order. + * + * \p list must be a list. The dynamic order in which \p proc is + * applied to the elements of \p list is unspecified. + */ +pmt_t pmt_map(pmt_t proc(pmt_t), pmt_t list); + +/*! + * \brief reverse \p list. + * + * \p list must be a proper list. + */ +pmt_t pmt_reverse(pmt_t list); + +/*! + * \brief destructively reverse \p list. + * + * \p list must be a proper list. + */ +pmt_t pmt_reverse_x(pmt_t list); + +/*! + * \brief (acons x y a) == (cons (cons x y) a) + */ +inline static pmt_t +pmt_acons(pmt_t x, pmt_t y, pmt_t a) +{ + return pmt_cons(pmt_cons(x, y), a); +} + +/* + * ------------------------------------------------------------------------ + * read / write + * ------------------------------------------------------------------------ + */ +extern const pmt_t PMT_EOF; //< The end of file object + +//! return true if obj is the EOF object, otherwise return false. +bool pmt_is_eof_object(pmt_t obj); + +/*! + * read converts external representations of pmt objects into the + * objects themselves. Read returns the next object parsable from + * the given input port, updating port to point to the first + * character past the end of the external representation of the + * object. + * + * If an end of file is encountered in the input before any + * characters are found that can begin an object, then an end of file + * object is returned. The port remains open, and further attempts + * to read will also return an end of file object. If an end of file + * is encountered after the beginning of an object's external + * representation, but the external representation is incomplete and + * therefore not parsable, an error is signaled. + */ +pmt_t pmt_read(std::istream &port); + +/*! + * Write a written representation of \p obj to the given \p port. + */ +void pmt_write(pmt_t obj, std::ostream &port); + +/* + * ------------------------------------------------------------------------ + * portable byte stream representation + * ------------------------------------------------------------------------ + */ +/*! + * \brief Write portable byte-serial representation of \p obj to \p sink + */ +void pmt_serialize(pmt_t obj, std::ostream &sink); + +/*! + * \brief Create obj from portable byte-serial representation + */ +pmt_t pmt_deserialize(std::istream &source); + +#endif /* INCLUDED_PMT_H */ diff --git a/pmt/src/lib/pmt_int.h b/pmt/src/lib/pmt_int.h new file mode 100644 index 00000000..73354641 --- /dev/null +++ b/pmt/src/lib/pmt_int.h @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_PMT_INT_H +#define INCLUDED_PMT_INT_H + +#include + +/* + * EVERYTHING IN THIS FILE IS PRIVATE TO THE IMPLEMENTATION! + * + * See pmt.h for the public interface + */ + +class pmt_base { +protected: + pmt_base(){}; + virtual ~pmt_base(); + +private: + pmt_base(const pmt_base& rhs); // NOT IMPLEMENTED + pmt_base& operator=(const pmt_base& rhs); // NOT IMPLEMENTED + + +public: + virtual bool is_bool() const { return false; } + virtual bool is_symbol() const { return false; } + virtual bool is_number() const { return false; } + virtual bool is_integer() const { return false; } + virtual bool is_real() const { return false; } + virtual bool is_complex() const { return false; } + virtual bool is_null() const { return false; } + virtual bool is_pair() const { return false; } + virtual bool is_vector() const { return false; } + virtual bool is_dict() const { return false; } +}; + +class pmt_bool : public pmt_base +{ +public: + pmt_bool(); + //~pmt_bool(){} + + bool is_bool() const { return true; } +}; + + +class pmt_symbol : public pmt_base +{ + std::string d_name; + pmt_t d_next; + +public: + pmt_symbol(const std::string &name); + //~pmt_symbol(){} + + bool is_symbol() const { return true; } + const std::string name() { return d_name; } + + pmt_t next() { return d_next; } // symbol table link + void set_next(pmt_t next) { d_next = next; } +}; + +class pmt_integer : public pmt_base +{ + long d_value; + +public: + pmt_integer(long value); + //~pmt_integer(){} + + bool is_integer() const { return true; } + long value() const { return d_value; } +}; + +class pmt_real : public pmt_base +{ + double d_value; + +public: + pmt_real(double value); + //~pmt_real(){} + + bool is_real() const { return true; } + double value() const { return d_value; } +}; + +class pmt_complex : public pmt_base +{ + std::complex d_value; + +public: + pmt_complex(std::complex value); + //~pmt_complex(){} + + bool is_complex() const { return true; } + std::complex value() const { return d_value; } +}; + +class pmt_null : public pmt_base +{ +public: + pmt_null(); + //~pmt_null(){} + + bool is_null() const { return true; } +}; + +class pmt_pair : public pmt_base +{ + pmt_t d_car; + pmt_t d_cdr; + +public: + pmt_pair(pmt_t car, pmt_t cdr); + //~pmt_pair(){}; + + bool is_pair() const { return true; } + pmt_t car() const { return d_car; } + pmt_t cdr() const { return d_cdr; } + + void set_car(pmt_t car) { d_car = car; } + void set_cdr(pmt_t cdr) { d_cdr = cdr; } +}; + +class pmt_vector : public pmt_base +{ + std::vector d_v; + +public: + pmt_vector(size_t len, pmt_t fill); + //~pmt_vector(); + + bool is_vector() const { return true; } + pmt_t ref(size_t k) const; + void set(size_t k, pmt_t obj); + void fill(pmt_t fill); + size_t length() const { return d_v.size(); } + + pmt_t _ref(size_t k) const { return d_v[k]; } +}; + +class pmt_dict : public pmt_base +{ + pmt_t d_alist; // list of (key . value) pairs + +public: + pmt_dict(); + //~pmt_dict(); + + bool is_dict() const { return true; } + void set(pmt_t key, pmt_t value); + pmt_t ref(pmt_t key, pmt_t default_value) const; + bool has_key(pmt_t key) const; + pmt_t items() const; + pmt_t keys() const; + pmt_t values() const; +}; + +#endif /* INCLUDED_PMT_INT_H */ diff --git a/pmt/src/lib/qa_pmt.cc b/pmt/src/lib/qa_pmt.cc new file mode 100644 index 00000000..6ed681a6 --- /dev/null +++ b/pmt/src/lib/qa_pmt.cc @@ -0,0 +1,40 @@ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This class gathers together all the test cases for pmt into + * a single test suite. As you create new test cases, add them here. + */ + +#include +#include + +CppUnit::TestSuite * +qa_pmt::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("pmt"); + + s->addTest (qa_pmt_prims::suite ()); + //s->addTest (qa_gr_circular_file::suite ()); + //s->addTest (qa_gr_fxpt::suite ()); + + return s; +} diff --git a/pmt/src/lib/qa_pmt.h b/pmt/src/lib/qa_pmt.h new file mode 100644 index 00000000..166e7f84 --- /dev/null +++ b/pmt/src/lib/qa_pmt.h @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_QA_PMT_H +#define INCLUDED_QA_PMT_H + +#include + +//! collect all the tests for pmt + +class qa_pmt { + public: + //! return suite of tests for all of pmt + static CppUnit::TestSuite *suite (); +}; + +#endif /* INCLUDED_QA_PMT_H */ diff --git a/pmt/src/lib/qa_pmt_prims.cc b/pmt/src/lib/qa_pmt_prims.cc new file mode 100644 index 00000000..3c81a656 --- /dev/null +++ b/pmt/src/lib/qa_pmt_prims.cc @@ -0,0 +1,284 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +void +qa_pmt_prims::test_symbols() +{ + CPPUNIT_ASSERT(!pmt_is_symbol(PMT_BOOL_T)); + CPPUNIT_ASSERT(!pmt_is_symbol(PMT_BOOL_F)); + CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_BOOL_F), pmt_wrong_type); + + pmt_t sym1 = pmt_string_to_symbol("test"); + CPPUNIT_ASSERT(pmt_is_symbol(sym1)); + CPPUNIT_ASSERT_EQUAL(std::string("test"), pmt_symbol_to_string(sym1)); + CPPUNIT_ASSERT(pmt_is_true(sym1)); + CPPUNIT_ASSERT(!pmt_is_false(sym1)); + + pmt_t sym2 = pmt_string_to_symbol("foo"); + pmt_t sym3 = pmt_string_to_symbol("test"); + CPPUNIT_ASSERT_EQUAL(sym1, sym3); + CPPUNIT_ASSERT(sym1 != sym2); + CPPUNIT_ASSERT(sym1 == sym3); + + static const int N = 2048; + std::vector v1(N); + std::vector v2(N); + + // generate a bunch of symbols + for (int i = 0; i < N; i++){ + char buf[100]; + snprintf(buf, sizeof(buf), "test-%d", i); + v1[i] = pmt_string_to_symbol(buf); + } + + // confirm that they are all unique + for (int i = 0; i < N; i++) + for (int j = i + 1; j < N; j++) + CPPUNIT_ASSERT(v1[i] != v1[j]); + + // generate the same symbols again + for (int i = 0; i < N; i++){ + char buf[100]; + snprintf(buf, sizeof(buf), "test-%d", i); + v2[i] = pmt_string_to_symbol(buf); + } + + // confirm that we get the same ones back + for (int i = 0; i < N; i++) + CPPUNIT_ASSERT(v1[i] == v2[i]); +} + +void +qa_pmt_prims::test_booleans() +{ + pmt_t sym = pmt_string_to_symbol("test"); + CPPUNIT_ASSERT(pmt_is_bool(PMT_BOOL_T)); + CPPUNIT_ASSERT(pmt_is_bool(PMT_BOOL_F)); + CPPUNIT_ASSERT(!pmt_is_bool(sym)); + CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_BOOL_F); + CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_BOOL_T); + CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_BOOL_F)); + CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_BOOL_T)); + CPPUNIT_ASSERT_THROW(pmt_to_bool(sym), pmt_wrong_type); +} + +void +qa_pmt_prims::test_integers() +{ + pmt_t p1 = pmt_from_long(1); + pmt_t m1 = pmt_from_long(-1); + CPPUNIT_ASSERT(!pmt_is_integer(PMT_BOOL_T)); + CPPUNIT_ASSERT(pmt_is_integer(p1)); + CPPUNIT_ASSERT(pmt_is_integer(m1)); + CPPUNIT_ASSERT_THROW(pmt_to_long(PMT_BOOL_T), pmt_wrong_type); + CPPUNIT_ASSERT_EQUAL(-1L, pmt_to_long(m1)); + CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(p1)); +} + +void +qa_pmt_prims::test_reals() +{ + pmt_t p1 = pmt_from_double(1); + pmt_t m1 = pmt_from_double(-1); + CPPUNIT_ASSERT(!pmt_is_real(PMT_BOOL_T)); + CPPUNIT_ASSERT(pmt_is_real(p1)); + CPPUNIT_ASSERT(pmt_is_real(m1)); + CPPUNIT_ASSERT_THROW(pmt_to_double(PMT_BOOL_T), pmt_wrong_type); + CPPUNIT_ASSERT_EQUAL(-1.0, pmt_to_double(m1)); + CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(p1)); + CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(pmt_from_long(1))); +} + +void +qa_pmt_prims::test_complexes() +{ + pmt_t p1 = pmt_make_rectangular(2, -3); + pmt_t m1 = pmt_make_rectangular(-3, 2); + CPPUNIT_ASSERT(!pmt_is_complex(PMT_BOOL_T)); + CPPUNIT_ASSERT(pmt_is_complex(p1)); + CPPUNIT_ASSERT(pmt_is_complex(m1)); + CPPUNIT_ASSERT_THROW(pmt_to_complex(PMT_BOOL_T), pmt_wrong_type); + CPPUNIT_ASSERT_EQUAL(std::complex(2, -3), pmt_to_complex(p1)); + CPPUNIT_ASSERT_EQUAL(std::complex(-3, 2), pmt_to_complex(m1)); + CPPUNIT_ASSERT_EQUAL(std::complex(1.0, 0), pmt_to_complex(pmt_from_long(1))); + CPPUNIT_ASSERT_EQUAL(std::complex(1.0, 0), pmt_to_complex(pmt_from_double(1.0))); +} + +void +qa_pmt_prims::test_pairs() +{ + CPPUNIT_ASSERT(pmt_is_null(PMT_NIL)); + CPPUNIT_ASSERT(!pmt_is_pair(PMT_NIL)); + pmt_t s1 = pmt_string_to_symbol("s1"); + pmt_t s2 = pmt_string_to_symbol("s2"); + pmt_t s3 = pmt_string_to_symbol("s3"); + + pmt_t c1 = pmt_cons(s1, PMT_NIL); + CPPUNIT_ASSERT(pmt_is_pair(c1)); + CPPUNIT_ASSERT(!pmt_is_pair(s1)); + CPPUNIT_ASSERT_EQUAL(s1, pmt_car(c1)); + CPPUNIT_ASSERT_EQUAL(PMT_NIL, pmt_cdr(c1)); + + pmt_t c3 = pmt_cons(s3, PMT_NIL); + pmt_t c2 = pmt_cons(s2, c3); + pmt_set_cdr(c1, c2); + CPPUNIT_ASSERT_EQUAL(c2, pmt_cdr(c1)); + pmt_set_car(c1, s3); + CPPUNIT_ASSERT_EQUAL(s3, pmt_car(c1)); + + CPPUNIT_ASSERT_THROW(pmt_cdr(PMT_NIL), pmt_wrong_type); + CPPUNIT_ASSERT_THROW(pmt_car(PMT_NIL), pmt_wrong_type); + CPPUNIT_ASSERT_THROW(pmt_set_car(s1, PMT_NIL), pmt_wrong_type); + CPPUNIT_ASSERT_THROW(pmt_set_cdr(s1, PMT_NIL), pmt_wrong_type); +} + +void +qa_pmt_prims::test_vectors() +{ + static const size_t N = 3; + pmt_t v1 = pmt_make_vector(N, PMT_NIL); + CPPUNIT_ASSERT_EQUAL(N, pmt_length(v1)); + pmt_t s0 = pmt_string_to_symbol("s0"); + pmt_t s1 = pmt_string_to_symbol("s1"); + pmt_t s2 = pmt_string_to_symbol("s2"); + + pmt_vector_set(v1, 0, s0); + pmt_vector_set(v1, 1, s1); + pmt_vector_set(v1, 2, s2); + + CPPUNIT_ASSERT_EQUAL(s0, pmt_vector_ref(v1, 0)); + CPPUNIT_ASSERT_EQUAL(s1, pmt_vector_ref(v1, 1)); + CPPUNIT_ASSERT_EQUAL(s2, pmt_vector_ref(v1, 2)); + + CPPUNIT_ASSERT_THROW(pmt_vector_ref(v1, N), pmt_out_of_range); + CPPUNIT_ASSERT_THROW(pmt_vector_set(v1, N, PMT_NIL), pmt_out_of_range); + + pmt_vector_fill(v1, s0); + for (size_t i = 0; i < N; i++) + CPPUNIT_ASSERT_EQUAL(s0, pmt_vector_ref(v1, i)); +} + +void +qa_pmt_prims::test_equivalence() +{ + pmt_t s0 = pmt_string_to_symbol("s0"); + pmt_t s1 = pmt_string_to_symbol("s1"); + pmt_t s2 = pmt_string_to_symbol("s2"); + pmt_t list0 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL))); + pmt_t list1 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL))); + pmt_t i0 = pmt_from_long(42); + pmt_t i1 = pmt_from_long(42); + pmt_t r0 = pmt_from_double(42); + pmt_t r1 = pmt_from_double(42); + pmt_t r2 = pmt_from_double(43); + + CPPUNIT_ASSERT(pmt_eq(s0, s0)); + CPPUNIT_ASSERT(!pmt_eq(s0, s1)); + CPPUNIT_ASSERT(pmt_eqv(s0, s0)); + CPPUNIT_ASSERT(!pmt_eqv(s0, s1)); + + CPPUNIT_ASSERT(pmt_eqv(i0, i1)); + CPPUNIT_ASSERT(pmt_eqv(r0, r1)); + CPPUNIT_ASSERT(!pmt_eqv(r0, r2)); + CPPUNIT_ASSERT(!pmt_eqv(i0, r0)); + + CPPUNIT_ASSERT(!pmt_eq(list0, list1)); + CPPUNIT_ASSERT(!pmt_eqv(list0, list1)); + CPPUNIT_ASSERT(pmt_equal(list0, list1)); + + pmt_t v0 = pmt_make_vector(3, s0); + pmt_t v1 = pmt_make_vector(3, s0); + pmt_t v2 = pmt_make_vector(4, s0); + CPPUNIT_ASSERT(!pmt_eqv(v0, v1)); + CPPUNIT_ASSERT(pmt_equal(v0, v1)); + CPPUNIT_ASSERT(!pmt_equal(v0, v2)); + + pmt_vector_set(v0, 0, list0); + pmt_vector_set(v0, 1, list0); + pmt_vector_set(v1, 0, list1); + pmt_vector_set(v1, 1, list1); + CPPUNIT_ASSERT(pmt_equal(v0, v1)); +} + +void +qa_pmt_prims::test_misc() +{ + CPPUNIT_ASSERT_THROW(pmt_length(PMT_NIL), pmt_wrong_type); + + pmt_t k0 = pmt_string_to_symbol("k0"); + pmt_t k1 = pmt_string_to_symbol("k1"); + pmt_t k2 = pmt_string_to_symbol("k2"); + pmt_t k3 = pmt_string_to_symbol("k3"); + pmt_t v0 = pmt_string_to_symbol("v0"); + pmt_t v1 = pmt_string_to_symbol("v1"); + pmt_t v2 = pmt_string_to_symbol("v2"); + pmt_t p0 = pmt_cons(k0, v0); + pmt_t p1 = pmt_cons(k1, v1); + pmt_t p2 = pmt_cons(k2, v2); + + pmt_t alist = pmt_cons(p0, pmt_cons(p1, pmt_cons(p2, PMT_NIL))); + CPPUNIT_ASSERT(pmt_eq(p1, pmt_assv(k1, alist))); + CPPUNIT_ASSERT(pmt_eq(PMT_BOOL_F, pmt_assv(k3, alist))); + + pmt_t keys = pmt_cons(k0, pmt_cons(k1, pmt_cons(k2, PMT_NIL))); + pmt_t vals = pmt_cons(v0, pmt_cons(v1, pmt_cons(v2, PMT_NIL))); + CPPUNIT_ASSERT(pmt_equal(keys, pmt_map(pmt_car, alist))); + CPPUNIT_ASSERT(pmt_equal(vals, pmt_map(pmt_cdr, alist))); +} + +void +qa_pmt_prims::test_dict() +{ + pmt_t dict = pmt_make_dict(); + CPPUNIT_ASSERT(pmt_is_dict(dict)); + + pmt_t k0 = pmt_string_to_symbol("k0"); + pmt_t k1 = pmt_string_to_symbol("k1"); + pmt_t k2 = pmt_string_to_symbol("k2"); + pmt_t k3 = pmt_string_to_symbol("k3"); + pmt_t v0 = pmt_string_to_symbol("v0"); + pmt_t v1 = pmt_string_to_symbol("v1"); + pmt_t v2 = pmt_string_to_symbol("v2"); + pmt_t v3 = pmt_string_to_symbol("v3"); + pmt_t not_found = pmt_cons(PMT_NIL, PMT_NIL); + + CPPUNIT_ASSERT(!pmt_dict_has_key(dict, k0)); + pmt_dict_set(dict, k0, v0); + CPPUNIT_ASSERT(pmt_dict_has_key(dict, k0)); + CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k0, not_found), v0)); + CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), not_found)); + pmt_dict_set(dict, k1, v1); + pmt_dict_set(dict, k2, v2); + CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), v1)); + pmt_dict_set(dict, k1, v3); + CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), v3)); + + pmt_t keys = pmt_cons(k2, pmt_cons(k1, pmt_cons(k0, PMT_NIL))); + pmt_t vals = pmt_cons(v2, pmt_cons(v3, pmt_cons(v0, PMT_NIL))); + CPPUNIT_ASSERT(pmt_equal(keys, pmt_dict_keys(dict))); + CPPUNIT_ASSERT(pmt_equal(vals, pmt_dict_values(dict))); +} diff --git a/pmt/src/lib/qa_pmt_prims.h b/pmt/src/lib/qa_pmt_prims.h new file mode 100644 index 00000000..334ee65d --- /dev/null +++ b/pmt/src/lib/qa_pmt_prims.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_QA_PMT_PRIMS_H +#define INCLUDED_QA_PMT_PRIMS_H + +#include +#include + +class qa_pmt_prims : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE(qa_pmt_prims); + CPPUNIT_TEST(test_symbols); + CPPUNIT_TEST(test_booleans); + CPPUNIT_TEST(test_integers); + CPPUNIT_TEST(test_reals); + CPPUNIT_TEST(test_complexes); + CPPUNIT_TEST(test_pairs); + CPPUNIT_TEST(test_vectors); + CPPUNIT_TEST(test_equivalence); + CPPUNIT_TEST(test_misc); + CPPUNIT_TEST(test_dict); + CPPUNIT_TEST_SUITE_END(); + + private: + void test_symbols(); + void test_booleans(); + void test_integers(); + void test_reals(); + void test_complexes(); + void test_pairs(); + void test_vectors(); + void test_equivalence(); + void test_misc(); + void test_dict(); +}; + +#endif /* INCLUDED_QA_PMT_PRIMS_H */ + diff --git a/pmt/src/lib/test_pmt.cc b/pmt/src/lib/test_pmt.cc new file mode 100644 index 00000000..41cdc633 --- /dev/null +++ b/pmt/src/lib/test_pmt.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +int +main(int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest(qa_pmt::suite ()); + + bool was_successful = runner.run("", false); + + return was_successful ? 0 : 1; +} diff --git a/usrp/AUTHORS b/usrp/AUTHORS new file mode 100644 index 00000000..bdfe42dc --- /dev/null +++ b/usrp/AUTHORS @@ -0,0 +1,4 @@ +Matt Ettus +Eric Blossom +Michael Dickens Fast USB support for OS/X +Martin Dudok van Heel Multi usrp synchronisation, 8 bit support diff --git a/usrp/ChangeLog b/usrp/ChangeLog new file mode 100644 index 00000000..e5acb6a9 --- /dev/null +++ b/usrp/ChangeLog @@ -0,0 +1,1055 @@ +2006-06-25 Eric Blossom + + * firmware/include/fpga_regs_standard.h: doc fix to reflect current reality. + +2006-06-10 Eric Blossom + + * host/apps/usrper.cc: removed dead (#if 0'd) code, that's no longer applicable. + +2006-05-11 Martin Dudok van Heel + Added synchronised multi_usrp support using a new fpga firmware build in a new toplevel usrp_multi. + A few changes were needed in the mainline code, but they shouldn't affect anyone + (No functionality changes in the existing code, just a few API additions) + + * firmware/include/fpga_regs_standard.v: added Master/slave control register FR_RX_MASTER_SLAVE + * firmware/include/fpga_regs_common.h: added 32 bit counter support bmFR_MODE_RX_COUNTING_32BIT + * firmware/include/generate_regs.py: added support for bitno and bm defines + * firmware/include/fpga_regs_standard.h: added Master/slave control register FR_RX_MASTER_SLAVE + * host/lib/usrp_basic.h: added _write_fpga_reg_masked + * host/lib/usrp_basic.cc: added _write_fpga_reg_masked + * host/lib/usrp_standard.h: added FPGA_MODE_COUNTING_32BIT + * fpga/Makefile.extra: regenerated to add new usrp_multi files + * fpga/rbf/rev4/multi_2rxhb_2tx.rbf: new (fpga firmware for synchronised multi_usrp support) + * fpga/rbf/rev4/multi_4rx_0tx.rbf: new (fpga firmware for synchronised multi_usrp support) + * fpga/rbf/Makefile.am: added commented out rev2/multi_2rxhb_2tx.rbf and rev4/multi_2rxhb_2tx.rbf + * fpga/rbf/rev2/multi_2rxhb_2tx.rbf: new (fpga firmware for synchronised multi_usrp support) + * fpga/rbf/rev2/multi_4rx_0tx.rbf: new (fpga firmware for synchronised multi_usrp support) + * fpga/toplevel/usrp_std/usrp_std.v: split rx_buffer reset into dsp reset and reset_regs + * fpga/toplevel/usrp_multi: new fpga toplevel for synchronised multi_usrp support + * fpga/toplevel/usrp_multi/usrp_multi.esf: new + * fpga/toplevel/usrp_multi/usrp_multi.vh: new toplevel verilog include, + to turn on/off multi usrp support and number of rx/tx channels and halfband + * fpga/toplevel/usrp_multi/usrp_std.vh: new wrapper for usrp_multi.vh + * fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh: new + * fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh: new + * fpga/toplevel/usrp_multi/usrp_multi.v: new toplevel verilog file for multi_usrp support. + The multi_usrp support can be turned on and off in usrp_multi.vh. + If it is turned off this file will generate exactly the same as usrp_std.v + (just do a diff between usrp_std.v and usrp_multi.v to see how this is done) + * fpga/toplevel/usrp_multi/usrp_multi.qpf: new + * fpga/toplevel/usrp_multi/usrp_multi.psf: new + * fpga/toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh: new + * fpga/toplevel/usrp_multi/usrp_multi.qsf: new + * fpga/toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh: new + * fpga/toplevel/usrp_multi/usrp_multi.csf: new + * fpga/toplevel/usrp_multi/.cvsignore: new + * fpga/sdr_lib/rx_buffer.v: split reset into dsp reset and reset registers + * fpga/sdr_lib/master_control_multi.v: new wrapper for master_control.v which adds multi_usrp support + * fpga/sdr_lib/phase_acc.v: set reset of FREQADDR register to 1'b0 + This way reset can be used to reset phase_acc without resetting the frequency + (this reset was not used untill now) + * fpga/sdr_lib/setting_reg_masked.v: new masked 16 bit register + +2006-05-01 Michael Dickens + + * host/lib/Makefile.am, host/lib/fusb_darwin.{h,cc}: mods for + higher speed OS/X support. + * host/lib/darwin_libusb.h, host/lib/mld_threads.h, + host/lib/circular_buffer.h, host/lib/circular_linked_list.h, + README_OSX: new files for higher speed OS/X support. + + +2006-03-29 Eric Blossom + + * fpga/Makefile.am: regenerated Makefile.extra so that make distcheck + passes. + * fpga/rbf/Makefile.am: simplified installation of FPGA rbf + files. It actually works again ;) + +2006-03-09 Eric Blossom + + * fpga/gen_makefile_extra.py, fpga/Makefile.am, + fpga/Makefile.extra: based on an idea by Martin, we now machine + generate the list of FPGA related files that should go into the + tarball distribution. After adding or removing fpga files from + CVS, you must run gen_makefile_extra.py to regenerate the Makefile + fragment. + +2006-03-09 Martin Dudok van Heel + + * firmware/src/usrp2/Makefile.am, usrp/rbf/Makefile.am: fixed + make distcheck failures. + +2006-03-06 Eric Blossom + + * host/lib/usrp_standard.cc (compute_freq_control_word_fpga): + Removed host-side truncation of frequency control word. + Tuning resolution is now approximately 0.03 Hz. + +2006-02-18 Eric Blossom + + * host/lib/usrp_prims.{h,cc}, host/lib/usrp_basic.{h,cc}, + host/lib/usrp_standard.{h,cc}: added support for specifying the + firmware and fpga files that is to be loaded. Also provided + default override via USRP_FPGA and USRP_FIRMWARE environment + variables. + +2006-02-17 Eric Blossom + + * host/lib/usrp_basic.{h,cc}, host/lib/usrp_prims.{h,cc}: added + methods to retrieve serial number from usrp motherboard. + * host/apps/burn-serial-number: burn a serial number into usrp motherboard. + * firmware/src/usrp2/eeprom_io.{h,c}: routines to read and write eeprom. + * firmware/src/usrp2/usrp_main.c (patch_usb_descriptors): read h/w + rev and serial number out of boot eeprom and patch into returned + usb descriptors. + + * host/apps/test_usrp0.cc, host/lib/usrp0.{h,cc}: removed usrp0 + host code. + * firmware/src/Makefile.am: removed all rev0 and rev1 usrp firmware. + +2006-02-09 Eric Blossom + + * fpga/toplevel/usrp_std/usrp_std.vh: refactored condition compilation. + * fpga/toplevel/usrp_std/usrp_std_config_2rxhb_2tx.vh: new + * fpga/toplevel/usrp_std/usrp_std_config_4rx_0tx.vh: new + + * firmware/include/fpga_regs_common.{h,v}, host/lib/usrp_basic.cc: + removed reference to FR_ATR_CTL. + * fpga/sdr_lib/rx_chain_hb.v: deleted. Capability was folded into rx_chain.v + +2006-02-01 Eric Blossom + + * host/lib/usrp_prims.cc (usrp_open_interface): reenabled + usb_set_configuration for WIN32 platform. Thanks Martin! + +2006-01-30 Eric Blossom + + * fpga/sdr_lib/master_control.v: modified code so that it appears + that atr_ctl is always asserted. This allows us to simplify the + daughterboard and applications code. They can control everything + via the other three ATR_* regs. + * fpga/rbf/usrp_fpga_rev2.rbf: updated with new binary. + + * host/lib/usrp_prims.cc (_usrp_load_fpga): manually reset fpga + regs by writing zero to them. + +2006-01-25 Eric Blossom + + * host/lib/usrp_standard.{h,cc}: new methods for reporting on FPGA + capabilities. + * firmware/include/fpga_regs_standard.h (FR_RB_CAPS): new reg that + describes FPGA capabilities. + +2005-12-15 Eric Blossom + + * fpga/Makefile.am: Added missing files to EXTRA_DIST. + +2005-12-08 Martin Dudok van Heel + + tagged RBF_2005_12_08 + + * fpga/rbf/usrp_fpga_rev2.rbf: updated. + * fpga/toplevel/usrp_std/usrp_std.v: fixed counter mode bug + related to half-band filter. + +2005-12-07 Eric Blossom + + Tagged all files: RBF_2005_12_07 + + * fpga/rbf/usrp_fpga_rev2.rbf: updated with new Auto T/R switching code. + +2005-12-06 Eric Blossom + + * host/swig/Makefile.am (prims.cc usrp_prims.py): added new dependencies. + * host/lib/usrp_basic.cc: disabled printing of daughterboard types. + +2005-12-05 Eric Blossom + + * firmware/include/fpga_regs_standard.h: renumbed + FR_TX_FORMAT and FR_RX_FORMAT to remove gap. + * firmware/include/fpga_regs_common.h: moved FR_ATR regs here from + fpga_regs_standard.h. + * host/lib/usrp_basic.cc: zero Auto T/R regs at init time. + +2005-12-01 Eric Blossom + + * host/swig/usrp_fpga_regs.py: define all fpga register names and + bit masks. This is effectively a python binding for the contents + of firmware/include/fpga_regs_{common,standard}.h + * host/swig/prims.i: swigged fpga_regs_{common,standard}.h + +2005-11-30 Eric Blossom + + * firmware/include/fpga_regs_standard.h: fixed typo in FR_ATR_* + series. Renumbered to start after the 16 registers reserved for + custom user definition. + * firmware/include/generate_regs.py (generate_fpga_regs): changed + generated register const width to 7 bits. + +2005-11-19 Martin Dudok van Heel + + * host/apps/Makefile.am: make make-dist work again by + added new burn-db-eeprom and removing burn-dbs-eeprom + and burn-tvrx-eeprom from noinst_PYTHON. + * fpga/Makefile.am: make make-dist work again by making + EXTRA_DIST consistant with latest cleanup of old files. + +2005-11-18 Eric Blossom + + * firmware/include/fpga_regs_standard.h: redefined auto + transmit/receive control registers. + +2005-11-17 Eric Blossom + + * host/lib/fusb_linux.cc (write): added code to minimize transmit + buffering. This allows the higher level code to control buffering + of USB transfers. + +2005-11-15 Eric Blossom + + * host/lib/usrp_basic.cc: zero the daughterboard i/o registers on open. + * fpga/rbf/usrp_fgpa_rev2.rbf: new RBF_2005_11_15 + +2005-11-15 Matt Ettus + + * fpga/sdr_lib/master_control.v, fpga/sdr_lib/io_pins.v: + Refactored resets to fix problem where starting Rx side was + killing Tx side. + +2005-11-13 Eric Blossom + + * host/lib/usrp_prims.cc (usrp_open_interface): removed call to usb_set_configuration. + +2005-11-02 Eric Blossom + + * host/lib/usrp_basic.h (class usrp_basic_tx): fixed pga_db_per_step. + +2005-10-31 Eric Blossom + + * host/lib/usrp_prims.cc (usrp_open_interface): ignore error on + usb_set_configuration. + +2005-10-28 Eric Blossom + + * fpga/rbf/Makefile.am (install-data-local): conditionally install + fpga .rbf files. If a file named DONT_INSTALL_RBF exists in the + install directory, the install will not be done. + +2005-10-24 Eric Blossom + + * host/lib/usrp_standard.{h,cc}: mods to use halfband decimator + in FPGA. + + * fpga/sdr_lib/hb/halfband_decim.v: added documentation. + +2005-10-20 Eric Blossom + + * host/lib/usrp_standard.{h,cc} (class usrp_standard_rx): support + setting and getting rx format (8-bit values, etc). + * host/lib/usrp_basic.cc (usrp_basic): disable FPGA DEBUG_EN in ctor. + * host/lib/gen_usrp_dbid.py, host/lib/usrp_prims.h: handle and + cases. + * host/apps/test_usrp_standard_rx.cc (main): added support for 8-bit samples. + + * fpga/sdr_lib/rx_buffer.v: fixed misspelled netname. + * fpga/toplevel/usrp_std/usrp_std.v: added additional ../ to includes. + * fpga/sdr_lib/master_control.v: put FR_DEBUG_EN back to single reg. + +2005-10-17 Eric Blossom + + * firmware/include/fpga_regs_standard.h: redefined RX_FORMAT register. + * firmware/include/fpga_regs_common.h: split FR_DEBUG_EN into a TX + and an RX register. + +2005-10-13 Eric Blossom + + * host/lib/usrp_standard.cc: initialize nchannels before interp/decim + rate. Fixed problem computing polling iterval. + * host/apps/test_usrp_standard_tx.cc (main): added -M megabytes option. + +2005-09-21 Eric Blossom + + * host/lib/usrp_basic.h: adc_freq() -> adc_rate(); dac_freq() -> + dac_rate(). Also added converter_rate() which is defined on both + Tx and Rx sides. + +2005-09-20 Eric Blossom + + * host/apps/burn-db-eeprom: new. Burns eeproms on all kinds of + daughterboards. + +2005-09-17 Eric Blossom + + * host/swig/prims.i: added interface for usrp_dbid_to_string. + +2005-09-09 Larry Doolittle + + * host/apps/test_usrp_standard_rx.cc: Added -M option to specify + how many megabytes to transfer. + +2005-09-06 Martin Dudok van Heel + + * host/lib/fusb_win32.cc: Solved missing samples bug in usb code. + (Which you could see by running test_counting.py example) + +2005-08-26 Eric Blossom + + * firmware/include/fpga_regs_standard.{h,v}: Added defs for new + FR_TX_FORMAT and FR_RX_FORMAT registers. + +2005-08-19 Eric Blossom + + * doc/Makefile.am: clean-local now uses $(RM) -fr + +2005-07-29 Martin Dvh , Stephane Fillod + + * host/lib/fusb_win32.{cc,h}: WTH made win32 fast usb buffer work + * host/lib/usrp_prims.cc: Get usrp basepath for firmware from + environment variable USRP_PATH. Needed for win32 binary installer + +2005-07-24 Stephane Fillod + + * config/usrp_fusb_tech.m4: select win32 fusb for Cygwin + +2005-07-19 Eric Blossom + + * host/apps/usrp_cal_dc_offset.cc: new. control system for + determining ADC DC offset correction. Works, but really ought to + be reimplemented in FPGA and run constantly. Part of the problem + is that the offset correction varies with temperature, pga gain, + and daughterboard. + + * firmware/src/common/build_eeprom.py (build_shell_script): added + sleep 1 after each command. + + * host/lib/usrp_standard.h (class usrp_standard_rx): new method: + set_ddc_phase. + + * host/lib/usrp_basic.{h,cc}, host/lib/usrp_standard.{h,cc}: added + fusb_block_size and fusb_nblocks args to constructors so that + application code can control "fast usb" buffer. + +2005-07-11 Eric Blossom + + * host/lib/gen_usrp_dbid.py: new. Generate usrp_dbid.h, + usrp_dbid.py and usrp_dbid.cc using usrp_dbid.dat as the input file. + * host/apps/burn-basic-eeprom, host/apps/burn-dbs-eeprom, + host/apps/burn-tvrx-eeprom: import usrp_dbid + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, host/lib/Makefile.am, host/swig/Makefile.am: mods + for x86_64, $(NO_UNDEFINED) + +2005-05-18 Eric Blossom + + * host/lib/usrp_standard.{h,cc}, host/lib/usrp_basic.{h,cc}: new + start and stop methods to kick off data xfer. (Useful for + minimizing latency). + * host/apps/test_usrp_standard_{tx,rx}.cc: modified to use new + start method. + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + * usrp.inf, usrp.iss.in: new for windows installer + +2005-05-01 Stephane Fillod + + * config/usrp_fusb_tech.m4,host/lib/Makefile.am: added win32 + fusb support. + * host/lib/fusb_sysconfig_win32.cc, host/lib/fusb_win32.{h,cc}: + new files + * host/apps/test_usrp0.cc, host/apps/test_usrp_standard_rx.cc, + host/apps/test_usrp_standard_tx.cc, host/lib/fusb.h, + host/lib/fusb_linux.cc, host/lib/fusb_sysconfig_darwin.cc, + host/lib/fusb_sysconfig_generic.cc, host/lib/fusb_sysconfig_linux.cc, + host/lib/usrp0.cc, host/lib/usrp0.h, host/lib/usrp_basic.cc, + host/lib/usrp_basic.h: do not hardcode the usb driver block_size. + * host/lib/fusb_darwin.cc, host/lib/fusb_generic.cc: typo and read + endpoint fix. + +2005-03-31 Eric Blossom + + * firmware/include/usrp_spi_defs.h,firmware/include/Makefile.am: + renamed from spi_defs.h to usrp_spi_defs.h. It's now installed. + +2005-03-26 Eric Blossom + + * host/lib/fusb_linux.cc (read): fix for x86_64 compile. + +2005-03-15 Eric Blossom + + * host/lib/usrp_basic.{h,cc}: hoisted write_aux_dac and read_aux_dac + methods out of usrp_basic and into usrp_basic_rx and usrp_basic_tx. + +2005-03-11 Eric Blossom + + * host/lib/usrp_basic.{h,cc}: new methods: set_adc_offset, + set_dac_offset, set_adc_buffer_bypass. + +2005-03-03 Eric Blossom + + * host/lib/usrp_standard.cc (set_decim_rate): added warning about rates > 128. + +2005-02-22 Eric Blossom + + * firmware/src/usrp1/spi.c (read_byte_msb): rewritten to work + around SDCC 2.4.0 bug. + +2005-02-20 Eric Blossom + + * firmware/include/usrp_ids.h (USB_PID_FSF_SSRP_reserved): added + PID for SSRP. + +2005-02-18 Eric Blossom + + * host/lib/usrp_standard.cc (set_interp_rate,set_decim_rate): added range check. + * host/lib/usrp_standard.h: doc fix. + +2005-02-16 Eric Blossom + + * host/lib/usrp_dbid.cc: new ID. + * host/lib/usrp_daughterboards.h (USRP_DBID_DBS_RX): new ID. + * host/lib/usrp_basic.{h,cc}: added read_i2c and write_i2c methods. + * host/apps/burn-dbs-eeprom: init eeprom on DBS Rx daughterboard. + +2005-02-11 Eric Blossom + + * doc/Makefile.am: fixes for distcheck. + * src/host/apps/Makefile.am: add burn-basic-eeprom to tarball. + +2005-02-10 Eric Blossom + + * configure.ac, doc/Makefile.am: build html from DocBook if + they've got xmlto installed. + +2005-02-09 Eric Blossom + + * host/lib/std_paths.h.in (std_paths): new. Use prefix to locate + fpga and firmware binaries. + + * host/lib/usrp_prims.cc (compute_hash): rewritten to use embedded + md5 code instead of calling out to program. + * host/lib/md5.{h,c}: new. imported from core-utils. + +2005-02-08 Eric Blossom + + * host/apps/usrper.cc (usage): added missing parameter. + +2005-02-06 Eric Blossom + + * configure.ac: upped rev to 0.7 for release. + * host/swig/Makefile.am: backed out dependency on libpython + * host/apps/Makefile.am, host/apps/test_fusb.cc: removed test_fusb.cc + * doc/Makefile.am: new. Generate doxygen docs. + +2005-02-05 Eric Blossom + + * fpga/Makefile.am: new. distribute verilog with tarball. + * fpga/rbf/Makefile.am: new. distribute rbf's with tarball + * host/apps/test_usrp_standard_rx.cc (main): fixed calling sequence. + +2005-02-02 Eric Blossom + + * fpga/toplevel/usrp_basic/usrp_basic.v: Removed + ch?tx_freq from list of signals passed to serial_io in order to + get it to compile. + +2005-01-28 Stephane Fillod + + * src/Makefile.am: fixes for MinGW. + +2005-01-10 Eric Blossom + + * host/lib/usrp_standard.{h,cc}: changed default strategy on mux values. + + * host/lib/usrp_basic.{h,cc}: probe d'boards and initialize + fpga adc_offset and oe regs. Add methods to control all knobs. + Includes d'board i/o pins, PGA's, query daugherboard ids. + + * host/lib/usrp_prims.{h,cc},host/lib/usrp_dbid.cc: new code to + read, parse and write d'board EEPROMs. + +2005-01-08 Eric Blossom + + * firmware/include/usrp_i2c_addr.h: doc fix on d'board EEPROM contents + +2005-01-05 Eric Blossom + + * host/lib/usrp_basic.cc (set_pga): fixed incorrect upper limit. + +2005-01-04 Eric Blossom + + * host/lib/usrp_basic.{h,cc} (class usrp_basic_rx): new methods + for controlling Rx PGA. + +2004-12-20 Eric Blossom + + * firmware/src/common/build_eeprom.py: new. builds shell script + to burn low-power code into usrp motherboard EEPROM. + +2004-12-19 Eric Blossom + + * firmware/src/usrp1/{eeprom_boot.a51,eeprom_init.c}: new. Mimimum + code that will put board in low-power state at boot time. + + * firmware/src/usrp2/Makefile.am: reorg to remove duplicate code + between rev1 and rev2. + * firmware/src/usrp2/{fpga.h,fpga_load.h,fpga_rev2.c,fpga_rev2,usrp_common.h, + usrp_globals.h,usrp_rev2_regs.h}: removed. + * firmware/src/usrp2/fpga_rev1.c: new + +2004-12-08 Eric Blossom + + * host/lib/usrp_prims.{h,cc}, host/lib/usrp_basic.cc: minor tweaks for rev2 h/w. + + * firmware/src/usrp2/.cvsignore,Makefile.am,_startup.a51,blink_leds.c, + board_specific.c,check_mdelay.c,check_udelay.c,edit-gpif,fpga.h, + fpga_load.c,fpga_load.h,fpga_rev2.c,fpga_rev2.h,gpif.c,gpif.gpf,init_gpif.c, + spi.c,spi.h,usb_descriptors.a51,usrp_common.c,usrp_common.h,usrp_globals.h, + usrp_main.c,usrp_rev2_regs.h,vectors.a51: new. copied from usrp1. + Should remerge this after we're sorted out. + +2004-11-29 Berndt Josef Wulf + + * configure.ac, config/usrp_sdcc.m4: new. check for proper version + of SDCC 8051 compiler and assembler. + * config/usrp_libusb.m4: fixed check for usb.h + +2004-11-14 Eric Blossom + + * firmware/src/usrp1/usrp_rev1_regs.h (bmMISC_OUTPUTS): removed + unused define. + (bmPORT_E_OUTPUTS): made bmPE_FPGA_CLR_STATUS an output (as it + should have been all along). + +2004-10-20 Stephane Fillod + + * configure.ac, config/Makefile.am, config/gr_pwin32.m4, + host/Makefile.am, host/apps/Makefile.am, + host/apps/time_stuff.c, host/lib/Makefile.am, + host/swig/Makefile.am: detect missing functions under Win32. + + * config/mkstemp.m4, config/onceonly.m4, + host/misc/bug_work_around_8.cc, host/misc/getopt.c, + host/misc/getopt.h, host/misc/gettimeofday.c, + host/misc/Makefile.am, host/misc/mkstemp.c, + host/misc/tempname.c, host/misc/usleep.c, + host/misc/.cvsignore: new files, replacements for win32 support + + * host/lib/usrp_prims.cc: fix libusb init on systems not as + clever as Linux (no easy shared global variable, and no + auto set_configuration). + +2004-10-20 Eric Blossom + + * firmware/src/common/Makefile.am, firmware/lib/Makefile.am, + firmware/src/common/Makefile.am, firmware/src/usrp0/Makefile.am, + firmware/src/usrp1/Makefile.am: make distcheck now works! + +2004-10-20 Stephane Fillod + + * firmware/src/common/Makefile.am, + firmware/src/common/edit-gpif, firmware/src/usrp0/Makefile.am, + firmware/src/usrp1/Makefile.am, firmware/src/usrp1/edit-gpif: + allow VPATH building. + +2004-10-18 Eric Blossom + + * fpga/sdr_lib/serial_io.v: removed dac_offset stuff. + * fpga/toplevel/usrp_basic/usrp_basic.v: removed dac_offset stuff. + Conditionalized debug output. + * host/swig/util.py: fixed import + + * fpga/toplevel/usrp_basic/usrp_basic.v,fpga/sdr_lib/serial_io.v: + modified to use 0-based naming on frequencies. + + * firmware/include/generate_all.py (generate_fpga_regs): new. + Generate fpga_regs.v from fpga_regs.h + * fpga/sdr_lib/serial_io.v: now use symbolic defines for register numbers. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 0.5cvs + +2004-10-11 Eric Blossom + + * configure.ac: bumped rev to 0.5, made release + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-09-30 Eric Blossom + + * firmware/include/usrp_i2c_addr.h: renamed from i2c_addr.h. + Now installed. + + * host/lib/usrp_basic.{h,cc}: added methods for writing/reading + aux dac/adc and eeproms. + +2004-09-29 Eric Blossom + + * host/lib/usrp_prims.{h,cc} (usrp_read_aux_adc, usrp_write_aux_dac): + Redefined the interface such that aux i/o values are 12-bit. + This buys us a bit of independence from the AD9862. + +2004-09-24 Eric Blossom + + * fpga/toplevel/usrp_basic/usrp_basic.v: subtract adc offset from + buffered input values. + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-08-19 Eric Blossom + + * host/lib/usrp_basic.{h,cc}, host/lib/usrp_standard.cc: make + verbose output conditional. + +2004-08-14 Matt Ettus + + Rx timing problem fixed! + + * fpga/sdr_lib/rx_buffer.v: revised to use extended RD assertion + timing. + +2004-08-14 Eric Blossom + + * firmware/src/usrp1/{edit-gpif,gpif.gpf}: copied for common and + modified. For the time being we've got a different gpif program + for the usrp0 and usrp1, though the usrp0 should get updated to + use the new organization. + * firmware/src/usrp1/{usrp_gpif.c,usrp_gpif_inline.h}: removed + links to common. Now generated in usrp1 from usrp1 specific gpif.c + +2004-08-06 Eric Blossom + + * host/lib/fusb_linux.cc (write): failure of submit_urb is now + propagated upward as an error. + +2004-08-04 Eric Blossom + + Rx counting and Rx/Tx digital loopback are now working, modulo the + problem at the beginning of the packet. The good news is that it + is completely reproducible, and there's no PLL being used in the FPGA. + + * host/lib/usrp_basic.{h,cc} (set_usb_data_rate,usb_data_rate): new methods. + * host/lib/usrp_standard.{h,cc}: polling rate is now + f(usb_data_rate). Moved fpga_mode into rx only, and changed + constructor to take optional mode. + * host/apps/test_usrp_standard_rx.cc (main): changes to match new + constructor. + * host/apps/test_usrp_standard_tx.cc (main): -c generates counting + sequence. + * fpga/toplevel/usrp_basic/usrp_basic.v: Fixed race. Changed + strobe_decim to strobe_interp in loopback setup. + * fpga/sdr_lib/tx_buffer.v: Removed unnecessary zero assignment. + +2004-07-31 Eric Blossom + + * host/apps/test_usrp_standard_tx.cc (main): added -l (loopback) option + * host/apps/test_usrp_standard_tx.cc (main): added -l (loopback) option + + * firmware/include/fpga_regs.h (FR_MODE): added new mode register. + * host/lib/usrp_basic.cc (usrp_basic): init to non-loopback mode + + * host/apps/test_usrp_standard_tx.cc (main): changed default + interp rate to 16 (=> 32MB/sec). + + * host/lib/usrp_bytesex.h (host_to_usrp_short): New. Conditional + byte swapping between host and usrp. + * host/app/test_usrp0.cc: added conditional byte swapping. + * host/app/test_usrp_standard_{rx,tx}.cc: added conditional byte swapping. + +2004-07-30 Eric Blossom + + * host/swig/Makefile.am: now installs usrp_prims.* directly in site-packages. + One could argue that this isn't particularly pretty, but it does + get it into the namespace where we want it. + +2004-07-29 Eric Blossom + + * host/apps/test_usrp0.cc (main): added code to set tx frequency. + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 0.4cvs + +2004-07-11 Eric Blossom + + * host/lib/usrp_basic.cc: invert TX_SYNC + + * host/lib/usrp_basic.{h,cc},usrp_standard.cc: now temporarily + disable tx and rx paths when changing interpolation or decimation + rate. Didn't fix the problem, but shouldn't hurt either. + +2004-07-07 Eric Blossom + + * firmware/src/common/_startup.a51 (__sdcc_external_startup): + Rewritten to avoid fragile kludge. Now requires that all firmware + be compiled with --no-xinit-opt. + + * firmware/src/usrp{0,1}/Makefile.am: pass in linker option to + place usb descriptors at 0xE000 absolute. This works around the + fact that the assembler and linker don't really implement the + .even directive. + * firmware/src/usrp{0,1}/usb_descriptors.a51: now place + descriptors in USBDESCSEG, which we force to 0xE000. + + * firmware/src/usrp1/board_specific.c (power_down_9862s): + Power down the 9862's when the firmware is loaded to keep from + burning up the board. Note to Analog Devices: put a power pad + on these or some other way to get the heat out of them. + + * host/lib/usrp_prims.cc (_usrp_load_fpga): Since loading the FPGA + wiggles the shared reset line with the 9862s, we now once again + power down the 9862's. + +2004-07-06 Eric Blossom + + * firmware/src/common/_startup.a51 (__sdcc_external_startup): + picked up bug fixes from 2.4.0 release, and added a fragile kludge + that ensures that our variables are all initialized properly. + + * firmware/src/usrp0/usrp_main.c, firmware/src/usrp1/usrp_main.c, + firmware/src/common/usb_common.c: removed deprecated use of + pragma NOIV. + +2004-07-05 Eric Blossom + + * host/lib/fusb_linux.cc (alloc_urb): removed + USBDEVFS_URB_QUEUE_BULK flag. + +2004-07-02 Eric Blossom + + * host/lib/usrp_basic.h: added adc_freq and dac_freq + to disambiguate the interpretation of interpolation and decimation + ratios. + +2004-07-01 Eric Blossom + + * host/swig/prims.i: renamed from usrp_prims.i Module is now + installed as usrp.prims + * host/lib/usrp_basic.cc (usrp_basic_tx, usrp_basic_rx): power + down 9862 tx or rx path in destructor. + * host/lib/usrp_standard.cc: now control coarse and fine + modulators transparently, based on user provided center freq. + * fpga/sdr_lib/gen_cordic_consts.py: new. generate magic constants for cordic. + * fpga/sdr_lib/cordic.v: `define constants. integer c00 = + wasn't being synthesized correctly by Quartus II 4.0 + +2004-05-28 Eric Blossom + + * host/lib/usrp_standard.{h,cc}: Now uses 4x interpolator and + 9862 cordic. Tx path looks great up to +/- 44 MHz! + This code still twiddles the coarse modulator manually. + +2004-05-27 Eric Blossom + + * Tagged everything with BEFORE_CLOCK_REVAMP_2004_05_27. + We're about to rework the boards, host code and the verilog to + directly feed the 64 MHz oscillator to the 9862's and the FPGA. + With any luck, life will drastically improve... + + +2004-05-25 Eric Blossom + + * host/lib/usrp_standard.{h,cc} (class usrp_standard_tx_use_nco): + new. Class that utilizes the AD9862's built-in NCO for up conversion. + There's still something slightly flaky going on. + + * host/lib/usrp_basic.cc: initialize 9862 Tx FTW + +2004-05-21 Eric Blossom + + * firmware/src/usrp1/usrp_main.c (main): work around compiler + data initialization bug. + + * firmware/src/usrp1/fpga_rev1.{h,c}: added support for {TX,RX}_RESET + +2004-05-10 Eric Blossom + + * host/lib/usrp_basic.cc (~usrp_basic_rx): turn off rx_enable. + + * firmware/src/usrp1/usrp_main.c: removed unneeded global + g_fpga_reset. + +2004-05-08 Eric Blossom + + * firmware/src/usrp1/usrp_main.c (main): enabled GSTATE output. + +2004-05-07 Eric Blossom + + * host/lib/usrp_standard.cc (make): changed constructors and make + to pass the interp/decim rate. This ensures that the rate is set + to something the user wants when the rx and tx paths are first + enabled. + + * host/lib/usrp_basic.cc (initialize): enabled xrun status polling. + (set_fpga_rx_sample_rate_divisor,set_fpga_rx_sample_rate_divisor): + set FPGA register to N-1. + + * host/lib/usrp_standard.cc (set_interp_rate, set_decim_rate): now + set FPGA register to N-1. + +2004-04-18 Eric Blossom + + * firmware/src/usrp1/spi.c (spi_read, spi_write): removed extra + clocks. FPGA is now doing the right thing. + + * host/lib/ad9862.h: new. register defs for AD962 codec. + + * firmware/src/usrp1/spi.c (spi_write,spi_read): clock once w/o + enables for the FPGA's benefit. We're also clocking one extra + cycle at the end with enables again for the FPGA. I think we + should remove the extra clocking at the end. + +2004-04-17 Eric Blossom + + * host/lib/usrp_prims.{h,cc} (usrp_read_aux_adc,usrp_write_aux_dac): new. + * host/lib/usrp_prims.{h,cc} (usrp_eeprom_write,usrp_eeprom_read): new. + +2004-04-16 Eric Blossom + + * firmware/include/i2c_addr.h: new. I2C addresses. + +2004-04-12 Eric Blossom + + * host/apps/test_usrp0.cc: renamed from test_usrp.cc + * firmware/include/fpga_regs.h: corrected to match latest control_bus.v + +2004-04-11 Eric Blossom + + * host/lib/usrp0.{h,cc}: new. copies of original usrp.{h,cc} + * host/lib/usrp_basic.{h,cc}: new. reflect rev1 hardware. + +2004-04-10 Eric Blossom + + * host/swig/usrp_prims.i: new. SWIG'd usrp_prims. + * host/lib/usrp_prims.cc: added usrp_rescan; dispatch on hardware revision + when appropriate; added usrp_read_fpga_reg + * firmware/src/usrp1/fpga_rev1.h: added declarations + * firmware/src/usrp1/fpga_rev.c: added implementations for + fpga_write_reg, fpga_set_reset, fpga_set_tx_enable, fpga_set_rx_enable. + * firmware/include/fpga_regs0.h: renamed prev fpga_regs.h to fpga_regs0.h + * firmware/include/fpga_regs.h: new for usrp rev1. Needs checking + against verilog. + + +2004-03-01 Eric Blossom + + * host/lib/rate_to_regval.h: new. mapping table. + * host/lib/usrp.cc (map_rate_to_regval): now support all 97 legal + values. + +2004-01-11 Eric Blossom + + * configure.ac: configure fast usb technique as f(os) + * config/usrp_fusb_tech.m4: new autoconf macro + * host/lib/fusb.{h,cc}: refactored in to abstract class + * host/lib/fusb_{darwin,generic,linux}.{h,cc}: new concrete classes + * host/lib/fusb_sysconfig_{darwin,generic,linux}.cc: new + + * config/usrp_libusb.m4: new. check for libusb. + * configure.ac: check for libusb + + * firmware/src/Makefile.am: fixed dependencies + * firmware/src/fpga.{h,c}, firmware/src/usrp_main.c: cleanup to + make board with no FPGA usable again. + * firmware/include/usrp_config.h: doc fix. + +2003-12-30 Eric Blossom + + * host/lib/fusb.cc (alloc_urb): fixes for linux 2.5/2.6 + +2003-12-12 Eric Blossom + + * firmware/lib/i2c.c (i2c_read): worked around sdcc compiler bug. + +2003-12-07 Eric Blossom + + * configure.ac: autoconfiscated the firmware directory. It now + builds from the top along with the host code. + + * I've touched just about every file in the tree, both + firmware and host side. The combo is now working well. It is + capable of half duplex reading or writing at 31.25 MB/sec and + (pseudo) full duplex reading and writing at 15.625 MS/sec in each + direction. + + In addition, the receive side is decoupled from the transmit side + so that separate processes can open each side. + + +2003-11-27 Eric Blossom + + * firmware/src/fpga.c (clock_out_config_byte): assembly speedup + for loading fpga. + + basic support for interrupts is now working. + + * firmware/lib/{isr.c,timer.c}: new + * firmware/include/{isr.h,timer.h}: new + * firmware/src/command_loop.c (isr_tick): blink led + +2003-11-21 Eric Blossom + + * firmware/src/edit-gpif (edit_gpif): now leave xdata alone + * firmware/src/init_gpif.c: added xdata storage qualifer + * firmware/Makefile: added linker opts to get xdata located properly + + Rearranged the firmware directory. + firmware/basic_fw/include --> firmware/include + firmware/basic_fw/src --> firmware/src + All older firmware stuff was removed + +2003-11-15 Eric Blossom + + * host/lib/fusb.cc (fusb_devhandle, _cancel_pending_rqsts): now + use reverse_iterator to cancel pending requests from the back to + the front. This removes the mystery of more than one cancelled + urb having a non-zero transfer count. + + * host/lib/test_fusb.cc (test_output): fixed defective test case + that was having me think the tx code wasn't working. + +2003-11-13 Eric Blossom + + * host/lib/fusb.{h,cc}: work in progress on the Rx path. + +2003-11-11 Eric Blossom + + * host/lib/fusb.{h,cc}: halved net Tx memory requirement by using + a single user mode buffer. + +2003-11-10 Eric Blossom + + System is now sustaining 31MB/sec on the TX path, no underruns ;-) + + * firmware/basic_fw/src/edit-gpif: now machine generate inline + definitions for setup_flowstate_common, setup_flowstate_read and + setup_flowstate_write. + + * firmware/basic_fw/src/usrp_common.c: clear_usrp_error now clears + over and underrun flags from status word. + * firmware/basic_fw/src/usrp_comands.c: added bit defs for overrun + and underrun status indicators. + * firmware/basic_fw/src/command_loop.c (poll_gpif): now checks for + over and underruns and clears fpga status. + + * firmware/basic_fw/include/usrp_regs.h (bmFCB_CLR_STATUS): moved + FPGA clear_status line to the previous location of SDO. This + means that firmware from here out will only work with the latest + FPGA bitstreams that have this pin configurd as an input. + + * host/lib/fusb.{h,cc}: fast streaming usb library built on top of libusb. + This version uses linux specific magic. + + * host/lib/test_fusb.cc: test and benchmarking code for fusb. + +2003-11-08 Eric Blossom + + * firmware/basic_fw/src/gpif.gpf: moved BOGUS ctl line to CTL5. + Added clear_status as CTL3. + * firmware/basic_fw/src/usrp_common.c (init_usrp): removed + obsolete ENABLE_FIFO ifdef. Disabled RX pump priming. + * firmware/basic_fw/src/command_loop.c (main): enable both RX and TX. + +2003-10-22 Eric Blossom + + * host/lib/Usrp.{h,cc}: added accessors for get_rx_freq, get_tx_freq + +2003-10-17 Eric Blossom + + * host/usrper/test_input.cc (main): new program to exercise USRP + input path. + + * host/lib/Usrp.{h,cc} (read): changed return value from bool to int + +2003-09-30 Eric Blossom + + * host/lib/Usrp.{h,cc}: handle new format interp and decim regs. + * firmware/basic_fw/src/command_loop.c (g_enable_read): disabled + read for the time being. + +2003-09-17 Eric Blossom + + * host/lib/Usrp.cc (find_file): changed load path for firmware and + fpga bits to to /usr/local/share/usrp. + (Usrp): now set gstate, sleep, fpga_reset and tx_enable per Matt's + script. + +2003-09-16 Eric Blossom + + * AUTHORS, NEWS, README: new & empty + * bootstrap, configure.ac, Makefile.am: new for autoconfiscation + * host/Makefile.am, host/lib/Makefile.am, host/usrper/Makefile.am: new + * host/lib/{Makefile.am,Usrp.{h,cc}}: new class to interface to USRP. + * host/usrper/usrper2.cc: new code to exercise Usrp.{h,cc} + + * host/usrper/usrper.cc: removed uneeded includes + +2003-09-04 Eric Blossom + + * firmware/basic_fw/src/usrp_commands.h, + firmware/basic_fw/src/command_loop.c (do_set_sleep_bits), + host/usrper/usrper.cc (usrp_set_sleep_bits): added command to slam + the A/D and D/A sleep control lines. + + +2003-08-30 Eric Blossom + + * firmware/basic_fw/src/usrp_commands.h: removed obsolete + foo_CLR_bar commands. Added UCMD_SET_GSTATE_OUTPUT_ENABLE to + enable the output of the GPIF state on the low 3 bits of Port E. + + * host/usrper/usrper.cc (usrper_load_firmware): now implements + "load_firmware" command. + +2003-08-17 Eric Blossom + + * host/usrper/usrper.cc (usrper_load_fpga), + firmware/basic_fw/src/fpga.c: changed load_fpga to expect a byte + count, not a bit count in the xfer packet. + + * firmware/basic_fw/src/fpga.c (do_fpga_config_start): cleanup, + add appropriate delay. + + * firmware/basic_fw/src/usrp_common.c (udelay1, udelay): new delay functions + +2003-07-30 Eric Blossom + + * firmware/basic_fw/include/fx2regs.h: changed sfr and sbit syntax + to match what SDCC expects. Now the SFR's are really allocated + where they are supposed to be ;-) + +# +# Copyright 2003,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/usrp/Makefile.am b/usrp/Makefile.am new file mode 100644 index 00000000..cd908c86 --- /dev/null +++ b/usrp/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = usrp.pc.in usrp.iss.in usrp.inf + +SUBDIRS = host firmware fpga doc + diff --git a/usrp/README b/usrp/README new file mode 100644 index 00000000..63ff4a24 --- /dev/null +++ b/usrp/README @@ -0,0 +1,37 @@ +# +# README -- the short version +# + +The top level makefile handles the host code and FX2 firmware. + +Besides the normal gcc suite and all the auto tools, you'll need +the SDCC free C compiler to build the firmware. You MUST +USE VERSION 2.4.0 or VERSION 2.5.0 due to some problems with variable +initialization. http://sdcc.sourceforge.net + + +# To get started... + +./bootstrap # if you're building from CVS + +./configure +make && make check && make install + + +The high level interface to the USRP using our standard FPGA bitstram +is contained in usrp/host/lib/usrp_standard.h + +If you've got doxygen installed, there are html docs in +usrp/doc/html/index.html + + +# Compiling the verilog (not required unless you're modifying it) + +If you want to build the FPGA .rbf file from source (not required; we +provide pre-compiled .rbf files in usrp/fpga/rbf directory), you'll +need Altera's no cost Quartus II development tools. We're currently +building with Quartus II 5.1sp1 Web Edition. The project file is +usrp/fpga/toplevel/usrp_std/usrp_std.qpf. The toplevel verilog file +is usrp/fpga/toplevel/usrp_std/usrp_std.v. The bulk of the verilog +modules are contained in usrp/fpga/sdr_lib + diff --git a/usrp/doc/Doxyfile.in b/usrp/doc/Doxyfile.in new file mode 100644 index 00000000..e0533e59 --- /dev/null +++ b/usrp/doc/Doxyfile.in @@ -0,0 +1,1167 @@ +# +# Copyright 2001,2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# Doxyfile 1.3.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Universal Software Radio Peripheral" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 2 levels of 10 sub-directories under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise +# cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/host \ + @top_srcdir@/doc/other + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h \ + *.cc \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = CVS \ + @top_srcdir@/host/swig + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = moc_*.cc + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = @HAVE_DOT@ + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/usrp/doc/Makefile.am b/usrp/doc/Makefile.am new file mode 100644 index 00000000..563fa92f --- /dev/null +++ b/usrp/doc/Makefile.am @@ -0,0 +1,79 @@ +# +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + + +SUBDIRS = other + +man3dir = $(mandir)/man3 +docdir = $(prefix)/share/doc/@PACKAGE@-@VERSION@ + +EXTRA_DIST = \ + Doxyfile.in \ + ddc.eps \ + ddc.png \ + usrp-block-diagram.eps \ + usrp-block-diagram.png \ + usrp.jpg \ + usrp_guide.xml + +if HAS_XMLTO +DOCBOOK_HTML_FILES=usrp_guide.html +all-local: dox docbook-html +else +DOCBOOK_HTML_FILES= +all-local: dox +endif + +dox: html/index.html +html/index.html: + mkdir -p html + @DOXYGEN@ + +docbook-html: usrp_guide.html + +usrp_guide.html: usrp_guide.xml + xmlto html-nochunks $< + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(docdir) + @for i in $(top_srcdir)/usrp/README $(top_srcdir)/usrp/ChangeLog; do \ + echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(docdir); \ + done + + mkdir -p $(DESTDIR)$(docdir)/html + @for i in $(DOCBOOK_HTML_FILES); do \ + echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)/html"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(docdir)/html; \ + done + cp -r html $(DESTDIR)$(docdir) + +uninstall-local: + @for i in README ChangeLog; do \ + echo "$(RM) $(DESTDIR)$(docdir)/$$i;"; \ + $(RM) $(DESTDIR)$(docdir)/$$i; \ + done + $(RM) -fr $(DESTDIR)$(docdir)/html + +clean-local: + $(RM) -fr latex html man xml $(DOCBOOK_HTML_FILES) diff --git a/usrp/doc/ddc.eps b/usrp/doc/ddc.eps new file mode 100644 index 00000000..8931a16a --- /dev/null +++ b/usrp/doc/ddc.eps @@ -0,0 +1,3105 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000010008000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000300FE001800C100000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000701CF001800C300000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000F03830018000300000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000003F03000018000300000000000 +%00000000000000001F800000000000031800000000000000000000000000780000000000000000 +%000000000000000000000000000000000000000000F00019C03000000000000000000000000000 +%0000000007303000019E0CFC0000000000 +%00000000000000007FE00000000000031800000000000000C00000000000F80000000000000000 +%000000000000000000000000000000000000000001E00019C03000000000000000000000000000 +%000000000030638001FF0C7C0000000000 +%000000000000000060700000000000030000000000000000C00000000000C00000000000000000 +%000000000000000000000000000000000000000003000019E03000000000000000000000000000 +%0000000000307FE001C38C300000000000 +%0000000000000000E0380000000000030000000000000000C00000000000C00000000000000000 +%000000000000000000000000000000000000000003000031F03000000000000000000000000000 +%000000000030787001C18C300000000000 +%0000000000000000E0000C04202002030842002100110181F01000000001F02000000000000000 +%000000000000000000000000000000000000000007C08031B03000000000000000000000000000 +%000000000030703001818C300000000000 +%0000000000000000E0007F86FDF87FC3187FC0FF803F8FF1F8FE001FFC03F9FC00000000000000 +%00000000000000000000000000000000000000000FE7F031B83000000000000000000000000000 +%0000000000307033F181CC300000000000 +%00000000000000007C00E3879FBC78C31879C1CF803F9C70E1C7001FFC00C38E00000000000000 +%0000000000000000000000000000000000000000030E38219C3000000000000000000000000000 +%0000000000307033F981CC300000000000 +%00000000000000003FC0C1C70E0C70631860E30780381838C38300000000C30600000000000000 +%0000000000000000000000000000000000000000030C18618C3000000000000000000000000000 +%00000000003070300181CC300000000000 +%000000000000000007E000C60E0C60631860630380380038C30180000000C30000000000000000 +%0000000000000000000000000000000000000000030C00618E3000000000000000000000000000 +%000000000030303001818C300000000000 +%000000000000000000F001C60E0C60731860670380380038C30380000000C3C000000000000000 +%0000000000000000000000000000000000000000030F804187300001B6DBFFFB6DB00000000000 +%000000000030303001C18C300000000000 +%000000000000000000383FC60E0C60331860670380380FF8C3FF801FFC00C1FC00000000000000 +%00000000000000000000000000000000000000000307F041833000000000000000000000000000 +%0000000000301C6001E30C300000000000 +%0000000000000001C018F8C60E0C60731860670380381E38C300001FFC00C03E00000000000000 +%00000000000000000000000000000000000000000300F8C183B000000000000000000000000000 +%0000000000300FC001FF0C3C0000000000 +%0000000000000001C019C0C60E0C60731860670380383838C30000000000C00700000000000000 +%000000000000000000000000000000000000000003001CC181F000000000000000000000000000 +%0000000000300780019C0C1C0000000000 +%0000000000000000E039C1C60E0C70631860630380383038C30180000000C30700000000000000 +%0000000000000000000000000000000000000000030C0C8180F000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000F071C1C60E0C70E31860638780383078E38380000000C30600000000000000 +%0000000000000000000000000000000000000000030C1D8180F000000000000000080000000000 +%0000000000000000000000000000000000 +%00000000000000007FE0E7C60E0C7FC3186061FF80381CF8F9FF00000000C3DE00000000000000 +%00000000000000000000000000000000000000000307F981807000000000000000040000000000 +%0000000000000000000000000000000000 +%00000000000000001FC07CC60E0C7F83186060FB80380F98787C00000000C0FC00000000000000 +%00000000000000000000000000000000000000000303F181803000000000000000020000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000000300000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000030300000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000038700000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000006000000001FE00000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000007800000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000008000000000 +%0008000000000000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000004000000000 +%000C000180000060000018000000001000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000004000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%03DC1F87E1F001F87E0019E01F00F87E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000001000000000 +%0FFC7FC7C7FC00F0FF001FF83FC3FC7C00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%1C3C60C38E0C0061C3801C1870E30E3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000001000000000 +%181C60E38C0C006181801C1CE063043000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000800000000 +%181C00E3800C006300C0181CC033803000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%381C0FE381FC006300C0181CC033F03000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000400000000 +%380C7FE387FC006300C0181CC030FC3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%181C60E38E0C006300C0181CC0300E3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%181CC0E38C0C006381C0181CC072063000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%1C1CC0E38C1C00618180181C6067063800 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0E3CE1E38E3C0071C380181C70E38E3800 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000100000000 +%07FC7F61E7EC0078FF00181C3FC1FC1E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000100000000 +%01881C60E3C600383C0018080F00F00E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000080000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000080000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000040000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000040000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000020000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000020000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C01803C03FC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C0180FF03FF00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C0181E7C38F80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000C018301C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000008000000 +%000000000000000C018300C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000004000000 +%00000603307E000C0183000301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000070330FF800C0183C0030180000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000002000000 +%0000030631C1800C0181FC030380000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000002000000 +%000003063181800C01807F03FF00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000001863001800C018007C3FF80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000001000000 +%0000018C303F800C018001C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000018C30FD800C018000E300C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000800000 +%000000DC31C1800C018600E300E0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000800000 +%000000D83181800E038700E300E0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000F83183800E038380C300C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000400000 +%0000007031C78007FF03FF83FFC0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000007030FD8003FE00FF03FF80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000203070800070003C03FC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000200000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000100000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000040000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000020000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000010000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000010000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000004000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000004000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000002600 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000003E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000003FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000001FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000020000000000000000000000000000000000000000000010000000FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000007E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000003E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000001E00 +%0000000000000000000000000000000000 +%000007000000000004003C00000000000000000000000000000000000F00000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000001E00 +%0000000000000000000000000000000000 +%00000700000000000C007C00000000000000000000000000000000007FE0000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000E00 +%0000000000000000000000000000000000 +%00000700000000000C00600000000000000000000000000000000007FFFE000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000600 +%0000000000000000000000000000000000 +%00000700000000000C0060000000000000000000000000000000001F801F800000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000200 +%0000000000000000000000000000000000 +%00000719E06F03033F01FCDC1E06787800000000000000000000007C0003E00000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071FF87FC3031F01F8FC7F87FDFC0000000000000000000000F80001F00000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071E1870E3030C0060E0E1C78F0C0000000000000000000001C00000380000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C1C6063030C0060C0C0E7060E00000000000000000000038000001C0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C0C6063030C0060C18067060E00000000000000000000078000000E0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E000000000000000000000CC000001B0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000018600000318000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000018300000618000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063070C0060C1C067060E0000000000000000000030180000C0C000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C60E3070C0060C0C0C7060E00000000000000000000300C000180C000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C71C38F0C0060C0E1C7060E0000000000000000000060060003006000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C7F81FB0F0060C07F87060E0000000000000000000040030006002000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000006180C6700F3070060C01E07060600000000000000000000C001800C003000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000000C000C01C003000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000001C0006038003800000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000601C0003070003800000000000000 +%000000000000000000700200000000000000000000000000000000000000000000100000000000 +%0000000060000001800000000000000000 +%00000000006000000000000000000000000000000000000007E1800018E0001800000000000000 +%0000000000000000007F0200000000000000000000000000000000000000000000100000000000 +%000000007E000001800000000000000000 +%00000000000000000000000000000000000000000000000007FD80000DC0001800000000000000 +%0000000000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC00001800000000000000000 +%00000000000000000000000000000000000000000000000007FF80000780001800000000000000 +%0000000000000000007FFA00000003FF0000000060000000000300000000000000100000000000 +%000000007FF00001800000000000000000 +%0000000000000000000000000000000000000000000000000FFF80000700001C00000000000000 +%0000000000000000007FFA00000003FF800000006000000000C300000000000000100000000000 +%00000000FFF00001800000000000000000 +%00000000000000000000000000000000000000000000000007FD80000780001800000000000000 +%0000000000000000007FC20000000301C00000000000000000C000000000000000100000000000 +%000000007FC00001800000000000000000 +%00000000000000000000000000000000000000000000000007F180000DC0001800000000000000 +%0000000000000000007F020000000300E00000000000000000C000000000000000100000000000 +%000000007E000001800000000000000000 +%00000000000001007F0000200000000000000000000000000601800018E0001800000000000000 +%00000000000000000070020000000300601800404210100301E200400420000000100000000000 +%0000000060000001800000000000000000 +%00000000000003807FF003FC0000000000000000000000000001C0003070003800000000000000 +%00000000000000000000020000000300707F03F8637EFC1FE3F31BF03F60000000100000000000 +%0000000000000001800000000000000000 +%00000000000007807FF807FF0000000000000000000000000001C0006038003800000000000000 +%0000000000000000000002000000030030E7871C63CFDE1CF0C31F3879E0000000100000000000 +%0000000000000001800000000000000000 +%00000000000006C0601C0E070000000000000000000000000000C000C018003000000000000000 +%000000000000000000000200000003003181860C6387063030C31C1C60E0000000100000000000 +%0000000000000000000000000000000000 +%00000000000006C0600C1C038000000000000000000000000000C001800C003000000000000000 +%000000000000000000000200000003003181CC006307060030C31C1CE060000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600E18018000000000000000000000000000C0030006003000000000000000 +%000000000000000000000200000003003381CC006303060070C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C6060063800000000000000000000000000000040060003002000000000000000 +%0000000000000000000002000000030033FFCC006303060FF0C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%0000000000001C70600638000000000000000000000000000000600C0001806000000000000000 +%0000000000000000000002000000030073800C006303063E30C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%000000000000183060063800000000000000000000000000000020180000C04000000000000000 +%0000000000000000000002000000030063800C006303063030C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%00000000000018306006380000000000000000000000000000003070000060C000000000000000 +%00000000000000000000020000000300E1818E0E6303063030C3181C60E0000000100000000000 +%0000000000000000000000000000000000 +%000000000000383860063800000000000000000000000000000038E0000031C000000000000000 +%00000000000000000000020000000301C1C1860C6303063070C3181C60E0000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF86006180000000000000000000000000000001CC000001B8000000000000000 +%000000000000000000000200000003FFC0FF87BC63030639F0F3181C3FE0000000100000000000 +%0000000000000000000000000000000000 +%000000000000301C600E180180000000000000000000000000000F8000000F0000000000000000 +%000000000000000000000200000003FF007E01F06303061FB873181C1F60000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C600C1C038000000000000000000000000000070000000E0000000000000000 +%000000000000000000000200000000000000000000000000000000000060000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C601C0E038000000000000000000000000000038000001C0000000000000000 +%000000000000000000000200000000000000000000000000000000004060000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E6078078F000000000000000000000000000001E00000780000000000000000 +%0000000000000000000002000000000000000000000000000000000061C0000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FF003FE000000000000000000000000000000F80001F00000000000000000 +%000000000000000000000200000000000000000000000000000000003F80000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FC000F00000000000000000000000000000003E0007C00000000000000000 +%000000000000000000000200000000000000000000000000000000000F00000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000007F07E000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000003FFFC000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000007FE0000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C000000000007FE0000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C000000000007FF8000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C00000000000701C000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C00000000000701C000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C000E040C080700C0700E00C0000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C003F860C180700C3FC3F83F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000001F00000000000000000000 +%00000000000000000000020000000000C0071C61E180700C71E31C738000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000001F80000000000000000000 +%00000000000000000000020000000000C00E0E61E180701C60660C61C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003F80000000000000000000 +%00000000000000000000020000000000C00C0631E3007FF8006700600000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003FC0000000000000000000 +%00000000000000000000020000000000C00C0731B3007FF000E3C0780000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C0733330070003FE1F83F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C071B360070007C607C07C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C061B3600700060600E01C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C061E1E007000E0E606C0C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00E0E1E1E007000E0E70E60C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000FFC7FC0E1C00700077E3FC7F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000FFC1F00E1C0070003E61F83F0000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%C00000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007000000000000003C0000000000000000000000000000000000040000000000000000001F +%FC0000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C007C000000000000000000000000000000000004000000000000000001FC +%7FC000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C0060000000000000000000000000000000000004000000000000000007E0 +%07E000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C006000000000000000000000000000000000000400000000000000001F00 +%00F80000000000000000020000000000000000FFE3180000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000718E04703021F01F89C1E0238700000000000000000000000000400000000000000007800 +%001C0000000000000000020000000000000000FFE3186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071BF07F83033F01FCFC7F87FCFC000000000000000000000000040000000000000000E000 +%000E0000000000000000020000000000000000C000186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071F3879C3030C0060FCF1C7CF9C000000000000000000000000040000000000000000E000 +%00070000000000000000020000000000000000C000186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C1C70E3030C0060C0C0C7070E000000000000000000000000040000000000000001E000 +%00038000000000000000020000000000000000C00318F81C046000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C0C6063030C0060C1C067060E0000000000000000000000000400000000000000033000 +%0007C000000000000000020000000000000000C00318FC7F07F000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000061800 +%000CE000000000000000020000000000000000C0031870E387E000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000061C00 +%00187000000000000000020000000000000000FFC3186181870000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000040E00 +%00307000000000000000020000000000000000FFC3186180C60000000000000000100000000000 +%0000000000000007C00000000000000000 +%000007180C6063030C0060C18067060E00000000000000000000000004000000000000000C0700 +%00603800000000000000020000000000000000C0031861FFC60000000000000000100000000000 +%000000000000001FF00000000000000000 +%000007180C6063070C0060C0C0E7060E0000000000000000000000000400000000000000180380 +%00C03800000000000000020000000000000000C0031861FFC60000000000000000100000000000 +%00000000000000383C0000000000000000 +%000007180C70C3070C0060C0E1C7060E00000000000000000000000004000000000000001801C0 +%01801800000000000000020000000000000000C003186180060000000000000000100000000000 +%00000000000000701C0000000000000000 +%000007180C7FC3FF0F0060C07F87060E00000000000000000000000004000000000000003000E0 +%03001C00000000000000020000000000000000C003186180060000000000000000100000000000 +%00000000000000E00E0000000000000000 +%000007180C6F00F3070060C03F07060E0000000000000000000000000400000000000000300060 +%06000C00000000000000020000000000000000C003186180C60000000000000000100000000000 +%00000000000000C0060000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000000300030 +%0C000C00000000000000020000000000000000C0031871C1860000000000000000100000000000 +%00000000000001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000C00300018 +%18000400000000000070020000000000000000C003187CFF860000000000000000100000000000 +%00000000600001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FE060000E +%3000060000000000007F020000000000000000C003183C3E060000000000000000100000000000 +%000000007E0001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FF8600006 +%6000060000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FFF600003 +%C000060000000000007FFA00000000000000000000000000000000000000000000100000000000 +%00000000FFF001C0070000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FFE600001 +%C000060000000000007FFA00000000000000000000000000000000000000000000100000000000 +%00000000FFF000C0060000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FF8600003 +%C000060000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC000C0060000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FE0600006 +%6000060000000000007F0200000000000000000000000000000000000000000000100000000000 +%000000007E000060EC0000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000C0060000C +%380006000000000000700200000000000000000000000000000000000000000000100000000000 +%00000000600000707C0000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000700018 +%180006000000000000000200000000000000000000000000000000000000000000100000000000 +%000000000000003FFC0000000000000000 +%00000000000003807FE001FC000000000000000000000000000000000400000000000000300030 +%0C000C000000000000000200000000000000000000000000000000000000000000100000000000 +%000000000000000FEE0000000000000000 +%00000000000003807FF807FE000000000000000000000000000000000400000000000000300070 +%07000C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000030000000000000000 +%00000000000006C0603C0E070000000000000000000000000000000004000000000000003000E0 +%03000C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000006C0600C0C038000000000000000000000000000000004000000000000003001C0 +%01801C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000EE0600E1801800000000000000000000000000000000400000000000000180380 +%00E018000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600E1800000000000000000000000000000000000400000000000000180700 +%007038000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600638000000000000000000000000000000000004000000000000000C0E00 +%003838000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000001C70600638000000000000000000000000000000000004000000000000000C1C00 +%001C70000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000183060063800000000000000000000000000000000000400000000000000061800 +%000E70000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000183860063800000000000000000000000000000000000400000000000000033000 +%0007E0000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF86006380000000000000000000000000000000000040000000000000001A000 +%000380000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF8600E180180000000000000000000000000000000040000000000000000C000 +%000300000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000701C600E1C0180000000000000000000000000000000040000000000000000E000 +%000700000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C601C0C03800000000000000000000000000000000400000000000000007C00 +%003E00000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E603C0F07000000000000000000000000000000000400000000000000003E00 +%00FC00000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E7FF807FE000000000000000000000000000000000400000000000000000F80 +%01F000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FE001F80000000000000000000000000000000004000000000000000003FC +%3F8000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000004000000000000000000FF +%FF0000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000001F +%F80000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000001 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%0000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000007 +%00000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000007 +%80000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%80000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%80000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000001F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000007F800000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000C00000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000C00000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000800000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007E0C6FC00400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000E70C7FE00400000000000000000000 +%0007807807C0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C38C70600400000000000000000000 +%001FC1FE0FE0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C00C60600400000000000000000000 +%003863871870000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000F00C60600400000000000000000000 +%003033039830000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007E0C60600400000000000000000000 +%007007019800000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000001F8C60600400000000000000000000 +%006007019F80000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000038C60600400000000000000000000 +%0060060187E0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000818C60600400000000000000000000 +%0060070180F0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C18C60600400000000000000000000 +%007037018038000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000E38C60600400000000000000000000 +%003033039838000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007F0C60600400000000000000000000 +%003863871830000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%001FE1FE0FF0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%0007807C07C0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001803003E000F800000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001C0300FF803FE00000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001E0303C1C070780000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001E030300C0E0380000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001F030700E1C01C0000 +%00000000000000004000000000000001FF00000000006000018006086000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001B83060001800C0000 +%00000000000000004000000000000001FFC0000000006000018006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000019C30E0003800E0000 +%0000000000000000400000000000000180C0000000006000000006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000019C30E0003800E0000 +%0000000000000000400000000000000180E0000000006000000006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018E30C0003800E0000 +%0000000000000000400000000000000180603C08E00E66060D80C67E6700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018630E0003800E0000 +%000000000000000040000000000000018060FF1FF83FE30E0D83F67E6FC0000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018330E0003800E0000 +%0000000000000000400000000000000180C1C71F3871E30E0D871E1878E0000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000183B060061800C0000 +%00000000000000004000000000000001FF83831C1C60E30F198E0E187060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000181B060061800C0000 +%00000000000000004000000000000001FF80031C0CE0630B198C0E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000181F0700E0C01C0000 +%0000000000000000400000000000000181E0071C0CE0619B198C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180F0381C0E0380000 +%000000000000000040000000000000018060FF1C0CC0619B318C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180701FF807FF00000 +%000000000000000040000000000000018071E31C0CC06199B18C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180700FF001FC00000 +%000000000000000040000000000000018073831C0CE060F1B18C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000018073031C0C6060F1E18E0E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000180E3071C0C70E0F0E1861E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000001FFC1FF9C0C3FE070E187FE1E6060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000001FF80F99C0C0F6060E181E60E6060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000003E0300000000006000FC00000003 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000FF830000000000C003FF00000003 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001C1C00000000000C0070780000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380E00000000000C00E0180000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380400000000000800C01C0000000 +%000000000000000040000000000000000C000000180000000010C0000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380031BF81F8001801C0001FC1FC3 +%1BF03F800000000040000000000000000C000000180000000030C0000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001F0031F3839C001801800039E38E3 +%1F3879C00000000040000000000000000C00000000000000003000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000FE031C1C60600100180007073063 +%1C1860E00000000040000000000000000C00000000000000003000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000001FC31C0C60700300180006033003 +%1C1CC060000000004000000000000001CC07001C18CF0E01F07CC07819E0000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000003C31C0CE070030018000E033C03 +%181CE060000000004000000000000007EC1FC07F18FFBF83FC7CC0FE1BF0000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000E31C0CFFF0030018000E031FC3 +%181CFFE000000000400000000000000E3C38E0E398F1F3861C30C1C71E38000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000300631C0CE00006001C00CE0303E3 +%181CC00000000000400000000000000C1C6070C198E0C18E0C30C3839C18000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000300631C0CE00006000C01CE030073 +%181CC0000000000040000000000000180C60318018E0C1800C30C3019818000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380631C0C606006000E0186073073 +%181CE0600000000040000000000000180C7FF18018C0C1803C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000003C0C31C0C70600400070387063073 +%181C70E00000000040000000000000180C7FF18018C0C183FC30C701981C000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001FFC31C0C3DE00C0003FF03DE3DE3 +%181C3BC00000000040000000000000180C60018018C0C1878C30C701981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000007F031C0C1F800C0001FC01F80FC3 +%181C1F800000000040000000000000180C60018098C0C18C0C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000C1C7031C1D8C0C18C0C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000E1C7060C198C0C18C1C30C383981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000007FC3FE07F18C0C187FE3EC1FF181C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000003CC0F803E18C0C183E61EC07C181C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000007E000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000001FF800000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000381C00000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000700E00000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000060060300860030110180F818 +%088000000000000040000000000000001E00000010000000000000380700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0001FC0DF81FC3F8FF0F8FE +%0FE000000000000040000000000000003E000000300000000000003C0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0003CE0F9C38E3F9C7061C7 +%0FC0000000000000400000000000000030000000300000000000003C0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0003030E0C3073818386383 +%8E00000000000000400000000000000030000000300000000000003E0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0FE6030C0E6033800386301 +%8C000000000000004000000000000000FE1F00F07E1F037007FF00360700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0FF7030C0E7033800386301 +%CC000000000000004000000000000000FE7FC1FC7C3F83F007FF00330700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0077FF0C0E7FF380FF86301 +%CC0000000000000040000000000000003061C38E3071C3D0000000338700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0076000C0E600381E386301 +%CC00000000000000400000000000000030E0C70630C0E38000000031C700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0076000C0E6003838386301 +%CC0000000000000040000000000000003000C60030C0630000000030C700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000070077030C0E7033830386301 +%8C0000000000000040000000000000003007C60030C0630000000030E700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000381E3870C0E3073830786383 +%8C000000000000004000000000000000303FC60031C0730007FF00307700000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000001FFC1FE0C0E3FE381CF879FF +%0C0000000000000040000000000000003070C60030C0630007FF00303700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000007F00FC0C0E0FC380F983C7C +%0C00000000000000400000000000000030C0C60230C06300000000303F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000030C0C60630C06300000000301F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000030E1C30E38E0E300000000300F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000000307FE3FC3E7FC300000000300F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000000303C60F01E1F0300000000300700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000018000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000018000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000007C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000007C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FE000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FE000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FF000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FF000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000001F800000000000000000F000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000007FE00000000C00000001F000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000E0F00000000C000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000001C0300000000C000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000180380000000E000000038000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000380003F837E3F0FC0FC07F7F1FC07EC606 +%0FE0DF81FC60700000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000003800073C3CF0C1CE0FC0187F3CE0E7C606 +%1C70FBC38E70600000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030000C0C3870C3030E0018703071C1C606 +%3830E0C30630600000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030000C0E3030C3038C001870603181C606 +%3018C0C60030E00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030001C0E3030C7038C001870703181C606 +%3038C0C60038C00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030001FFE3030C7FF8C0018707FF180C606 +%3FF8C0C60018C00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000038019C003030C7000C001870600180C606 +%3000C0C60019800000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000018019C003030C7000C001870600181C606 +%3000C0C6000D800000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000001C030C0C3030C3030C001870703181C606 +%3018C0C6060D000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000E070E0C3030C3830C0018703871C3C70E +%3838C0C3060F000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000007FE07BC3030F1EF0C0018703FE0F7C3FE +%1EF0C0C3DE07000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000003F803F0303070FC0C0018700FC07DC1F6 +%07E0C0C0F806000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000006000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000006000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%00000000001C000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000038000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000008000 +%000000000030000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001E000187C00000000000003C0 +%0060F8000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003E00011FF000C0000000007C0 +%0063FC000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000300003183001C000000000E00 +%00670E000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000300003303801C000000380C00 +%004606000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000FC1802301803E030000381F03 +%00C607000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000FC7F06001803F1FC000381F9F +%C0C006000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000070E706003801C38E000380C18 +%E08006000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C386007001C707003FF8C30 +%60800E000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C00C00E001C603003FF8C38 +%01801C000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000030F00C01C001C603800380C1E +%018038000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000FE307E0C038001C603800380C0F +%C10070000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000FE300F88070001C603800380C03 +%E300E0000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003003980E0001C603800380C00 +%7303C0000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003181981C0001C703000380C30 +%330300000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C190380001C307000000C38 +%760600000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000030FF103FF800F3FE000000C1F +%E60FFE000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000307E303FF800F0FC000000C0F +%C60FFF000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0 lw 1 lj 0.000 c 17781 10461 m 14606 10461 l 14606 6016 l 20956 6016 l +20956 10461 l 17781 10461 l pc +gs +pum +15663 7567 t +65 0 m 65 -606 l 274 -606 l 321 -606 357 -603 382 -597 ct 416 -589 446 -575 471 -554 ct +503 -527 526 -492 542 -450 ct 558 -408 566 -360 566 -306 ct 566 -260 561 -219 550 -184 ct +539 -148 525 -119 509 -95 ct 492 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +353 -3 320 0 284 0 ct p +145 -71 m 275 -71 l 315 -71 346 -75 369 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 457 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -371 473 -419 452 -453 ct +431 -487 406 -510 376 -522 ct 355 -530 320 -534 272 -534 ct 145 -534 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1564 -520 m 1564 -606 l 1638 -606 l 1638 -520 l p +1564 0 m 1564 -439 l 1638 -439 l 1638 0 l p ef +1748 0 m 1748 -439 l 1815 -439 l 1815 -377 l 1829 -399 1847 -416 1870 -429 ct +1893 -442 1919 -449 1948 -449 ct 1981 -449 2007 -442 2028 -428 ct 2049 -415 2064 -396 2072 -372 ct +2107 -423 2152 -449 2208 -449 ct 2251 -449 2285 -437 2308 -412 ct 2332 -388 2343 -351 2343 -301 ct +2343 0 l 2269 0 l 2269 -276 l 2269 -306 2267 -327 2262 -340 ct 2257 -354 2249 -364 2236 -372 ct +2223 -380 2208 -384 2191 -384 ct 2160 -384 2135 -374 2114 -353 ct 2094 -333 2084 -300 2084 -255 ct +2084 0 l 2009 0 l 2009 -285 l 2009 -318 2003 -343 1991 -359 ct 1979 -376 1959 -384 1932 -384 ct +1911 -384 1891 -379 1873 -368 ct 1856 -357 1843 -340 1835 -319 ct 1827 -298 1823 -267 1823 -227 ct +1823 0 l p ef +2750 -54 m 2722 -30 2696 -14 2670 -4 ct 2645 5 2617 9 2588 9 ct 2540 9 2503 -1 2477 -25 ct +2451 -49 2438 -79 2438 -115 ct 2438 -137 2443 -156 2453 -174 ct 2463 -192 2475 -206 2491 -217 ct +2507 -228 2525 -236 2545 -241 ct 2559 -245 2581 -249 2611 -253 ct 2671 -260 2715 -268 2744 -278 ct +2744 -288 2744 -295 2744 -298 ct 2744 -328 2737 -349 2723 -362 ct 2704 -379 2676 -387 2638 -387 ct +2603 -387 2577 -381 2561 -369 ct 2544 -356 2532 -335 2524 -303 ct 2451 -313 l +2458 -345 2468 -370 2484 -389 ct 2499 -408 2521 -423 2549 -433 ct 2578 -443 2611 -449 2649 -449 ct +2687 -449 2717 -444 2740 -435 ct 2764 -427 2781 -415 2792 -402 ct 2803 -389 2811 -372 2815 -351 ct +2818 -339 2819 -316 2819 -283 ct 2819 -184 l 2819 -114 2821 -71 2824 -52 ct +2827 -34 2833 -16 2843 0 ct 2765 0 l 2757 -15 l 2752 -33 l p +2744 -220 m 2717 -209 2676 -200 2622 -192 ct 2592 -187 2570 -182 2557 -177 ct +2545 -171 2535 -163 2528 -153 ct 2521 -142 2518 -130 2518 -117 ct 2518 -98 2525 -81 2540 -68 ct +2555 -55 2577 -48 2606 -48 ct 2635 -48 2660 -54 2683 -67 ct 2705 -79 2721 -96 2732 -118 ct +2740 -135 2744 -160 2744 -193 ct p ef +3076 -66 m 3087 0 l 3066 3 3047 5 3030 5 ct 3003 5 2982 1 2968 -7 ct 2953 -15 2942 -26 2936 -40 ct +2930 -54 2927 -83 2927 -128 ct 2927 -381 l 2872 -381 l 2872 -439 l 2927 -439 l +2927 -547 l 3001 -592 l 3001 -439 l 3076 -439 l 3076 -381 l 3001 -381 l +3001 -124 l 3001 -103 3002 -89 3005 -83 ct 3008 -77 3012 -72 3018 -69 ct 3024 -65 3032 -63 3043 -63 ct +3051 -63 l 3062 -64 l p ef +3152 -520 m 3152 -606 l 3226 -606 l 3226 -520 l p +3152 0 m 3152 -439 l 3226 -439 l 3226 0 l p ef +3336 0 m 3336 -439 l 3403 -439 l 3403 -376 l 3436 -425 3482 -449 3543 -449 ct +3570 -449 3594 -444 3616 -434 ct 3638 -425 3655 -412 3666 -397 ct 3677 -382 3685 -363 3689 -342 ct +3692 -328 3693 -304 3693 -270 ct 3693 0 l 3619 0 l 3619 -267 l 3619 -297 3616 -320 3610 -335 ct +3604 -350 3594 -362 3579 -371 ct 3565 -380 3547 -384 3527 -384 ct 3496 -384 3468 -374 3445 -354 ct +3422 -334 3411 -296 3411 -239 ct 3411 0 l p ef +3799 36 m 3871 47 l 3874 69 3883 85 3896 95 ct 3915 109 3940 116 3972 116 ct +4006 116 4033 109 4052 95 ct 4071 82 4083 62 4090 38 ct 4094 22 4095 -8 4095 -57 ct +4063 -19 4022 0 3974 0 ct 3913 0 3867 -21 3833 -65 ct 3800 -108 3784 -161 3784 -222 ct +3784 -264 3791 -302 3807 -338 ct 3822 -373 3844 -400 3873 -420 ct 3901 -439 3935 -449 3974 -449 ct +4026 -449 4069 -428 4102 -386 ct 4102 -439 l 4171 -439 l 4171 -59 l 4171 8 4164 57 4150 85 ct +4136 114 4114 136 4084 153 ct 4054 169 4017 178 3972 178 ct 3920 178 3878 166 3845 142 ct +3813 119 l 3798 83 l p +3860 -227 m 3860 -169 3872 -127 3895 -101 ct 3918 -74 3946 -61 3981 -61 ct +4015 -61 4044 -74 4067 -101 ct 4090 -127 4101 -168 4101 -224 ct 4101 -278 4090 -319 4066 -346 ct +4042 -373 4013 -387 3979 -387 ct 3946 -387 3918 -374 3895 -347 ct 3872 -320 l +3860 -280 l p ef +pom +pum +16007 8520 t +62 0 m 62 -606 l 142 -606 l 142 -71 l 440 -71 l 440 0 l p ef +478 -219 m 478 -300 500 -361 545 -400 ct 583 -432 629 -449 684 -449 ct 744 -449 793 -429 832 -389 ct +870 -350 889 -295 889 -225 ct 889 -169 881 -124 864 -92 ct 847 -60 822 -34 790 -16 ct +757 0 722 9 684 9 ct 622 9 572 -9 534 -49 ct 497 -88 l 478 -145 l p +554 -219 m 554 -163 566 -121 591 -93 ct 615 -65 646 -51 684 -51 ct 721 -51 751 -65 776 -93 ct +800 -121 813 -164 813 -222 ct 813 -276 800 -317 776 -345 ct 751 -373 720 -387 684 -387 ct +646 -387 615 -373 591 -345 ct 566 -317 l 554 -275 l p ef +1062 0 m 928 -439 l 1005 -439 l 1075 -185 l 1101 -91 l 1102 -96 1110 -126 1124 -181 ct +1194 -439 l 1270 -439 l 1336 -184 l 1358 -100 l 1383 -185 l 1458 -439 l +1531 -439 l 1393 0 l 1316 0 l 1246 -263 l 1229 -337 l 1140 0 l p ef +1811 0 m 1811 -606 l 2040 -606 l 2080 -606 2111 -604 2132 -600 ct 2162 -595 2187 -586 2207 -572 ct +2227 -558 2243 -538 2255 -513 ct 2268 -488 2274 -461 2274 -430 ct 2274 -379 2257 -335 2224 -300 ct +2192 -264 2132 -246 2047 -246 ct 1891 -246 l 1891 0 l p +1891 -318 m 2048 -318 l 2100 -318 2136 -327 2158 -346 ct 2180 -366 2191 -393 2191 -428 ct +2191 -453 2185 -475 2172 -493 ct 2159 -511 2142 -523 2121 -529 ct 2108 -532 2083 -534 2046 -534 ct +1891 -534 l p ef +2644 -54 m 2616 -30 2590 -14 2564 -4 ct 2539 5 2511 9 2482 9 ct 2434 9 2397 -1 2371 -25 ct +2345 -49 2332 -79 2332 -115 ct 2332 -137 2337 -156 2347 -174 ct 2357 -192 2369 -206 2385 -217 ct +2401 -228 2419 -236 2439 -241 ct 2453 -245 2475 -249 2505 -253 ct 2565 -260 2609 -268 2638 -278 ct +2638 -288 2638 -295 2638 -298 ct 2638 -328 2631 -349 2617 -362 ct 2598 -379 2570 -387 2532 -387 ct +2497 -387 2471 -381 2455 -369 ct 2438 -356 2426 -335 2418 -303 ct 2345 -313 l +2352 -345 2362 -370 2378 -389 ct 2393 -408 2415 -423 2443 -433 ct 2472 -443 2505 -449 2543 -449 ct +2581 -449 2611 -444 2634 -435 ct 2658 -427 2675 -415 2686 -402 ct 2697 -389 2705 -372 2709 -351 ct +2712 -339 2713 -316 2713 -283 ct 2713 -184 l 2713 -114 2715 -71 2718 -52 ct +2721 -34 2727 -16 2737 0 ct 2659 0 l 2651 -15 l 2646 -33 l p +2638 -220 m 2611 -209 2570 -200 2516 -192 ct 2486 -187 2464 -182 2451 -177 ct +2439 -171 2429 -163 2422 -153 ct 2415 -142 2412 -130 2412 -117 ct 2412 -98 2419 -81 2434 -68 ct +2449 -55 2471 -48 2500 -48 ct 2529 -48 2554 -54 2577 -67 ct 2599 -79 2615 -96 2626 -118 ct +2634 -135 2638 -160 2638 -193 ct p ef +2778 -131 m 2851 -142 l 2855 -113 2867 -90 2886 -74 ct 2905 -59 2931 -51 2965 -51 ct +2999 -51 3024 -58 3041 -72 ct 3058 -86 3066 -102 3066 -121 ct 3066 -138 3059 -151 3044 -160 ct +3034 -167 3008 -175 2968 -186 ct 2913 -199 2875 -211 2854 -221 ct 2833 -231 2817 -245 2806 -263 ct +2795 -281 2790 -301 2790 -322 ct 2790 -342 2794 -360 2803 -376 ct 2812 -393 2825 -407 2840 -418 ct +2852 -427 2867 -434 2887 -440 ct 2907 -446 2929 -449 2952 -449 ct 2986 -449 3016 -444 3042 -434 ct +3069 -424 3088 -410 3100 -393 ct 3113 -376 3121 -354 3126 -325 ct 3053 -315 l +3050 -338 3040 -356 3024 -368 ct 3008 -381 2986 -387 2957 -387 ct 2923 -387 2898 -382 2884 -370 ct +2869 -359 2862 -346 2862 -331 ct 2862 -321 2865 -312 2871 -305 ct 2877 -297 2887 -290 2900 -285 ct +2907 -282 2929 -276 2965 -266 ct 3018 -252 3055 -240 3076 -231 ct 3096 -222 3113 -209 3125 -192 ct +3136 -175 3142 -154 3142 -129 ct 3142 -104 3135 -80 3121 -58 ct 3106 -37 3085 -20 3058 -8 ct +3031 3 3000 9 2965 9 ct 2908 9 2865 -1 2835 -25 ct 2805 -49 l 2786 -84 l p ef +3175 -131 m 3248 -142 l 3252 -113 3264 -90 3283 -74 ct 3302 -59 3328 -51 3362 -51 ct +3396 -51 3421 -58 3438 -72 ct 3455 -86 3463 -102 3463 -121 ct 3463 -138 3456 -151 3441 -160 ct +3431 -167 3405 -175 3365 -186 ct 3310 -199 3272 -211 3251 -221 ct 3230 -231 3214 -245 3203 -263 ct +3192 -281 3187 -301 3187 -322 ct 3187 -342 3191 -360 3200 -376 ct 3209 -393 3222 -407 3237 -418 ct +3249 -427 3264 -434 3284 -440 ct 3304 -446 3326 -449 3349 -449 ct 3383 -449 3413 -444 3439 -434 ct +3466 -424 3485 -410 3497 -393 ct 3510 -376 3518 -354 3523 -325 ct 3450 -315 l +3447 -338 3437 -356 3421 -368 ct 3405 -381 3383 -387 3354 -387 ct 3320 -387 3295 -382 3281 -370 ct +3266 -359 3259 -346 3259 -331 ct 3259 -321 3262 -312 3268 -305 ct 3274 -297 3284 -290 3297 -285 ct +3304 -282 3326 -276 3362 -266 ct 3415 -252 3452 -240 3473 -231 ct 3493 -222 3510 -209 3522 -192 ct +3533 -175 3539 -154 3539 -129 ct 3539 -104 3532 -80 3518 -58 ct 3503 -37 3482 -20 3455 -8 ct +3428 3 3397 9 3362 9 ct 3305 9 3262 -1 3232 -25 ct 3202 -49 l 3183 -84 l p ef +pom +pum +16827 9473 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +585 -520 m 585 -606 l 659 -606 l 659 -520 l p +585 0 m 585 -439 l 659 -439 l 659 0 l p ef +768 0 m 768 -606 l 842 -606 l 842 0 l p ef +1118 -66 m 1129 0 l 1108 3 1089 5 1072 5 ct 1045 5 1024 1 1010 -7 ct 995 -15 984 -26 978 -40 ct +972 -54 969 -83 969 -128 ct 969 -381 l 914 -381 l 914 -439 l 969 -439 l +969 -547 l 1043 -592 l 1043 -439 l 1118 -439 l 1118 -381 l 1043 -381 l +1043 -124 l 1043 -103 1044 -89 1047 -83 ct 1050 -77 1054 -72 1060 -69 ct 1066 -65 1074 -63 1085 -63 ct +1093 -63 l 1104 -64 l p ef +1494 -141 m 1571 -131 l 1559 -86 1536 -52 1504 -27 ct 1471 -2 1429 9 1378 9 ct +1314 9 1263 -9 1225 -49 ct 1187 -88 1169 -144 1169 -215 ct 1169 -289 1188 -347 1226 -387 ct +1264 -428 1313 -449 1374 -449 ct 1432 -449 1480 -429 1518 -389 ct 1555 -349 1573 -292 1573 -220 ct +1573 -216 1573 -209 1573 -200 ct 1245 -200 l 1248 -152 1262 -115 1286 -89 ct +1311 -64 1342 -51 1378 -51 ct 1406 -51 1429 -58 1448 -72 ct 1467 -87 l 1483 -110 l +p +1250 -261 m 1495 -261 l 1492 -298 1482 -326 1467 -344 ct 1443 -373 1412 -387 1374 -387 ct +1340 -387 1312 -376 1288 -353 ct 1265 -330 l 1252 -300 l p ef +1669 0 m 1669 -439 l 1736 -439 l 1736 -372 l 1753 -403 1768 -424 1783 -434 ct +1797 -444 1813 -449 1831 -449 ct 1856 -449 1881 -441 1907 -425 ct 1882 -356 l +1863 -366 1845 -372 1827 -372 ct 1811 -372 1796 -367 1783 -357 ct 1770 -347 1761 -334 1755 -316 ct +1747 -290 1743 -261 1743 -229 ct 1743 0 l p ef +pom +gr +11317 10321 m 11312 10318 l 11099 10206 l 11093 10203 l 10924 10032 l +10921 10026 l 10811 9811 l 10808 9805 l 10769 9556 l 10769 9549 l +10808 9299 l 10811 9293 l 10921 9078 l 10924 9072 l 11093 8901 l 11099 8898 l +11312 8786 l 11317 8784 l 11564 8744 l 11571 8744 l 11817 8784 l 11823 8786 l +12036 8898 l 12041 8901 l 12210 9072 l 12213 9078 l 12324 9293 l 12326 9299 l +12366 9549 l 12366 9556 l 12326 9805 l 12324 9811 l 12213 10026 l +12210 10032 l 12041 10203 l 12036 10206 l 11823 10318 l 11817 10321 l +11571 10361 l 11564 10361 l 11317 10321 l p +11567 10319 m 11806 10279 l 12013 10171 l 12178 10004 l 12285 9794 l +12324 9552 l 12285 9310 l 12178 9100 l 12013 8933 l 11806 8825 l 11567 8786 l +11328 8825 l 11121 8933 l 10956 9100 l 10849 9310 l 10811 9552 l 10849 9794 l +10956 10004 l 11121 10171 l 11328 10279 l 11567 10319 l p +11049 9029 m 11079 8998 l 11286 9208 l 11493 9417 l 11700 9627 l 11907 9837 l +12115 10048 l 12085 10078 l 11877 9868 l 11670 9658 l 11463 9448 l +11255 9238 l 11049 9029 l p +11079 10078 m 11049 10049 l 11255 9838 l 11463 9628 l 11670 9418 l +11878 9208 l 12086 8998 l 12115 9029 l 11907 9239 l 11700 9449 l 11493 9659 l +11286 9869 l 11079 10078 l p ef +1 lw 0 lj 11317 10321 m 11312 10318 l 11099 10206 l 11093 10203 l 10924 10032 l +10921 10026 l 10811 9811 l 10808 9805 l 10769 9556 l 10769 9549 l +10808 9299 l 10811 9293 l 10921 9078 l 10924 9072 l 11093 8901 l 11099 8898 l +11312 8786 l 11317 8784 l 11564 8744 l 11571 8744 l 11817 8784 l 11823 8786 l +12036 8898 l 12041 8901 l 12210 9072 l 12213 9078 l 12324 9293 l 12326 9299 l +12366 9549 l 12366 9556 l 12326 9805 l 12324 9811 l 12213 10026 l +12210 10032 l 12041 10203 l 12036 10206 l 11823 10318 l 11817 10321 l +11571 10361 l 11564 10361 l 11317 10321 l pc +11567 10319 m 11806 10279 l 12013 10171 l 12178 10004 l 12285 9794 l +12324 9552 l 12285 9310 l 12178 9100 l 12013 8933 l 11806 8825 l 11567 8786 l +11328 8825 l 11121 8933 l 10956 9100 l 10849 9310 l 10811 9552 l 10849 9794 l +10956 10004 l 11121 10171 l 11328 10279 l 11567 10319 l pc +11049 9029 m 11079 8998 l 11286 9208 l 11493 9417 l 11700 9627 l 11907 9837 l +12115 10048 l 12085 10078 l 11877 9868 l 11670 9658 l 11463 9448 l +11255 9238 l 11049 9029 l pc +11079 10078 m 11049 10049 l 11255 9838 l 11463 9628 l 11670 9418 l +11878 9208 l 12086 8998 l 12115 9029 l 11907 9239 l 11700 9449 l 11493 9659 l +11286 9869 l 11079 10078 l pc +7989 6986 m 7538 6836 l 7539 7136 l 7989 6986 l p ef +5716 6986 m 7629 6986 l ps +14606 6986 m 14155 6836 l 14156 7136 l 14606 6986 l p ef +9526 6986 m 14246 6986 l ps +10769 9526 m 10318 9376 l 10319 9676 l 10769 9526 l p ef +5716 9526 m 10409 9526 l ps +14606 9526 m 14155 9376 l 14156 9676 l 14606 9526 l p ef +12426 9526 m 14246 9526 l ps +0 lw 1 lj 10061 16546 m 6251 16546 l 6251 12736 l 13871 12736 l 13871 16546 l +10061 16546 l pc +gs +pum +9102 13970 t +64 0 m 64 -606 l 146 -606 l 465 -130 l 465 -606 l 542 -606 l 542 0 l +459 0 l 141 -476 l 141 0 l p ef +1106 -212 m 1187 -192 l 1170 -126 1140 -76 1096 -41 ct 1052 -6 999 10 936 10 ct +870 10 817 -2 776 -29 ct 735 -56 704 -94 683 -145 ct 661 -195 651 -249 651 -307 ct +651 -370 663 -425 687 -472 ct 711 -519 745 -555 790 -580 ct 834 -604 883 -616 937 -616 ct +998 -616 1049 -601 1090 -570 ct 1131 -539 1160 -496 1176 -440 ct 1097 -421 l +1083 -465 1063 -497 1036 -517 ct 1009 -537 976 -547 935 -547 ct 889 -547 850 -536 818 -514 ct +787 -492 765 -462 752 -424 ct 740 -386 733 -348 733 -308 ct 733 -256 741 -211 756 -173 ct +771 -134 794 -105 826 -86 ct 858 -67 892 -58 929 -58 ct 974 -58 1012 -71 1043 -97 ct +1074 -123 l 1095 -161 l p ef +1284 -295 m 1284 -395 1311 -474 1366 -531 ct 1420 -588 1489 -617 1575 -617 ct +1631 -617 1681 -603 1726 -576 ct 1771 -550 1805 -512 1829 -465 ct 1852 -417 1864 -362 1864 -302 ct +1864 -240 1852 -185 1827 -137 ct 1802 -88 1767 -52 1722 -27 ct 1676 -2 1627 10 1574 10 ct +1517 10 1466 -3 1421 -31 ct 1376 -58 1342 -96 1319 -143 ct 1296 -191 l 1284 -242 l +p +1367 -294 m 1367 -220 1387 -163 1426 -121 ct 1465 -79 1515 -58 1574 -58 ct +1634 -58 1684 -79 1723 -122 ct 1762 -164 1782 -224 1782 -302 ct 1782 -352 1773 -395 1757 -431 ct +1740 -468 1715 -497 1683 -517 ct 1651 -537 1615 -547 1575 -547 ct 1518 -547 1470 -528 1429 -489 ct +1388 -450 l 1367 -385 l p ef +pom +pum +7514 14923 t +38 -194 m 113 -201 l 117 -171 125 -146 138 -126 ct 151 -107 172 -91 199 -79 ct +227 -67 258 -61 292 -61 ct 323 -61 350 -66 373 -75 ct 397 -84 414 -96 426 -112 ct +437 -128 443 -145 443 -164 ct 443 -183 437 -200 426 -214 ct 415 -228 397 -240 372 -250 ct +355 -256 319 -266 264 -279 ct 208 -293 169 -305 147 -317 ct 118 -332 96 -351 82 -374 ct +68 -396 61 -421 61 -449 ct 61 -480 69 -508 87 -535 ct 104 -561 130 -582 163 -595 ct +196 -609 233 -616 274 -616 ct 319 -616 359 -609 393 -594 ct 427 -580 454 -559 472 -531 ct +491 -502 501 -471 502 -435 ct 425 -429 l 421 -468 407 -496 383 -516 ct 359 -536 324 -545 277 -545 ct +229 -545 194 -537 171 -519 ct 149 -501 138 -480 138 -454 ct 138 -433 146 -415 162 -401 ct +177 -387 217 -372 283 -357 ct 348 -343 393 -330 417 -319 ct 452 -303 478 -282 495 -257 ct +512 -232 520 -203 520 -171 ct 520 -138 511 -108 492 -80 ct 474 -51 447 -29 413 -13 ct +378 2 339 10 296 10 ct 241 10 195 2 158 -13 ct 121 -29 92 -53 71 -85 ct 50 -117 l +39 -154 l p ef +638 -520 m 638 -606 l 712 -606 l 712 -520 l p +638 0 m 638 -439 l 712 -439 l 712 0 l p ef +822 0 m 822 -439 l 889 -439 l 889 -376 l 922 -425 968 -449 1029 -449 ct +1056 -449 1080 -444 1102 -434 ct 1124 -425 1141 -412 1152 -397 ct 1163 -382 1171 -363 1175 -342 ct +1178 -328 1179 -304 1179 -270 ct 1179 0 l 1105 0 l 1105 -267 l 1105 -297 1102 -320 1096 -335 ct +1090 -350 1080 -362 1065 -371 ct 1051 -380 1033 -384 1013 -384 ct 982 -384 954 -374 931 -354 ct +908 -334 897 -296 897 -239 ct 897 0 l p ef +1600 -141 m 1677 -131 l 1665 -86 1642 -52 1610 -27 ct 1577 -2 1535 9 1484 9 ct +1420 9 1369 -9 1331 -49 ct 1293 -88 1275 -144 1275 -215 ct 1275 -289 1294 -347 1332 -387 ct +1370 -428 1419 -449 1480 -449 ct 1538 -449 1586 -429 1624 -389 ct 1661 -349 1679 -292 1679 -220 ct +1679 -216 1679 -209 1679 -200 ct 1351 -200 l 1354 -152 1368 -115 1392 -89 ct +1417 -64 1448 -51 1484 -51 ct 1512 -51 1535 -58 1554 -72 ct 1573 -87 l 1589 -110 l +p +1356 -261 m 1601 -261 l 1598 -298 1588 -326 1573 -344 ct 1549 -373 1518 -387 1480 -387 ct +1446 -387 1418 -376 1394 -353 ct 1371 -330 l 1358 -300 l p ef +1958 10 m 2133 -616 l 2193 -616 l 2017 10 l p ef +2931 -212 m 3012 -192 l 2995 -126 2965 -76 2921 -41 ct 2877 -6 2824 10 2761 10 ct +2695 10 2642 -2 2601 -29 ct 2560 -56 2529 -94 2508 -145 ct 2486 -195 2476 -249 2476 -307 ct +2476 -370 2488 -425 2512 -472 ct 2536 -519 2570 -555 2615 -580 ct 2659 -604 2708 -616 2762 -616 ct +2823 -616 2874 -601 2915 -570 ct 2956 -539 2985 -496 3001 -440 ct 2922 -421 l +2908 -465 2888 -497 2861 -517 ct 2834 -537 2801 -547 2760 -547 ct 2714 -547 2675 -536 2643 -514 ct +2612 -492 2590 -462 2577 -424 ct 2565 -386 2558 -348 2558 -308 ct 2558 -256 2566 -211 2581 -173 ct +2596 -134 2619 -105 2651 -86 ct 2683 -67 2717 -58 2754 -58 ct 2799 -58 2837 -71 2868 -97 ct +2899 -123 l 2920 -161 l p ef +3097 -219 m 3097 -300 3119 -361 3164 -400 ct 3202 -432 3248 -449 3303 -449 ct +3363 -449 3412 -429 3451 -389 ct 3489 -350 3508 -295 3508 -225 ct 3508 -169 3500 -124 3483 -92 ct +3466 -60 3441 -34 3409 -16 ct 3376 0 3341 9 3303 9 ct 3241 9 3191 -9 3153 -49 ct +3116 -88 l 3097 -145 l p +3173 -219 m 3173 -163 3185 -121 3210 -93 ct 3234 -65 3265 -51 3303 -51 ct 3340 -51 3370 -65 3395 -93 ct +3419 -121 3432 -164 3432 -222 ct 3432 -276 3419 -317 3395 -345 ct 3370 -373 3339 -387 3303 -387 ct +3265 -387 3234 -373 3210 -345 ct 3185 -317 l 3173 -275 l p ef +3571 -131 m 3644 -142 l 3648 -113 3660 -90 3679 -74 ct 3698 -59 3724 -51 3758 -51 ct +3792 -51 3817 -58 3834 -72 ct 3851 -86 3859 -102 3859 -121 ct 3859 -138 3852 -151 3837 -160 ct +3827 -167 3801 -175 3761 -186 ct 3706 -199 3668 -211 3647 -221 ct 3626 -231 3610 -245 3599 -263 ct +3588 -281 3583 -301 3583 -322 ct 3583 -342 3587 -360 3596 -376 ct 3605 -393 3618 -407 3633 -418 ct +3645 -427 3660 -434 3680 -440 ct 3700 -446 3722 -449 3745 -449 ct 3779 -449 3809 -444 3835 -434 ct +3862 -424 3881 -410 3893 -393 ct 3906 -376 3914 -354 3919 -325 ct 3846 -315 l +3843 -338 3833 -356 3817 -368 ct 3801 -381 3779 -387 3750 -387 ct 3716 -387 3691 -382 3677 -370 ct +3662 -359 3655 -346 3655 -331 ct 3655 -321 3658 -312 3664 -305 ct 3670 -297 3680 -290 3693 -285 ct +3700 -282 3722 -276 3758 -266 ct 3811 -252 3848 -240 3869 -231 ct 3889 -222 3906 -209 3918 -192 ct +3929 -175 3935 -154 3935 -129 ct 3935 -104 3928 -80 3914 -58 ct 3899 -37 3878 -20 3851 -8 ct +3824 3 3793 9 3758 9 ct 3701 9 3658 -1 3628 -25 ct 3598 -49 l 3579 -84 l p ef +3998 -520 m 3998 -606 l 4072 -606 l 4072 -520 l p +3998 0 m 3998 -439 l 4072 -439 l 4072 0 l p ef +4183 0 m 4183 -439 l 4250 -439 l 4250 -376 l 4283 -425 4329 -449 4390 -449 ct +4417 -449 4441 -444 4463 -434 ct 4485 -425 4502 -412 4513 -397 ct 4524 -382 4532 -363 4536 -342 ct +4539 -328 4540 -304 4540 -270 ct 4540 0 l 4466 0 l 4466 -267 l 4466 -297 4463 -320 4457 -335 ct +4451 -350 4441 -362 4426 -371 ct 4412 -380 4394 -384 4374 -384 ct 4343 -384 4315 -374 4292 -354 ct +4269 -334 4258 -296 4258 -239 ct 4258 0 l p ef +4960 -141 m 5037 -131 l 5025 -86 5002 -52 4970 -27 ct 4937 -2 4895 9 4844 9 ct +4780 9 4729 -9 4691 -49 ct 4653 -88 4635 -144 4635 -215 ct 4635 -289 4654 -347 4692 -387 ct +4730 -428 4779 -449 4840 -449 ct 4898 -449 4946 -429 4984 -389 ct 5021 -349 5039 -292 5039 -220 ct +5039 -216 5039 -209 5039 -200 ct 4711 -200 l 4714 -152 4728 -115 4752 -89 ct +4777 -64 4808 -51 4844 -51 ct 4872 -51 4895 -58 4914 -72 ct 4933 -87 l 4949 -110 l +p +4716 -261 m 4961 -261 l 4958 -298 4948 -326 4933 -344 ct 4909 -373 4878 -387 4840 -387 ct +4806 -387 4778 -376 4754 -353 ct 4731 -330 l 4718 -300 l p ef +pom +pum +8136 15876 t +349 -237 m 349 -308 l 605 -309 l 605 -84 l 566 -52 525 -29 483 -13 ct +441 2 398 10 354 10 ct 295 10 241 -2 192 -27 ct 143 -53 107 -90 82 -138 ct 57 -186 45 -240 45 -300 ct +45 -359 57 -414 82 -465 ct 106 -516 142 -554 188 -579 ct 234 -604 288 -616 348 -616 ct +392 -616 432 -609 467 -595 ct 502 -581 530 -561 550 -535 ct 571 -510 586 -477 596 -436 ct +524 -416 l 515 -447 504 -472 490 -489 ct 476 -507 457 -521 432 -532 ct 407 -542 379 -547 349 -547 ct +312 -547 280 -542 253 -531 ct 227 -520 205 -505 189 -487 ct 172 -468 160 -449 150 -427 ct +135 -389 127 -349 127 -305 ct 127 -251 137 -205 155 -169 ct 174 -133 201 -106 236 -88 ct +272 -70 310 -62 350 -62 ct 385 -62 418 -68 452 -82 ct 485 -95 510 -109 527 -124 ct +527 -237 l p ef +1017 -141 m 1094 -131 l 1082 -86 1059 -52 1027 -27 ct 994 -2 952 9 901 9 ct +837 9 786 -9 748 -49 ct 710 -88 692 -144 692 -215 ct 692 -289 711 -347 749 -387 ct +787 -428 836 -449 897 -449 ct 955 -449 1003 -429 1041 -389 ct 1078 -349 1096 -292 1096 -220 ct +1096 -216 1096 -209 1096 -200 ct 768 -200 l 771 -152 785 -115 809 -89 ct 834 -64 865 -51 901 -51 ct +929 -51 952 -58 971 -72 ct 990 -87 l 1006 -110 l p +773 -261 m 1018 -261 l 1015 -298 1005 -326 990 -344 ct 966 -373 935 -387 897 -387 ct +863 -387 835 -376 811 -353 ct 788 -330 l 775 -300 l p ef +1193 0 m 1193 -439 l 1260 -439 l 1260 -376 l 1293 -425 1339 -449 1400 -449 ct +1427 -449 1451 -444 1473 -434 ct 1495 -425 1512 -412 1523 -397 ct 1534 -382 1542 -363 1546 -342 ct +1549 -328 1550 -304 1550 -270 ct 1550 0 l 1476 0 l 1476 -267 l 1476 -297 1473 -320 1467 -335 ct +1461 -350 1451 -362 1436 -371 ct 1422 -380 1404 -384 1384 -384 ct 1353 -384 1325 -374 1302 -354 ct +1279 -334 1268 -296 1268 -239 ct 1268 0 l p ef +1970 -141 m 2047 -131 l 2035 -86 2012 -52 1980 -27 ct 1947 -2 1905 9 1854 9 ct +1790 9 1739 -9 1701 -49 ct 1663 -88 1645 -144 1645 -215 ct 1645 -289 1664 -347 1702 -387 ct +1740 -428 1789 -449 1850 -449 ct 1908 -449 1956 -429 1994 -389 ct 2031 -349 2049 -292 2049 -220 ct +2049 -216 2049 -209 2049 -200 ct 1721 -200 l 1724 -152 1738 -115 1762 -89 ct +1787 -64 1818 -51 1854 -51 ct 1882 -51 1905 -58 1924 -72 ct 1943 -87 l 1959 -110 l +p +1726 -261 m 1971 -261 l 1968 -298 1958 -326 1943 -344 ct 1919 -373 1888 -387 1850 -387 ct +1816 -387 1788 -376 1764 -353 ct 1741 -330 l 1728 -300 l p ef +2145 0 m 2145 -439 l 2212 -439 l 2212 -372 l 2229 -403 2244 -424 2259 -434 ct +2273 -444 2289 -449 2307 -449 ct 2332 -449 2357 -441 2383 -425 ct 2358 -356 l +2339 -366 2321 -372 2303 -372 ct 2287 -372 2272 -367 2259 -357 ct 2246 -347 2237 -334 2231 -316 ct +2223 -290 2219 -261 2219 -229 ct 2219 0 l p ef +2723 -54 m 2695 -30 2669 -14 2643 -4 ct 2618 5 2590 9 2561 9 ct 2513 9 2476 -1 2450 -25 ct +2424 -49 2411 -79 2411 -115 ct 2411 -137 2416 -156 2426 -174 ct 2436 -192 2448 -206 2464 -217 ct +2480 -228 2498 -236 2518 -241 ct 2532 -245 2554 -249 2584 -253 ct 2644 -260 2688 -268 2717 -278 ct +2717 -288 2717 -295 2717 -298 ct 2717 -328 2710 -349 2696 -362 ct 2677 -379 2649 -387 2611 -387 ct +2576 -387 2550 -381 2534 -369 ct 2517 -356 2505 -335 2497 -303 ct 2424 -313 l +2431 -345 2441 -370 2457 -389 ct 2472 -408 2494 -423 2522 -433 ct 2551 -443 2584 -449 2622 -449 ct +2660 -449 2690 -444 2713 -435 ct 2737 -427 2754 -415 2765 -402 ct 2776 -389 2784 -372 2788 -351 ct +2791 -339 2792 -316 2792 -283 ct 2792 -184 l 2792 -114 2794 -71 2797 -52 ct +2800 -34 2806 -16 2816 0 ct 2738 0 l 2730 -15 l 2725 -33 l p +2717 -220 m 2690 -209 2649 -200 2595 -192 ct 2565 -187 2543 -182 2530 -177 ct +2518 -171 2508 -163 2501 -153 ct 2494 -142 2491 -130 2491 -117 ct 2491 -98 2498 -81 2513 -68 ct +2528 -55 2550 -48 2579 -48 ct 2608 -48 2633 -54 2656 -67 ct 2678 -79 2694 -96 2705 -118 ct +2713 -135 2717 -160 2717 -193 ct p ef +3049 -66 m 3060 0 l 3039 3 3020 5 3003 5 ct 2976 5 2955 1 2941 -7 ct 2926 -15 2915 -26 2909 -40 ct +2903 -54 2900 -83 2900 -128 ct 2900 -381 l 2845 -381 l 2845 -439 l 2900 -439 l +2900 -547 l 2974 -592 l 2974 -439 l 3049 -439 l 3049 -381 l 2974 -381 l +2974 -124 l 2974 -103 2975 -89 2978 -83 ct 2981 -77 2985 -72 2991 -69 ct 2997 -65 3005 -63 3016 -63 ct +3024 -63 l 3035 -64 l p ef +3097 -219 m 3097 -300 3119 -361 3164 -400 ct 3202 -432 3248 -449 3303 -449 ct +3363 -449 3412 -429 3451 -389 ct 3489 -350 3508 -295 3508 -225 ct 3508 -169 3500 -124 3483 -92 ct +3466 -60 3441 -34 3409 -16 ct 3376 0 3341 9 3303 9 ct 3241 9 3191 -9 3153 -49 ct +3116 -88 l 3097 -145 l p +3173 -219 m 3173 -163 3185 -121 3210 -93 ct 3234 -65 3265 -51 3303 -51 ct 3340 -51 3370 -65 3395 -93 ct +3419 -121 3432 -164 3432 -222 ct 3432 -276 3419 -317 3395 -345 ct 3370 -373 3339 -387 3303 -387 ct +3265 -387 3234 -373 3210 -345 ct 3185 -317 l 3173 -275 l p ef +3600 0 m 3600 -439 l 3667 -439 l 3667 -372 l 3684 -403 3699 -424 3714 -434 ct +3728 -444 3744 -449 3762 -449 ct 3787 -449 3812 -441 3838 -425 ct 3813 -356 l +3794 -366 3776 -372 3758 -372 ct 3742 -372 3727 -367 3714 -357 ct 3701 -347 3692 -334 3686 -316 ct +3678 -290 3674 -261 3674 -229 ct 3674 0 l p ef +pom +gr +gs +pum +1284 9366 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +293 0 m 293 -439 l 360 -439 l 360 -376 l 393 -425 439 -449 500 -449 ct +527 -449 551 -444 573 -434 ct 595 -425 612 -412 623 -397 ct 634 -382 642 -363 646 -342 ct +649 -328 650 -304 650 -270 ct 650 0 l 576 0 l 576 -267 l 576 -297 573 -320 567 -335 ct +561 -350 551 -362 536 -371 ct 522 -380 504 -384 484 -384 ct 453 -384 425 -374 402 -354 ct +379 -334 368 -296 368 -239 ct 368 0 l p ef +769 168 m 769 -439 l 837 -439 l 837 -382 l 853 -404 871 -421 891 -432 ct +911 -443 936 -449 965 -449 ct 1002 -449 1035 -439 1064 -420 ct 1092 -400 1114 -373 1129 -338 ct +1143 -303 1151 -264 1151 -222 ct 1151 -177 1143 -137 1126 -101 ct 1110 -65 1087 -37 1056 -18 ct +1025 0 993 9 959 9 ct 934 9 912 4 892 -5 ct 873 -16 856 -29 844 -45 ct 844 168 l +p +837 -217 m 837 -160 848 -118 871 -91 ct 894 -64 922 -51 954 -51 ct 987 -51 1016 -65 1039 -93 ct +1063 -121 1075 -164 1075 -223 ct 1075 -279 1063 -321 1040 -349 ct 1017 -376 990 -390 958 -390 ct +926 -390 898 -376 873 -346 ct 849 -316 l 837 -273 l p ef +1507 0 m 1507 -64 l 1473 -14 1427 9 1368 9 ct 1342 9 1318 4 1295 -4 ct 1273 -14 1256 -27 1245 -42 ct +1234 -57 1227 -75 1222 -97 ct 1219 -112 1218 -135 1218 -167 ct 1218 -439 l 1292 -439 l +1292 -195 l 1292 -156 1294 -130 1297 -117 ct 1301 -97 1311 -82 1326 -70 ct +1342 -59 1360 -54 1383 -54 ct 1405 -54 1426 -59 1446 -71 ct 1465 -82 1479 -98 1487 -118 ct +1495 -137 1499 -166 1499 -203 ct 1499 -439 l 1574 -439 l 1574 0 l p ef +1858 -66 m 1869 0 l 1848 3 1829 5 1812 5 ct 1785 5 1764 1 1750 -7 ct 1735 -15 1724 -26 1718 -40 ct +1712 -54 1709 -83 1709 -128 ct 1709 -381 l 1654 -381 l 1654 -439 l 1709 -439 l +1709 -547 l 1783 -592 l 1783 -439 l 1858 -439 l 1858 -381 l 1783 -381 l +1783 -124 l 1783 -103 1784 -89 1787 -83 ct 1790 -77 1794 -72 1800 -69 ct 1806 -65 1814 -63 1825 -63 ct +1833 -63 l 1844 -64 l p ef +2190 0 m 2190 -381 l 2124 -381 l 2124 -439 l 2190 -439 l 2190 -485 l +2190 -515 2193 -537 2198 -551 ct 2205 -571 2218 -586 2236 -598 ct 2254 -610 2279 -616 2312 -616 ct +2333 -616 2356 -614 2381 -609 ct 2370 -544 l 2355 -547 2340 -548 2326 -548 ct +2304 -548 2288 -543 2278 -533 ct 2269 -524 2264 -506 2264 -479 ct 2264 -439 l +2350 -439 l 2350 -381 l 2264 -381 l 2264 0 l p ef +2410 0 m 2410 -439 l 2477 -439 l 2477 -372 l 2494 -403 2509 -424 2524 -434 ct +2538 -444 2554 -449 2572 -449 ct 2597 -449 2622 -441 2648 -425 ct 2623 -356 l +2604 -366 2586 -372 2568 -372 ct 2552 -372 2537 -367 2524 -357 ct 2511 -347 2502 -334 2496 -316 ct +2488 -290 2484 -261 2484 -229 ct 2484 0 l p ef +2674 -219 m 2674 -300 2696 -361 2741 -400 ct 2779 -432 2825 -449 2880 -449 ct +2940 -449 2989 -429 3028 -389 ct 3066 -350 3085 -295 3085 -225 ct 3085 -169 3077 -124 3060 -92 ct +3043 -60 3018 -34 2986 -16 ct 2953 0 2918 9 2880 9 ct 2818 9 2768 -9 2730 -49 ct +2693 -88 l 2674 -145 l p +2750 -219 m 2750 -163 2762 -121 2787 -93 ct 2811 -65 2842 -51 2880 -51 ct 2917 -51 2947 -65 2972 -93 ct +2996 -121 3009 -164 3009 -222 ct 3009 -276 2996 -317 2972 -345 ct 2947 -373 2916 -387 2880 -387 ct +2842 -387 2811 -373 2787 -345 ct 2762 -317 l 2750 -275 l p ef +3177 0 m 3177 -439 l 3244 -439 l 3244 -377 l 3258 -399 3276 -416 3299 -429 ct +3322 -442 3348 -449 3377 -449 ct 3410 -449 3436 -442 3457 -428 ct 3478 -415 3493 -396 3501 -372 ct +3536 -423 3581 -449 3637 -449 ct 3680 -449 3714 -437 3737 -412 ct 3761 -388 3772 -351 3772 -301 ct +3772 0 l 3698 0 l 3698 -276 l 3698 -306 3696 -327 3691 -340 ct 3686 -354 3678 -364 3665 -372 ct +3652 -380 3637 -384 3620 -384 ct 3589 -384 3564 -374 3543 -353 ct 3523 -333 3513 -300 3513 -255 ct +3513 0 l 3438 0 l 3438 -285 l 3438 -318 3432 -343 3420 -359 ct 3408 -376 3388 -384 3361 -384 ct +3340 -384 3320 -379 3302 -368 ct 3285 -357 3272 -340 3264 -319 ct 3256 -298 3252 -267 3252 -227 ct +3252 0 l p ef +pom +pum +2302 10319 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +gs +pum +1284 6773 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +293 0 m 293 -439 l 360 -439 l 360 -376 l 393 -425 439 -449 500 -449 ct +527 -449 551 -444 573 -434 ct 595 -425 612 -412 623 -397 ct 634 -382 642 -363 646 -342 ct +649 -328 650 -304 650 -270 ct 650 0 l 576 0 l 576 -267 l 576 -297 573 -320 567 -335 ct +561 -350 551 -362 536 -371 ct 522 -380 504 -384 484 -384 ct 453 -384 425 -374 402 -354 ct +379 -334 368 -296 368 -239 ct 368 0 l p ef +769 168 m 769 -439 l 837 -439 l 837 -382 l 853 -404 871 -421 891 -432 ct +911 -443 936 -449 965 -449 ct 1002 -449 1035 -439 1064 -420 ct 1092 -400 1114 -373 1129 -338 ct +1143 -303 1151 -264 1151 -222 ct 1151 -177 1143 -137 1126 -101 ct 1110 -65 1087 -37 1056 -18 ct +1025 0 993 9 959 9 ct 934 9 912 4 892 -5 ct 873 -16 856 -29 844 -45 ct 844 168 l +p +837 -217 m 837 -160 848 -118 871 -91 ct 894 -64 922 -51 954 -51 ct 987 -51 1016 -65 1039 -93 ct +1063 -121 1075 -164 1075 -223 ct 1075 -279 1063 -321 1040 -349 ct 1017 -376 990 -390 958 -390 ct +926 -390 898 -376 873 -346 ct 849 -316 l 837 -273 l p ef +1507 0 m 1507 -64 l 1473 -14 1427 9 1368 9 ct 1342 9 1318 4 1295 -4 ct 1273 -14 1256 -27 1245 -42 ct +1234 -57 1227 -75 1222 -97 ct 1219 -112 1218 -135 1218 -167 ct 1218 -439 l 1292 -439 l +1292 -195 l 1292 -156 1294 -130 1297 -117 ct 1301 -97 1311 -82 1326 -70 ct +1342 -59 1360 -54 1383 -54 ct 1405 -54 1426 -59 1446 -71 ct 1465 -82 1479 -98 1487 -118 ct +1495 -137 1499 -166 1499 -203 ct 1499 -439 l 1574 -439 l 1574 0 l p ef +1858 -66 m 1869 0 l 1848 3 1829 5 1812 5 ct 1785 5 1764 1 1750 -7 ct 1735 -15 1724 -26 1718 -40 ct +1712 -54 1709 -83 1709 -128 ct 1709 -381 l 1654 -381 l 1654 -439 l 1709 -439 l +1709 -547 l 1783 -592 l 1783 -439 l 1858 -439 l 1858 -381 l 1783 -381 l +1783 -124 l 1783 -103 1784 -89 1787 -83 ct 1790 -77 1794 -72 1800 -69 ct 1806 -65 1814 -63 1825 -63 ct +1833 -63 l 1844 -64 l p ef +2190 0 m 2190 -381 l 2124 -381 l 2124 -439 l 2190 -439 l 2190 -485 l +2190 -515 2193 -537 2198 -551 ct 2205 -571 2218 -586 2236 -598 ct 2254 -610 2279 -616 2312 -616 ct +2333 -616 2356 -614 2381 -609 ct 2370 -544 l 2355 -547 2340 -548 2326 -548 ct +2304 -548 2288 -543 2278 -533 ct 2269 -524 2264 -506 2264 -479 ct 2264 -439 l +2350 -439 l 2350 -381 l 2264 -381 l 2264 0 l p ef +2410 0 m 2410 -439 l 2477 -439 l 2477 -372 l 2494 -403 2509 -424 2524 -434 ct +2538 -444 2554 -449 2572 -449 ct 2597 -449 2622 -441 2648 -425 ct 2623 -356 l +2604 -366 2586 -372 2568 -372 ct 2552 -372 2537 -367 2524 -357 ct 2511 -347 2502 -334 2496 -316 ct +2488 -290 2484 -261 2484 -229 ct 2484 0 l p ef +2674 -219 m 2674 -300 2696 -361 2741 -400 ct 2779 -432 2825 -449 2880 -449 ct +2940 -449 2989 -429 3028 -389 ct 3066 -350 3085 -295 3085 -225 ct 3085 -169 3077 -124 3060 -92 ct +3043 -60 3018 -34 2986 -16 ct 2953 0 2918 9 2880 9 ct 2818 9 2768 -9 2730 -49 ct +2693 -88 l 2674 -145 l p +2750 -219 m 2750 -163 2762 -121 2787 -93 ct 2811 -65 2842 -51 2880 -51 ct 2917 -51 2947 -65 2972 -93 ct +2996 -121 3009 -164 3009 -222 ct 3009 -276 2996 -317 2972 -345 ct 2947 -373 2916 -387 2880 -387 ct +2842 -387 2811 -373 2787 -345 ct 2762 -317 l 2750 -275 l p ef +3177 0 m 3177 -439 l 3244 -439 l 3244 -377 l 3258 -399 3276 -416 3299 -429 ct +3322 -442 3348 -449 3377 -449 ct 3410 -449 3436 -442 3457 -428 ct 3478 -415 3493 -396 3501 -372 ct +3536 -423 3581 -449 3637 -449 ct 3680 -449 3714 -437 3737 -412 ct 3761 -388 3772 -351 3772 -301 ct +3772 0 l 3698 0 l 3698 -276 l 3698 -306 3696 -327 3691 -340 ct 3686 -354 3678 -364 3665 -372 ct +3652 -380 3637 -384 3620 -384 ct 3589 -384 3564 -374 3543 -353 ct 3523 -333 3513 -300 3513 -255 ct +3513 0 l 3438 0 l 3438 -285 l 3438 -318 3432 -343 3420 -359 ct 3408 -376 3388 -384 3361 -384 ct +3340 -384 3320 -379 3302 -368 ct 3285 -357 3272 -340 3264 -319 ct 3256 -298 3252 -267 3252 -227 ct +3252 0 l p ef +pom +pum +2302 7726 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8442 7781 m 8437 7778 l 8224 7666 l 8218 7663 l 8049 7492 l 8046 7486 l +7936 7271 l 7933 7265 l 7894 7016 l 7894 7009 l 7933 6759 l 7936 6753 l +8046 6538 l 8049 6532 l 8218 6361 l 8224 6358 l 8437 6246 l 8442 6244 l +8689 6204 l 8696 6204 l 8942 6244 l 8948 6246 l 9161 6358 l 9166 6361 l +9335 6532 l 9338 6538 l 9449 6753 l 9451 6759 l 9491 7009 l 9491 7016 l +9451 7265 l 9449 7271 l 9338 7486 l 9335 7492 l 9166 7663 l 9161 7666 l +8948 7778 l 8942 7781 l 8696 7821 l 8689 7821 l 8442 7781 l p +8692 7779 m 8931 7739 l 9138 7631 l 9303 7464 l 9410 7254 l 9449 7012 l +9410 6770 l 9303 6560 l 9138 6393 l 8931 6285 l 8692 6246 l 8453 6285 l +8246 6393 l 8081 6560 l 7974 6770 l 7936 7012 l 7974 7254 l 8081 7464 l +8246 7631 l 8453 7739 l 8692 7779 l p +8174 6489 m 8204 6458 l 8411 6668 l 8618 6877 l 8825 7087 l 9032 7297 l +9240 7508 l 9210 7538 l 9002 7328 l 8795 7118 l 8588 6908 l 8380 6698 l +8174 6489 l p +8204 7538 m 8174 7509 l 8380 7298 l 8588 7088 l 8795 6878 l 9003 6668 l +9211 6458 l 9240 6489 l 9032 6699 l 8825 6909 l 8618 7119 l 8411 7329 l +8204 7538 l p ef +1 lw 0 lj 8442 7781 m 8437 7778 l 8224 7666 l 8218 7663 l 8049 7492 l +8046 7486 l 7936 7271 l 7933 7265 l 7894 7016 l 7894 7009 l 7933 6759 l +7936 6753 l 8046 6538 l 8049 6532 l 8218 6361 l 8224 6358 l 8437 6246 l +8442 6244 l 8689 6204 l 8696 6204 l 8942 6244 l 8948 6246 l 9161 6358 l +9166 6361 l 9335 6532 l 9338 6538 l 9449 6753 l 9451 6759 l 9491 7009 l +9491 7016 l 9451 7265 l 9449 7271 l 9338 7486 l 9335 7492 l 9166 7663 l +9161 7666 l 8948 7778 l 8942 7781 l 8696 7821 l 8689 7821 l 8442 7781 l +pc +8692 7779 m 8931 7739 l 9138 7631 l 9303 7464 l 9410 7254 l 9449 7012 l +9410 6770 l 9303 6560 l 9138 6393 l 8931 6285 l 8692 6246 l 8453 6285 l +8246 6393 l 8081 6560 l 7974 6770 l 7936 7012 l 7974 7254 l 8081 7464 l +8246 7631 l 8453 7739 l 8692 7779 l pc +8174 6489 m 8204 6458 l 8411 6668 l 8618 6877 l 8825 7087 l 9032 7297 l +9240 7508 l 9210 7538 l 9002 7328 l 8795 7118 l 8588 6908 l 8380 6698 l +8174 6489 l pc +8204 7538 m 8174 7509 l 8380 7298 l 8588 7088 l 8795 6878 l 9003 6668 l +9211 6458 l 9240 6489 l 9032 6699 l 8825 6909 l 8618 7119 l 8411 7329 l +8204 7538 l pc +8691 7821 m 8541 8271 l 8841 8270 l 8691 7821 l p ef +8691 8181 m 8691 12701 l ps +11531 10361 m 11381 10811 l 11681 10810 l 11531 10361 l p ef +11531 10721 m 11531 12701 l ps +gs +pum +7329 12171 t +26 -131 m 99 -142 l 103 -113 115 -90 134 -74 ct 153 -59 179 -51 213 -51 ct +247 -51 272 -58 289 -72 ct 306 -86 314 -102 314 -121 ct 314 -138 307 -151 292 -160 ct +282 -167 256 -175 216 -186 ct 161 -199 123 -211 102 -221 ct 81 -231 65 -245 54 -263 ct +43 -281 38 -301 38 -322 ct 38 -342 42 -360 51 -376 ct 60 -393 73 -407 88 -418 ct +100 -427 115 -434 135 -440 ct 155 -446 177 -449 200 -449 ct 234 -449 264 -444 290 -434 ct +317 -424 336 -410 348 -393 ct 361 -376 369 -354 374 -325 ct 301 -315 l 298 -338 288 -356 272 -368 ct +256 -381 234 -387 205 -387 ct 171 -387 146 -382 132 -370 ct 117 -359 110 -346 110 -331 ct +110 -321 113 -312 119 -305 ct 125 -297 135 -290 148 -285 ct 155 -282 177 -276 213 -266 ct +266 -252 303 -240 324 -231 ct 344 -222 361 -209 373 -192 ct 384 -175 390 -154 390 -129 ct +390 -104 383 -80 369 -58 ct 354 -37 333 -20 306 -8 ct 279 3 248 9 213 9 ct 156 9 113 -1 83 -25 ct +53 -49 l 34 -84 l p ef +453 -520 m 453 -606 l 527 -606 l 527 -520 l p +453 0 m 453 -439 l 527 -439 l 527 0 l p ef +637 0 m 637 -439 l 704 -439 l 704 -376 l 737 -425 783 -449 844 -449 ct +871 -449 895 -444 917 -434 ct 939 -425 956 -412 967 -397 ct 978 -382 986 -363 990 -342 ct +993 -328 994 -304 994 -270 ct 994 0 l 920 0 l 920 -267 l 920 -297 917 -320 911 -335 ct +905 -350 895 -362 880 -371 ct 866 -380 848 -384 828 -384 ct 797 -384 769 -374 746 -354 ct +723 -334 712 -296 712 -239 ct 712 0 l p ef +pom +gr +gs +pum +11880 12223 t +342 -160 m 415 -151 l 407 -100 387 -61 354 -32 ct 321 -4 280 9 232 9 ct 172 9 124 -9 87 -49 ct +51 -88 33 -144 33 -217 ct 33 -265 40 -306 56 -342 ct 72 -378 96 -404 128 -422 ct +160 -440 195 -449 233 -449 ct 280 -449 319 -437 350 -412 ct 380 -388 400 -354 408 -310 ct +336 -299 l 329 -328 317 -350 299 -365 ct 282 -380 260 -387 236 -387 ct 198 -387 168 -374 144 -347 ct +121 -320 109 -278 109 -220 ct 109 -161 120 -118 143 -91 ct 166 -64 195 -51 232 -51 ct +261 -51 285 -60 305 -78 ct 324 -96 l 337 -123 l p ef +451 -219 m 451 -300 473 -361 518 -400 ct 556 -432 602 -449 657 -449 ct 717 -449 766 -429 805 -389 ct +843 -350 862 -295 862 -225 ct 862 -169 854 -124 837 -92 ct 820 -60 795 -34 763 -16 ct +730 0 695 9 657 9 ct 595 9 545 -9 507 -49 ct 470 -88 l 451 -145 l p +527 -219 m 527 -163 539 -121 564 -93 ct 588 -65 619 -51 657 -51 ct 694 -51 724 -65 749 -93 ct +773 -121 786 -164 786 -222 ct 786 -276 773 -317 749 -345 ct 724 -373 693 -387 657 -387 ct +619 -387 588 -373 564 -345 ct 539 -317 l 527 -275 l p ef +926 -131 m 999 -142 l 1003 -113 1015 -90 1034 -74 ct 1053 -59 1079 -51 1113 -51 ct +1147 -51 1172 -58 1189 -72 ct 1206 -86 1214 -102 1214 -121 ct 1214 -138 1207 -151 1192 -160 ct +1182 -167 1156 -175 1116 -186 ct 1061 -199 1023 -211 1002 -221 ct 981 -231 965 -245 954 -263 ct +943 -281 938 -301 938 -322 ct 938 -342 942 -360 951 -376 ct 960 -393 973 -407 988 -418 ct +1000 -427 1015 -434 1035 -440 ct 1055 -446 1077 -449 1100 -449 ct 1134 -449 1164 -444 1190 -434 ct +1217 -424 1236 -410 1248 -393 ct 1261 -376 1269 -354 1274 -325 ct 1201 -315 l +1198 -338 1188 -356 1172 -368 ct 1156 -381 1134 -387 1105 -387 ct 1071 -387 1046 -382 1032 -370 ct +1017 -359 1010 -346 1010 -331 ct 1010 -321 1013 -312 1019 -305 ct 1025 -297 1035 -290 1048 -285 ct +1055 -282 1077 -276 1113 -266 ct 1166 -252 1203 -240 1224 -231 ct 1244 -222 1261 -209 1273 -192 ct +1284 -175 1290 -154 1290 -129 ct 1290 -104 1283 -80 1269 -58 ct 1254 -37 1233 -20 1206 -8 ct +1179 3 1148 9 1113 9 ct 1056 9 1013 -1 983 -25 ct 953 -49 l 934 -84 l p ef +pom +gr +24131 6986 m 23680 6836 l 23681 7136 l 24131 6986 l p ef +20956 6986 m 23771 6986 l ps +24131 9526 m 23680 9376 l 23681 9676 l 24131 9526 l p ef +20956 9526 m 23771 9526 l ps +gs +pum +24646 7223 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +pom +gr +gs +pum +24435 9763 t +524 -64 m 562 -39 596 -20 627 -8 ct 604 47 l 560 31 517 6 473 -27 ct 429 -2 379 10 325 10 ct +270 10 220 -2 175 -29 ct 131 -55 96 -93 72 -141 ct 48 -189 36 -243 36 -303 ct 36 -362 48 -417 72 -466 ct +97 -515 131 -552 176 -578 ct 221 -604 271 -617 326 -617 ct 382 -617 433 -603 478 -577 ct +523 -550 557 -513 580 -465 ct 604 -417 616 -363 616 -303 ct 616 -253 608 -208 593 -168 ct +578 -129 l 555 -94 l p +348 -167 m 394 -154 432 -135 462 -109 ct 509 -152 533 -217 533 -303 ct 533 -352 525 -395 508 -432 ct +491 -468 467 -497 435 -517 ct 403 -537 367 -547 327 -547 ct 267 -547 217 -527 178 -486 ct +138 -445 119 -384 119 -303 ct 119 -224 138 -163 177 -121 ct 216 -79 266 -58 327 -58 ct +355 -58 382 -63 408 -74 ct 383 -90 356 -102 328 -109 ct p ef +pom +gr +gs +pum +23747 3307 t +315 0 m 241 0 l 241 -474 l 223 -457 199 -440 170 -423 ct 141 -405 115 -393 92 -384 ct +92 -456 l 133 -476 170 -499 201 -527 ct 232 -555 254 -582 267 -608 ct 315 -608 l +p ef +897 -457 m 823 -452 l 816 -481 807 -502 795 -515 ct 775 -536 750 -547 720 -547 ct +697 -547 676 -540 658 -527 ct 634 -510 616 -485 602 -452 ct 589 -420 582 -373 581 -312 ct +599 -339 621 -360 647 -373 ct 673 -386 700 -393 729 -393 ct 778 -393 820 -375 855 -338 ct +890 -301 908 -254 908 -196 ct 908 -158 899 -123 883 -90 ct 867 -58 844 -33 815 -15 ct +787 1 754 10 718 10 ct 656 10 605 -12 566 -58 ct 527 -103 507 -178 507 -283 ct +507 -400 529 -486 572 -539 ct 610 -585 661 -608 725 -608 ct 773 -608 812 -595 842 -568 ct +873 -541 l 891 -504 l p +593 -196 m 593 -170 598 -146 609 -122 ct 620 -99 635 -81 655 -69 ct 675 -57 695 -50 717 -50 ct +748 -50 775 -63 798 -88 ct 820 -114 832 -148 832 -192 ct 832 -234 820 -267 798 -291 ct +776 -315 748 -327 714 -327 ct 680 -327 652 -315 628 -291 ct 605 -267 l 593 -235 l +p ef +952 -181 m 952 -256 l 1181 -256 l 1181 -181 l p ef +1341 0 m 1272 0 l 1272 -606 l 1346 -606 l 1346 -390 l 1378 -429 1418 -449 1467 -449 ct +1494 -449 1519 -443 1543 -432 ct 1568 -421 1587 -406 1603 -386 ct 1619 -367 1631 -343 1640 -315 ct +1648 -287 1653 -257 1653 -226 ct 1653 -150 1634 -92 1597 -51 ct 1560 -10 1515 9 1463 9 ct +1411 9 1370 -11 1341 -55 ct p +1340 -222 m 1340 -170 1347 -132 1362 -108 ct 1385 -70 1417 -51 1457 -51 ct +1489 -51 1517 -65 1541 -93 ct 1565 -121 1577 -164 1577 -220 ct 1577 -277 1565 -319 1543 -346 ct +1520 -374 1492 -387 1460 -387 ct 1428 -387 1399 -373 1376 -345 ct 1352 -317 l +1340 -276 l p ef +1723 -520 m 1723 -606 l 1797 -606 l 1797 -520 l p +1723 0 m 1723 -439 l 1797 -439 l 1797 0 l p ef +2070 -66 m 2081 0 l 2060 3 2041 5 2024 5 ct 1997 5 1976 1 1962 -7 ct 1947 -15 1936 -26 1930 -40 ct +1924 -54 1921 -83 1921 -128 ct 1921 -381 l 1866 -381 l 1866 -439 l 1921 -439 l +1921 -547 l 1995 -592 l 1995 -439 l 2070 -439 l 2070 -381 l 1995 -381 l +1995 -124 l 1995 -103 1996 -89 1999 -83 ct 2002 -77 2006 -72 2012 -69 ct 2018 -65 2026 -63 2037 -63 ct +2045 -63 l 2056 -64 l p ef +pom +pum +22596 4260 t +340 0 m 340 -55 l 312 -11 272 9 217 9 ct 182 9 150 0 121 -19 ct 92 -38 69 -65 53 -99 ct +37 -134 28 -174 28 -219 ct 28 -263 36 -302 50 -338 ct 65 -374 87 -401 116 -420 ct +145 -439 178 -449 214 -449 ct 241 -449 264 -443 285 -432 ct 306 -421 322 -406 335 -388 ct +335 -606 l 409 -606 l 409 0 l p +105 -219 m 105 -162 117 -120 141 -93 ct 164 -65 192 -51 224 -51 ct 257 -51 285 -64 307 -91 ct +330 -117 342 -158 342 -212 ct 342 -273 330 -317 307 -345 ct 284 -373 255 -387 221 -387 ct +188 -387 160 -374 138 -346 ct 116 -319 l 105 -277 l p ef +818 -54 m 790 -30 764 -14 738 -4 ct 713 5 685 9 656 9 ct 608 9 571 -1 545 -25 ct +519 -49 506 -79 506 -115 ct 506 -137 511 -156 521 -174 ct 531 -192 543 -206 559 -217 ct +575 -228 593 -236 613 -241 ct 627 -245 649 -249 679 -253 ct 739 -260 783 -268 812 -278 ct +812 -288 812 -295 812 -298 ct 812 -328 805 -349 791 -362 ct 772 -379 744 -387 706 -387 ct +671 -387 645 -381 629 -369 ct 612 -356 600 -335 592 -303 ct 519 -313 l 526 -345 536 -370 552 -389 ct +567 -408 589 -423 617 -433 ct 646 -443 679 -449 717 -449 ct 755 -449 785 -444 808 -435 ct +832 -427 849 -415 860 -402 ct 871 -389 879 -372 883 -351 ct 886 -339 887 -316 887 -283 ct +887 -184 l 887 -114 889 -71 892 -52 ct 895 -34 901 -16 911 0 ct 833 0 l 825 -15 l +820 -33 l p +812 -220 m 785 -209 744 -200 690 -192 ct 660 -187 638 -182 625 -177 ct 613 -171 603 -163 596 -153 ct +589 -142 586 -130 586 -117 ct 586 -98 593 -81 608 -68 ct 623 -55 645 -48 674 -48 ct +703 -48 728 -54 751 -67 ct 773 -79 789 -96 800 -118 ct 808 -135 812 -160 812 -193 ct +p ef +1144 -66 m 1155 0 l 1134 3 1115 5 1098 5 ct 1071 5 1050 1 1036 -7 ct 1021 -15 1010 -26 1004 -40 ct +998 -54 995 -83 995 -128 ct 995 -381 l 940 -381 l 940 -439 l 995 -439 l +995 -547 l 1069 -592 l 1069 -439 l 1144 -439 l 1144 -381 l 1069 -381 l +1069 -124 l 1069 -103 1070 -89 1073 -83 ct 1076 -77 1080 -72 1086 -69 ct 1092 -65 1100 -63 1111 -63 ct +1119 -63 l 1130 -64 l p ef +1506 -54 m 1478 -30 1452 -14 1426 -4 ct 1401 5 1373 9 1344 9 ct 1296 9 1259 -1 1233 -25 ct +1207 -49 1194 -79 1194 -115 ct 1194 -137 1199 -156 1209 -174 ct 1219 -192 1231 -206 1247 -217 ct +1263 -228 1281 -236 1301 -241 ct 1315 -245 1337 -249 1367 -253 ct 1427 -260 1471 -268 1500 -278 ct +1500 -288 1500 -295 1500 -298 ct 1500 -328 1493 -349 1479 -362 ct 1460 -379 1432 -387 1394 -387 ct +1359 -387 1333 -381 1317 -369 ct 1300 -356 1288 -335 1280 -303 ct 1207 -313 l +1214 -345 1224 -370 1240 -389 ct 1255 -408 1277 -423 1305 -433 ct 1334 -443 1367 -449 1405 -449 ct +1443 -449 1473 -444 1496 -435 ct 1520 -427 1537 -415 1548 -402 ct 1559 -389 1567 -372 1571 -351 ct +1574 -339 1575 -316 1575 -283 ct 1575 -184 l 1575 -114 1577 -71 1580 -52 ct +1583 -34 1589 -16 1599 0 ct 1521 0 l 1513 -15 l 1508 -33 l p +1500 -220 m 1473 -209 1432 -200 1378 -192 ct 1348 -187 1326 -182 1313 -177 ct +1301 -171 1291 -163 1284 -153 ct 1277 -142 1274 -130 1274 -117 ct 1274 -98 1281 -81 1296 -68 ct +1311 -55 1333 -48 1362 -48 ct 1391 -48 1416 -54 1439 -67 ct 1461 -79 1477 -96 1488 -118 ct +1496 -135 1500 -160 1500 -193 ct p ef +2070 -66 m 2081 0 l 2060 3 2041 5 2024 5 ct 1997 5 1976 1 1962 -7 ct 1947 -15 1936 -26 1930 -40 ct +1924 -54 1921 -83 1921 -128 ct 1921 -381 l 1866 -381 l 1866 -439 l 1921 -439 l +1921 -547 l 1995 -592 l 1995 -439 l 2070 -439 l 2070 -381 l 1995 -381 l +1995 -124 l 1995 -103 1996 -89 1999 -83 ct 2002 -77 2006 -72 2012 -69 ct 2018 -65 2026 -63 2037 -63 ct +2045 -63 l 2056 -64 l p ef +2118 -219 m 2118 -300 2140 -361 2185 -400 ct 2223 -432 2269 -449 2324 -449 ct +2384 -449 2433 -429 2472 -389 ct 2510 -350 2529 -295 2529 -225 ct 2529 -169 2521 -124 2504 -92 ct +2487 -60 2462 -34 2430 -16 ct 2397 0 2362 9 2324 9 ct 2262 9 2212 -9 2174 -49 ct +2137 -88 l 2118 -145 l p +2194 -219 m 2194 -163 2206 -121 2231 -93 ct 2255 -65 2286 -51 2324 -51 ct 2361 -51 2391 -65 2416 -93 ct +2440 -121 2453 -164 2453 -222 ct 2453 -276 2440 -317 2416 -345 ct 2391 -373 2360 -387 2324 -387 ct +2286 -387 2255 -373 2231 -345 ct 2206 -317 l 2194 -275 l p ef +2860 0 m 2860 -606 l 2935 -606 l 2935 -388 l 2970 -429 3013 -449 3066 -449 ct +3099 -449 3127 -442 3151 -429 ct 3175 -417 3192 -399 3203 -376 ct 3213 -354 3218 -321 3218 -278 ct +3218 0 l 3144 0 l 3144 -278 l 3144 -315 3136 -342 3119 -359 ct 3103 -376 3081 -385 3051 -385 ct +3029 -385 3008 -379 2989 -367 ct 2969 -356 2955 -340 2947 -321 ct 2939 -301 2935 -274 2935 -240 ct +2935 0 l p ef +3309 -219 m 3309 -300 3331 -361 3376 -400 ct 3414 -432 3460 -449 3515 -449 ct +3575 -449 3624 -429 3663 -389 ct 3701 -350 3720 -295 3720 -225 ct 3720 -169 3712 -124 3695 -92 ct +3678 -60 3653 -34 3621 -16 ct 3588 0 3553 9 3515 9 ct 3453 9 3403 -9 3365 -49 ct +3328 -88 l 3309 -145 l p +3385 -219 m 3385 -163 3397 -121 3422 -93 ct 3446 -65 3477 -51 3515 -51 ct 3552 -51 3582 -65 3607 -93 ct +3631 -121 3644 -164 3644 -222 ct 3644 -276 3631 -317 3607 -345 ct 3582 -373 3551 -387 3515 -387 ct +3477 -387 3446 -373 3422 -345 ct 3397 -317 l 3385 -275 l p ef +3783 -131 m 3856 -142 l 3860 -113 3872 -90 3891 -74 ct 3910 -59 3936 -51 3970 -51 ct +4004 -51 4029 -58 4046 -72 ct 4063 -86 4071 -102 4071 -121 ct 4071 -138 4064 -151 4049 -160 ct +4039 -167 4013 -175 3973 -186 ct 3918 -199 3880 -211 3859 -221 ct 3838 -231 3822 -245 3811 -263 ct +3800 -281 3795 -301 3795 -322 ct 3795 -342 3799 -360 3808 -376 ct 3817 -393 3830 -407 3845 -418 ct +3857 -427 3872 -434 3892 -440 ct 3912 -446 3934 -449 3957 -449 ct 3991 -449 4021 -444 4047 -434 ct +4074 -424 4093 -410 4105 -393 ct 4118 -376 4126 -354 4131 -325 ct 4058 -315 l +4055 -338 4045 -356 4029 -368 ct 4013 -381 3991 -387 3962 -387 ct 3928 -387 3903 -382 3889 -370 ct +3874 -359 3867 -346 3867 -331 ct 3867 -321 3870 -312 3876 -305 ct 3882 -297 3892 -290 3905 -285 ct +3912 -282 3934 -276 3970 -266 ct 4023 -252 4060 -240 4081 -231 ct 4101 -222 4118 -209 4130 -192 ct +4141 -175 4147 -154 4147 -129 ct 4147 -104 4140 -80 4126 -58 ct 4111 -37 4090 -20 4063 -8 ct +4036 3 4005 9 3970 9 ct 3913 9 3870 -1 3840 -25 ct 3810 -49 l 3791 -84 l p ef +4372 -66 m 4383 0 l 4362 3 4343 5 4326 5 ct 4299 5 4278 1 4264 -7 ct 4249 -15 4238 -26 4232 -40 ct +4226 -54 4223 -83 4223 -128 ct 4223 -381 l 4168 -381 l 4168 -439 l 4223 -439 l +4223 -547 l 4297 -592 l 4297 -439 l 4372 -439 l 4372 -381 l 4297 -381 l +4297 -124 l 4297 -103 4298 -89 4301 -83 ct 4304 -77 4308 -72 4314 -69 ct 4320 -65 4328 -63 4339 -63 ct +4347 -63 l 4358 -64 l p ef +pom +pum +23257 5213 t +177 0 m 10 -439 l 89 -439 l 183 -176 l 193 -147 203 -118 211 -87 ct 218 -110 227 -138 239 -171 ct +337 -439 l 413 -439 l 247 0 l p ef +479 -520 m 479 -606 l 553 -606 l 553 -520 l p +479 0 m 479 -439 l 553 -439 l 553 0 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -49 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -253 ct 872 -260 916 -268 945 -278 ct +945 -288 945 -295 945 -298 ct 945 -328 938 -349 924 -362 ct 905 -379 877 -387 839 -387 ct +804 -387 778 -381 762 -369 ct 745 -356 733 -335 725 -303 ct 652 -313 l 659 -345 669 -370 685 -389 ct +700 -408 722 -423 750 -433 ct 779 -443 812 -449 850 -449 ct 888 -449 918 -444 941 -435 ct +965 -427 982 -415 993 -402 ct 1004 -389 1012 -372 1016 -351 ct 1019 -339 1020 -316 1020 -283 ct +1020 -184 l 1020 -114 1022 -71 1025 -52 ct 1028 -34 1034 -16 1044 0 ct 966 0 l +958 -15 l 953 -33 l p +945 -220 m 918 -209 877 -200 823 -192 ct 793 -187 771 -182 758 -177 ct 746 -171 736 -163 729 -153 ct +722 -142 719 -130 719 -117 ct 719 -98 726 -81 741 -68 ct 756 -55 778 -48 807 -48 ct +836 -48 861 -54 884 -67 ct 906 -79 922 -96 933 -118 ct 941 -135 945 -160 945 -193 ct +p ef +1759 -606 m 1839 -606 l 1839 -256 l 1839 -195 1832 -146 1818 -110 ct 1804 -75 1780 -45 1744 -23 ct +1708 0 1660 10 1602 10 ct 1545 10 1499 0 1463 -19 ct 1426 -38 1401 -66 1385 -104 ct +1370 -141 1362 -191 1362 -256 ct 1362 -606 l 1442 -606 l 1442 -256 l 1442 -203 1447 -164 1457 -139 ct +1467 -115 1484 -95 1507 -82 ct 1531 -68 1560 -62 1595 -62 ct 1654 -62 1696 -75 1721 -102 ct +1746 -128 1759 -180 1759 -256 ct p ef +1969 -194 m 2044 -201 l 2048 -171 2056 -146 2069 -126 ct 2082 -107 2103 -91 2130 -79 ct +2158 -67 2189 -61 2223 -61 ct 2254 -61 2281 -66 2304 -75 ct 2328 -84 2345 -96 2357 -112 ct +2368 -128 2374 -145 2374 -164 ct 2374 -183 2368 -200 2357 -214 ct 2346 -228 2328 -240 2303 -250 ct +2286 -256 2250 -266 2195 -279 ct 2139 -293 2100 -305 2078 -317 ct 2049 -332 2027 -351 2013 -374 ct +1999 -396 1992 -421 1992 -449 ct 1992 -480 2000 -508 2018 -535 ct 2035 -561 2061 -582 2094 -595 ct +2127 -609 2164 -616 2205 -616 ct 2250 -616 2290 -609 2324 -594 ct 2358 -580 2385 -559 2403 -531 ct +2422 -502 2432 -471 2433 -435 ct 2356 -429 l 2352 -468 2338 -496 2314 -516 ct +2290 -536 2255 -545 2208 -545 ct 2160 -545 2125 -537 2102 -519 ct 2080 -501 2069 -480 2069 -454 ct +2069 -433 2077 -415 2093 -401 ct 2108 -387 2148 -372 2214 -357 ct 2279 -343 2324 -330 2348 -319 ct +2383 -303 2409 -282 2426 -257 ct 2443 -232 2451 -203 2451 -171 ct 2451 -138 2442 -108 2423 -80 ct +2405 -51 2378 -29 2344 -13 ct 2309 2 2270 10 2227 10 ct 2172 10 2126 2 2089 -13 ct +2052 -29 2023 -53 2002 -85 ct 1981 -117 l 1970 -154 l p ef +2576 0 m 2576 -606 l 2803 -606 l 2849 -606 2886 -600 2914 -587 ct 2942 -575 2964 -556 2980 -531 ct +2996 -505 3004 -479 3004 -451 ct 3004 -425 2997 -400 2983 -378 ct 2969 -355 2948 -336 2919 -322 ct +2956 -311 2984 -293 3004 -267 ct 3024 -241 3033 -211 3033 -175 ct 3033 -147 3027 -120 3015 -96 ct +3003 -72 2989 -53 2971 -40 ct 2953 -26 2931 -16 2905 -10 ct 2878 -3 2845 0 2807 0 ct +p +2656 -351 m 2787 -351 l 2822 -351 2848 -353 2863 -358 ct 2884 -364 2899 -374 2909 -388 ct +2920 -402 2925 -420 2925 -441 ct 2925 -461 2920 -479 2911 -494 ct 2901 -510 2887 -520 2869 -526 ct +2851 -531 2821 -534 2777 -534 ct 2656 -534 l p +2656 -71 m 2807 -71 l 2833 -71 2851 -72 2861 -74 ct 2880 -77 2895 -83 2908 -90 ct +2920 -98 2930 -109 2938 -124 ct 2946 -139 2950 -156 2950 -175 ct 2950 -198 2944 -218 2933 -234 ct +2921 -251 2905 -263 2885 -269 ct 2864 -276 2835 -279 2796 -279 ct 2656 -279 l +p ef +pom +gr +gs +pum +6825 19235 t +497 -212 m 578 -192 l 561 -126 531 -76 487 -41 ct 443 -6 390 10 327 10 ct +261 10 208 -2 167 -29 ct 126 -56 95 -94 74 -145 ct 52 -195 42 -249 42 -307 ct 42 -370 54 -425 78 -472 ct +102 -519 136 -555 181 -580 ct 225 -604 274 -616 328 -616 ct 389 -616 440 -601 481 -570 ct +522 -539 551 -496 567 -440 ct 488 -421 l 474 -465 454 -497 427 -517 ct 400 -537 367 -547 326 -547 ct +280 -547 241 -536 209 -514 ct 178 -492 156 -462 143 -424 ct 131 -386 124 -348 124 -308 ct +124 -256 132 -211 147 -173 ct 162 -134 185 -105 217 -86 ct 249 -67 283 -58 320 -58 ct +365 -58 403 -71 434 -97 ct 465 -123 l 486 -161 l p ef +991 -141 m 1068 -131 l 1056 -86 1033 -52 1001 -27 ct 968 -2 926 9 875 9 ct +811 9 760 -9 722 -49 ct 684 -88 666 -144 666 -215 ct 666 -289 685 -347 723 -387 ct +761 -428 810 -449 871 -449 ct 929 -449 977 -429 1015 -389 ct 1052 -349 1070 -292 1070 -220 ct +1070 -216 1070 -209 1070 -200 ct 742 -200 l 745 -152 759 -115 783 -89 ct 808 -64 839 -51 875 -51 ct +903 -51 926 -58 945 -72 ct 964 -87 l 980 -110 l p +747 -261 m 992 -261 l 989 -298 979 -326 964 -344 ct 940 -373 909 -387 871 -387 ct +837 -387 809 -376 785 -353 ct 762 -330 l 749 -300 l p ef +1166 0 m 1166 -439 l 1233 -439 l 1233 -376 l 1266 -425 1312 -449 1373 -449 ct +1400 -449 1424 -444 1446 -434 ct 1468 -425 1485 -412 1496 -397 ct 1507 -382 1515 -363 1519 -342 ct +1522 -328 1523 -304 1523 -270 ct 1523 0 l 1449 0 l 1449 -267 l 1449 -297 1446 -320 1440 -335 ct +1434 -350 1424 -362 1409 -371 ct 1395 -380 1377 -384 1357 -384 ct 1326 -384 1298 -374 1275 -354 ct +1252 -334 1241 -296 1241 -239 ct 1241 0 l p ef +1806 -66 m 1817 0 l 1796 3 1777 5 1760 5 ct 1733 5 1712 1 1698 -7 ct 1683 -15 1672 -26 1666 -40 ct +1660 -54 1657 -83 1657 -128 ct 1657 -381 l 1602 -381 l 1602 -439 l 1657 -439 l +1657 -547 l 1731 -592 l 1731 -439 l 1806 -439 l 1806 -381 l 1731 -381 l +1731 -124 l 1731 -103 1732 -89 1735 -83 ct 1738 -77 1742 -72 1748 -69 ct 1754 -65 1762 -63 1773 -63 ct +1781 -63 l 1792 -64 l p ef +2182 -141 m 2259 -131 l 2247 -86 2224 -52 2192 -27 ct 2159 -2 2117 9 2066 9 ct +2002 9 1951 -9 1913 -49 ct 1875 -88 1857 -144 1857 -215 ct 1857 -289 1876 -347 1914 -387 ct +1952 -428 2001 -449 2062 -449 ct 2120 -449 2168 -429 2206 -389 ct 2243 -349 2261 -292 2261 -220 ct +2261 -216 2261 -209 2261 -200 ct 1933 -200 l 1936 -152 1950 -115 1974 -89 ct +1999 -64 2030 -51 2066 -51 ct 2094 -51 2117 -58 2136 -72 ct 2155 -87 l 2171 -110 l +p +1938 -261 m 2183 -261 l 2180 -298 2170 -326 2155 -344 ct 2131 -373 2100 -387 2062 -387 ct +2028 -387 2000 -376 1976 -353 ct 1953 -330 l 1940 -300 l p ef +2357 0 m 2357 -439 l 2424 -439 l 2424 -372 l 2441 -403 2456 -424 2471 -434 ct +2485 -444 2501 -449 2519 -449 ct 2544 -449 2569 -441 2595 -425 ct 2570 -356 l +2551 -366 2533 -372 2515 -372 ct 2499 -372 2484 -367 2471 -357 ct 2458 -347 2449 -334 2443 -316 ct +2435 -290 2431 -261 2431 -229 ct 2431 0 l p ef +2904 0 m 2904 -381 l 2838 -381 l 2838 -439 l 2904 -439 l 2904 -485 l +2904 -515 2907 -537 2912 -551 ct 2919 -571 2932 -586 2950 -598 ct 2968 -610 2993 -616 3026 -616 ct +3047 -616 3070 -614 3095 -609 ct 3084 -544 l 3069 -547 3054 -548 3040 -548 ct +3018 -548 3002 -543 2992 -533 ct 2983 -524 2978 -506 2978 -479 ct 2978 -439 l +3064 -439 l 3064 -381 l 2978 -381 l 2978 0 l p ef +3124 0 m 3124 -439 l 3191 -439 l 3191 -372 l 3208 -403 3223 -424 3238 -434 ct +3252 -444 3268 -449 3286 -449 ct 3311 -449 3336 -441 3362 -425 ct 3337 -356 l +3318 -366 3300 -372 3282 -372 ct 3266 -372 3251 -367 3238 -357 ct 3225 -347 3216 -334 3210 -316 ct +3202 -290 3198 -261 3198 -229 ct 3198 0 l p ef +3716 -141 m 3793 -131 l 3781 -86 3758 -52 3726 -27 ct 3693 -2 3651 9 3600 9 ct +3536 9 3485 -9 3447 -49 ct 3409 -88 3391 -144 3391 -215 ct 3391 -289 3410 -347 3448 -387 ct +3486 -428 3535 -449 3596 -449 ct 3654 -449 3702 -429 3740 -389 ct 3777 -349 3795 -292 3795 -220 ct +3795 -216 3795 -209 3795 -200 ct 3467 -200 l 3470 -152 3484 -115 3508 -89 ct +3533 -64 3564 -51 3600 -51 ct 3628 -51 3651 -58 3670 -72 ct 3689 -87 l 3705 -110 l +p +3472 -261 m 3717 -261 l 3714 -298 3704 -326 3689 -344 ct 3665 -373 3634 -387 3596 -387 ct +3562 -387 3534 -376 3510 -353 ct 3487 -330 l 3474 -300 l p ef +4171 168 m 4171 -46 l 4160 -30 4144 -16 4123 -6 ct 4102 4 4080 9 4056 9 ct +4004 9 3959 -10 3922 -52 ct 3884 -94 3865 -151 3865 -223 ct 3865 -267 3873 -307 3888 -342 ct +3904 -377 3926 -404 3955 -422 ct 3984 -440 4016 -449 4051 -449 ct 4105 -449 4148 -426 4179 -380 ct +4179 -439 l 4246 -439 l 4246 168 l p +3942 -220 m 3942 -164 3954 -121 3977 -93 ct 4001 -65 4029 -51 4063 -51 ct 4094 -51 4122 -64 4144 -91 ct +4167 -118 4179 -159 4179 -214 ct 4179 -272 4167 -316 4143 -346 ct 4118 -375 4090 -390 4058 -390 ct +4025 -390 3998 -376 3975 -349 ct 3953 -321 l 3942 -279 l p ef +4656 0 m 4656 -64 l 4622 -14 4576 9 4517 9 ct 4491 9 4467 4 4444 -4 ct 4422 -14 4405 -27 4394 -42 ct +4383 -57 4376 -75 4371 -97 ct 4368 -112 4367 -135 4367 -167 ct 4367 -439 l 4441 -439 l +4441 -195 l 4441 -156 4443 -130 4446 -117 ct 4450 -97 4460 -82 4475 -70 ct +4491 -59 4509 -54 4532 -54 ct 4554 -54 4575 -59 4595 -71 ct 4614 -82 4628 -98 4636 -118 ct +4644 -137 4648 -166 4648 -203 ct 4648 -439 l 4723 -439 l 4723 0 l p ef +5145 -141 m 5222 -131 l 5210 -86 5187 -52 5155 -27 ct 5122 -2 5080 9 5029 9 ct +4965 9 4914 -9 4876 -49 ct 4838 -88 4820 -144 4820 -215 ct 4820 -289 4839 -347 4877 -387 ct +4915 -428 4964 -449 5025 -449 ct 5083 -449 5131 -429 5169 -389 ct 5206 -349 5224 -292 5224 -220 ct +5224 -216 5224 -209 5224 -200 ct 4896 -200 l 4899 -152 4913 -115 4937 -89 ct +4962 -64 4993 -51 5029 -51 ct 5057 -51 5080 -58 5099 -72 ct 5118 -87 l 5134 -110 l +p +4901 -261 m 5146 -261 l 5143 -298 5133 -326 5118 -344 ct 5094 -373 5063 -387 5025 -387 ct +4991 -387 4963 -376 4939 -353 ct 4916 -330 l 4903 -300 l p ef +5320 0 m 5320 -439 l 5387 -439 l 5387 -376 l 5420 -425 5466 -449 5527 -449 ct +5554 -449 5578 -444 5600 -434 ct 5622 -425 5639 -412 5650 -397 ct 5661 -382 5669 -363 5673 -342 ct +5676 -328 5677 -304 5677 -270 ct 5677 0 l 5603 0 l 5603 -267 l 5603 -297 5600 -320 5594 -335 ct +5588 -350 5578 -362 5563 -371 ct 5549 -380 5531 -384 5511 -384 ct 5480 -384 5452 -374 5429 -354 ct +5406 -334 5395 -296 5395 -239 ct 5395 0 l p ef +6083 -160 m 6156 -151 l 6148 -100 6128 -61 6095 -32 ct 6062 -4 6021 9 5973 9 ct +5913 9 5865 -9 5828 -49 ct 5792 -88 5774 -144 5774 -217 ct 5774 -265 5781 -306 5797 -342 ct +5813 -378 5837 -404 5869 -422 ct 5901 -440 5936 -449 5974 -449 ct 6021 -449 6060 -437 6091 -412 ct +6121 -388 6141 -354 6149 -310 ct 6077 -299 l 6070 -328 6058 -350 6040 -365 ct +6023 -380 6001 -387 5977 -387 ct 5939 -387 5909 -374 5885 -347 ct 5862 -320 5850 -278 5850 -220 ct +5850 -161 5861 -118 5884 -91 ct 5907 -64 5936 -51 5973 -51 ct 6002 -51 6026 -60 6046 -78 ct +6065 -96 l 6078 -123 l p ef +6217 169 m 6209 99 l 6225 103 6239 105 6251 105 ct 6268 105 6281 103 6291 97 ct +6301 92 6309 84 6315 74 ct 6320 66 6328 48 6338 19 ct 6340 14 6342 8 6345 0 ct +6178 -439 l 6258 -439 l 6350 -184 l 6362 -152 6372 -118 6382 -83 ct 6390 -117 6400 -150 6412 -183 ct +6506 -439 l 6581 -439 l 6413 7 l 6396 55 6382 88 6372 107 ct 6358 131 6343 149 6326 161 ct +6309 172 6289 178 6265 178 ct 6251 178 l 6235 175 l p ef +pom +pum +7778 20188 t +26 -181 m 26 -256 l 255 -256 l 255 -181 l p ef +364 0 m 364 -381 l 298 -381 l 298 -439 l 364 -439 l 364 -485 l 364 -515 367 -537 372 -551 ct +379 -571 392 -586 410 -598 ct 428 -610 453 -616 486 -616 ct 507 -616 530 -614 555 -609 ct +544 -544 l 529 -547 514 -548 500 -548 ct 478 -548 462 -543 452 -533 ct 443 -524 438 -506 438 -479 ct +438 -439 l 524 -439 l 524 -381 l 438 -381 l 438 0 l p ef +555 -131 m 628 -142 l 632 -113 644 -90 663 -74 ct 682 -59 708 -51 742 -51 ct +776 -51 801 -58 818 -72 ct 835 -86 843 -102 843 -121 ct 843 -138 836 -151 821 -160 ct +811 -167 785 -175 745 -186 ct 690 -199 652 -211 631 -221 ct 610 -231 594 -245 583 -263 ct +572 -281 567 -301 567 -322 ct 567 -342 571 -360 580 -376 ct 589 -393 602 -407 617 -418 ct +629 -427 644 -434 664 -440 ct 684 -446 706 -449 729 -449 ct 763 -449 793 -444 819 -434 ct +846 -424 865 -410 877 -393 ct 890 -376 898 -354 903 -325 ct 830 -315 l 827 -338 817 -356 801 -368 ct +785 -381 763 -387 734 -387 ct 700 -387 675 -382 661 -370 ct 646 -359 639 -346 639 -331 ct +639 -321 642 -312 648 -305 ct 654 -297 664 -290 677 -285 ct 684 -282 706 -276 742 -266 ct +795 -252 832 -240 853 -231 ct 873 -222 890 -209 902 -192 ct 913 -175 919 -154 919 -129 ct +919 -104 912 -80 898 -58 ct 883 -37 862 -20 835 -8 ct 808 3 777 9 742 9 ct 685 9 642 -1 612 -25 ct +582 -49 l 563 -84 l p ef +926 10 m 1101 -616 l 1161 -616 l 985 10 l p ef +1590 -71 m 1590 0 l 1189 0 l 1189 -17 1191 -35 1198 -51 ct 1208 -79 1224 -105 1247 -132 ct +1269 -158 1302 -189 1344 -224 ct 1410 -278 1455 -321 1478 -352 ct 1501 -384 1513 -413 1513 -442 ct +1513 -471 1502 -496 1481 -516 ct 1460 -537 1432 -547 1398 -547 ct 1363 -547 1334 -536 1312 -514 ct +1291 -493 1280 -463 1280 -425 ct 1203 -433 l 1208 -490 1228 -533 1262 -563 ct +1297 -593 1342 -608 1400 -608 ct 1458 -608 1504 -592 1538 -560 ct 1572 -528 1589 -488 1589 -440 ct +1589 -416 1584 -392 1574 -368 ct 1564 -345 1548 -320 1525 -294 ct 1502 -268 1463 -233 1410 -188 ct +1365 -150 1337 -125 1324 -111 ct 1311 -98 1301 -85 1293 -71 ct p ef +2097 -66 m 2108 0 l 2087 3 2068 5 2051 5 ct 2024 5 2003 1 1989 -7 ct 1974 -15 1963 -26 1957 -40 ct +1951 -54 1948 -83 1948 -128 ct 1948 -381 l 1893 -381 l 1893 -439 l 1948 -439 l +1948 -547 l 2022 -592 l 2022 -439 l 2097 -439 l 2097 -381 l 2022 -381 l +2022 -124 l 2022 -103 2023 -89 2026 -83 ct 2029 -77 2033 -72 2039 -69 ct 2045 -65 2053 -63 2064 -63 ct +2072 -63 l 2083 -64 l p ef +2145 -219 m 2145 -300 2167 -361 2212 -400 ct 2250 -432 2296 -449 2351 -449 ct +2411 -449 2460 -429 2499 -389 ct 2537 -350 2556 -295 2556 -225 ct 2556 -169 2548 -124 2531 -92 ct +2514 -60 2489 -34 2457 -16 ct 2424 0 2389 9 2351 9 ct 2289 9 2239 -9 2201 -49 ct +2164 -88 l 2145 -145 l p +2221 -219 m 2221 -163 2233 -121 2258 -93 ct 2282 -65 2313 -51 2351 -51 ct 2388 -51 2418 -65 2443 -93 ct +2467 -121 2480 -164 2480 -222 ct 2480 -276 2467 -317 2443 -345 ct 2418 -373 2387 -387 2351 -387 ct +2313 -387 2282 -373 2258 -345 ct 2233 -317 l 2221 -275 l p ef +3043 -98 m 3043 -264 l 2878 -264 l 2878 -333 l 3043 -333 l 3043 -498 l +3113 -498 l 3113 -333 l 3278 -333 l 3278 -264 l 3113 -264 l 3113 -98 l +p ef +3407 0 m 3407 -381 l 3341 -381 l 3341 -439 l 3407 -439 l 3407 -485 l +3407 -515 3410 -537 3415 -551 ct 3422 -571 3435 -586 3453 -598 ct 3471 -610 3496 -616 3529 -616 ct +3550 -616 3573 -614 3598 -609 ct 3587 -544 l 3572 -547 3557 -548 3543 -548 ct +3521 -548 3505 -543 3495 -533 ct 3486 -524 3481 -506 3481 -479 ct 3481 -439 l +3567 -439 l 3567 -381 l 3481 -381 l 3481 0 l p ef +3598 -131 m 3671 -142 l 3675 -113 3687 -90 3706 -74 ct 3725 -59 3751 -51 3785 -51 ct +3819 -51 3844 -58 3861 -72 ct 3878 -86 3886 -102 3886 -121 ct 3886 -138 3879 -151 3864 -160 ct +3854 -167 3828 -175 3788 -186 ct 3733 -199 3695 -211 3674 -221 ct 3653 -231 3637 -245 3626 -263 ct +3615 -281 3610 -301 3610 -322 ct 3610 -342 3614 -360 3623 -376 ct 3632 -393 3645 -407 3660 -418 ct +3672 -427 3687 -434 3707 -440 ct 3727 -446 3749 -449 3772 -449 ct 3806 -449 3836 -444 3862 -434 ct +3889 -424 3908 -410 3920 -393 ct 3933 -376 3941 -354 3946 -325 ct 3873 -315 l +3870 -338 3860 -356 3844 -368 ct 3828 -381 3806 -387 3777 -387 ct 3743 -387 3718 -382 3704 -370 ct +3689 -359 3682 -346 3682 -331 ct 3682 -321 3685 -312 3691 -305 ct 3697 -297 3707 -290 3720 -285 ct +3727 -282 3749 -276 3785 -266 ct 3838 -252 3875 -240 3896 -231 ct 3916 -222 3933 -209 3945 -192 ct +3956 -175 3962 -154 3962 -129 ct 3962 -104 3955 -80 3941 -58 ct 3926 -37 3905 -20 3878 -8 ct +3851 3 3820 9 3785 9 ct 3728 9 3685 -1 3655 -25 ct 3625 -49 l 3606 -84 l p ef +3969 10 m 4144 -616 l 4204 -616 l 4028 10 l p ef +4633 -71 m 4633 0 l 4232 0 l 4232 -17 4234 -35 4241 -51 ct 4251 -79 4267 -105 4290 -132 ct +4312 -158 4345 -189 4387 -224 ct 4453 -278 4498 -321 4521 -352 ct 4544 -384 4556 -413 4556 -442 ct +4556 -471 4545 -496 4524 -516 ct 4503 -537 4475 -547 4441 -547 ct 4406 -547 4377 -536 4355 -514 ct +4334 -493 4323 -463 4323 -425 ct 4246 -433 l 4251 -490 4271 -533 4305 -563 ct +4340 -593 4385 -608 4443 -608 ct 4501 -608 4547 -592 4581 -560 ct 4615 -528 4632 -488 4632 -440 ct +4632 -416 4627 -392 4617 -368 ct 4607 -345 4591 -320 4568 -294 ct 4545 -268 4506 -233 4453 -188 ct +4408 -150 4380 -125 4367 -111 ct 4354 -98 4344 -85 4336 -71 ct p ef +pom +gr +10161 16546 m 10011 16996 l 10311 16995 l 10161 16546 l p ef +10161 18381 m 10161 16906 l ps +gs +pum +2805 3466 t +38 -194 m 113 -201 l 117 -171 125 -146 138 -126 ct 151 -107 172 -91 199 -79 ct +227 -67 258 -61 292 -61 ct 323 -61 350 -66 373 -75 ct 397 -84 414 -96 426 -112 ct +437 -128 443 -145 443 -164 ct 443 -183 437 -200 426 -214 ct 415 -228 397 -240 372 -250 ct +355 -256 319 -266 264 -279 ct 208 -293 169 -305 147 -317 ct 118 -332 96 -351 82 -374 ct +68 -396 61 -421 61 -449 ct 61 -480 69 -508 87 -535 ct 104 -561 130 -582 163 -595 ct +196 -609 233 -616 274 -616 ct 319 -616 359 -609 393 -594 ct 427 -580 454 -559 472 -531 ct +491 -502 501 -471 502 -435 ct 425 -429 l 421 -468 407 -496 383 -516 ct 359 -536 324 -545 277 -545 ct +229 -545 194 -537 171 -519 ct 149 -501 138 -480 138 -454 ct 138 -433 146 -415 162 -401 ct +177 -387 217 -372 283 -357 ct 348 -343 393 -330 417 -319 ct 452 -303 478 -282 495 -257 ct +512 -232 520 -203 520 -171 ct 520 -138 511 -108 492 -80 ct 474 -51 447 -29 413 -13 ct +378 2 339 10 296 10 ct 241 10 195 2 158 -13 ct 121 -29 92 -53 71 -85 ct 50 -117 l +39 -154 l p ef +924 -54 m 896 -30 870 -14 844 -4 ct 819 5 791 9 762 9 ct 714 9 677 -1 651 -25 ct +625 -49 612 -79 612 -115 ct 612 -137 617 -156 627 -174 ct 637 -192 649 -206 665 -217 ct +681 -228 699 -236 719 -241 ct 733 -245 755 -249 785 -253 ct 845 -260 889 -268 918 -278 ct +918 -288 918 -295 918 -298 ct 918 -328 911 -349 897 -362 ct 878 -379 850 -387 812 -387 ct +777 -387 751 -381 735 -369 ct 718 -356 706 -335 698 -303 ct 625 -313 l 632 -345 642 -370 658 -389 ct +673 -408 695 -423 723 -433 ct 752 -443 785 -449 823 -449 ct 861 -449 891 -444 914 -435 ct +938 -427 955 -415 966 -402 ct 977 -389 985 -372 989 -351 ct 992 -339 993 -316 993 -283 ct +993 -184 l 993 -114 995 -71 998 -52 ct 1001 -34 1007 -16 1017 0 ct 939 0 l +931 -15 l 926 -33 l p +918 -220 m 891 -209 850 -200 796 -192 ct 766 -187 744 -182 731 -177 ct 719 -171 709 -163 702 -153 ct +695 -142 692 -130 692 -117 ct 692 -98 699 -81 714 -68 ct 729 -55 751 -48 780 -48 ct +809 -48 834 -54 857 -67 ct 879 -79 895 -96 906 -118 ct 914 -135 918 -160 918 -193 ct +p ef +1087 0 m 1087 -439 l 1154 -439 l 1154 -377 l 1168 -399 1186 -416 1209 -429 ct +1232 -442 1258 -449 1287 -449 ct 1320 -449 1346 -442 1367 -428 ct 1388 -415 1403 -396 1411 -372 ct +1446 -423 1491 -449 1547 -449 ct 1590 -449 1624 -437 1647 -412 ct 1671 -388 1682 -351 1682 -301 ct +1682 0 l 1608 0 l 1608 -276 l 1608 -306 1606 -327 1601 -340 ct 1596 -354 1588 -364 1575 -372 ct +1562 -380 1547 -384 1530 -384 ct 1499 -384 1474 -374 1453 -353 ct 1433 -333 1423 -300 1423 -255 ct +1423 0 l 1348 0 l 1348 -285 l 1348 -318 1342 -343 1330 -359 ct 1318 -376 1298 -384 1271 -384 ct +1250 -384 1230 -379 1212 -368 ct 1195 -357 1182 -340 1174 -319 ct 1166 -298 1162 -267 1162 -227 ct +1162 0 l p ef +1801 168 m 1801 -439 l 1869 -439 l 1869 -382 l 1885 -404 1903 -421 1923 -432 ct +1943 -443 1968 -449 1997 -449 ct 2034 -449 2067 -439 2096 -420 ct 2124 -400 2146 -373 2161 -338 ct +2175 -303 2183 -264 2183 -222 ct 2183 -177 2175 -137 2158 -101 ct 2142 -65 2119 -37 2088 -18 ct +2057 0 2025 9 1991 9 ct 1966 9 1944 4 1924 -5 ct 1905 -16 1888 -29 1876 -45 ct +1876 168 l p +1869 -217 m 1869 -160 1880 -118 1903 -91 ct 1926 -64 1954 -51 1986 -51 ct 2019 -51 2048 -65 2071 -93 ct +2095 -121 2107 -164 2107 -223 ct 2107 -279 2095 -321 2072 -349 ct 2049 -376 2022 -390 1990 -390 ct +1958 -390 1930 -376 1905 -346 ct 1881 -316 l 1869 -273 l p ef +2250 0 m 2250 -606 l 2324 -606 l 2324 0 l p ef +2437 -520 m 2437 -606 l 2511 -606 l 2511 -520 l p +2437 0 m 2437 -439 l 2511 -439 l 2511 0 l p ef +2621 0 m 2621 -439 l 2688 -439 l 2688 -376 l 2721 -425 2767 -449 2828 -449 ct +2855 -449 2879 -444 2901 -434 ct 2923 -425 2940 -412 2951 -397 ct 2962 -382 2970 -363 2974 -342 ct +2977 -328 2978 -304 2978 -270 ct 2978 0 l 2904 0 l 2904 -267 l 2904 -297 2901 -320 2895 -335 ct +2889 -350 2879 -362 2864 -371 ct 2850 -380 2832 -384 2812 -384 ct 2781 -384 2753 -374 2730 -354 ct +2707 -334 2696 -296 2696 -239 ct 2696 0 l p ef +3085 36 m 3157 47 l 3160 69 3169 85 3182 95 ct 3201 109 3226 116 3258 116 ct +3292 116 3319 109 3338 95 ct 3357 82 3369 62 3376 38 ct 3380 22 3381 -8 3381 -57 ct +3349 -19 3308 0 3260 0 ct 3199 0 3153 -21 3119 -65 ct 3086 -108 3070 -161 3070 -222 ct +3070 -264 3077 -302 3093 -338 ct 3108 -373 3130 -400 3159 -420 ct 3187 -439 3221 -449 3260 -449 ct +3312 -449 3355 -428 3388 -386 ct 3388 -439 l 3457 -439 l 3457 -59 l 3457 8 3450 57 3436 85 ct +3422 114 3400 136 3370 153 ct 3340 169 3303 178 3258 178 ct 3206 178 3164 166 3131 142 ct +3099 119 l 3084 83 l p +3146 -227 m 3146 -169 3158 -127 3181 -101 ct 3204 -74 3232 -61 3267 -61 ct +3301 -61 3330 -74 3353 -101 ct 3376 -127 3387 -168 3387 -224 ct 3387 -278 3376 -319 3352 -346 ct +3328 -373 3299 -387 3265 -387 ct 3232 -387 3204 -374 3181 -347 ct 3158 -320 l +3146 -280 l p ef +3812 0 m 3812 -439 l 3879 -439 l 3879 -372 l 3896 -403 3911 -424 3926 -434 ct +3940 -444 3956 -449 3974 -449 ct 3999 -449 4024 -441 4050 -425 ct 4025 -356 l +4006 -366 3988 -372 3970 -372 ct 3954 -372 3939 -367 3926 -357 ct 3913 -347 3904 -334 3898 -316 ct +3890 -290 3886 -261 3886 -229 ct 3886 0 l p ef +4390 -54 m 4362 -30 4336 -14 4310 -4 ct 4285 5 4257 9 4228 9 ct 4180 9 4143 -1 4117 -25 ct +4091 -49 4078 -79 4078 -115 ct 4078 -137 4083 -156 4093 -174 ct 4103 -192 4115 -206 4131 -217 ct +4147 -228 4165 -236 4185 -241 ct 4199 -245 4221 -249 4251 -253 ct 4311 -260 4355 -268 4384 -278 ct +4384 -288 4384 -295 4384 -298 ct 4384 -328 4377 -349 4363 -362 ct 4344 -379 4316 -387 4278 -387 ct +4243 -387 4217 -381 4201 -369 ct 4184 -356 4172 -335 4164 -303 ct 4091 -313 l +4098 -345 4108 -370 4124 -389 ct 4139 -408 4161 -423 4189 -433 ct 4218 -443 4251 -449 4289 -449 ct +4327 -449 4357 -444 4380 -435 ct 4404 -427 4421 -415 4432 -402 ct 4443 -389 4451 -372 4455 -351 ct +4458 -339 4459 -316 4459 -283 ct 4459 -184 l 4459 -114 4461 -71 4464 -52 ct +4467 -34 4473 -16 4483 0 ct 4405 0 l 4397 -15 l 4392 -33 l p +4384 -220 m 4357 -209 4316 -200 4262 -192 ct 4232 -187 4210 -182 4197 -177 ct +4185 -171 4175 -163 4168 -153 ct 4161 -142 4158 -130 4158 -117 ct 4158 -98 4165 -81 4180 -68 ct +4195 -55 4217 -48 4246 -48 ct 4275 -48 4300 -54 4323 -67 ct 4345 -79 4361 -96 4372 -118 ct +4380 -135 4384 -160 4384 -193 ct p ef +4716 -66 m 4727 0 l 4706 3 4687 5 4670 5 ct 4643 5 4622 1 4608 -7 ct 4593 -15 4582 -26 4576 -40 ct +4570 -54 4567 -83 4567 -128 ct 4567 -381 l 4512 -381 l 4512 -439 l 4567 -439 l +4567 -547 l 4641 -592 l 4641 -439 l 4716 -439 l 4716 -381 l 4641 -381 l +4641 -124 l 4641 -103 4642 -89 4645 -83 ct 4648 -77 4652 -72 4658 -69 ct 4664 -65 4672 -63 4683 -63 ct +4691 -63 l 4702 -64 l p ef +5092 -141 m 5169 -131 l 5157 -86 5134 -52 5102 -27 ct 5069 -2 5027 9 4976 9 ct +4912 9 4861 -9 4823 -49 ct 4785 -88 4767 -144 4767 -215 ct 4767 -289 4786 -347 4824 -387 ct +4862 -428 4911 -449 4972 -449 ct 5030 -449 5078 -429 5116 -389 ct 5153 -349 5171 -292 5171 -220 ct +5171 -216 5171 -209 5171 -200 ct 4843 -200 l 4846 -152 4860 -115 4884 -89 ct +4909 -64 4940 -51 4976 -51 ct 5004 -51 5027 -58 5046 -72 ct 5065 -87 l 5081 -110 l +p +4848 -261 m 5093 -261 l 5090 -298 5080 -326 5065 -344 ct 5041 -373 5010 -387 4972 -387 ct +4938 -387 4910 -376 4886 -353 ct 4863 -330 l 4850 -300 l p ef +5897 -356 m 5497 -356 l 5497 -425 l 5897 -425 l p +5897 -172 m 5497 -172 l 5497 -241 l 5897 -241 l p ef +6264 0 m 6264 -381 l 6198 -381 l 6198 -439 l 6264 -439 l 6264 -485 l +6264 -515 6267 -537 6272 -551 ct 6279 -571 6292 -586 6310 -598 ct 6328 -610 6353 -616 6386 -616 ct +6407 -616 6430 -614 6455 -609 ct 6444 -544 l 6429 -547 6414 -548 6400 -548 ct +6378 -548 6362 -543 6352 -533 ct 6343 -524 6338 -506 6338 -479 ct 6338 -439 l +6424 -439 l 6424 -381 l 6338 -381 l 6338 0 l p ef +6455 -131 m 6528 -142 l 6532 -113 6544 -90 6563 -74 ct 6582 -59 6608 -51 6642 -51 ct +6676 -51 6701 -58 6718 -72 ct 6735 -86 6743 -102 6743 -121 ct 6743 -138 6736 -151 6721 -160 ct +6711 -167 6685 -175 6645 -186 ct 6590 -199 6552 -211 6531 -221 ct 6510 -231 6494 -245 6483 -263 ct +6472 -281 6467 -301 6467 -322 ct 6467 -342 6471 -360 6480 -376 ct 6489 -393 6502 -407 6517 -418 ct +6529 -427 6544 -434 6564 -440 ct 6584 -446 6606 -449 6629 -449 ct 6663 -449 6693 -444 6719 -434 ct +6746 -424 6765 -410 6777 -393 ct 6790 -376 6798 -354 6803 -325 ct 6730 -315 l +6727 -338 6717 -356 6701 -368 ct 6685 -381 6663 -387 6634 -387 ct 6600 -387 6575 -382 6561 -370 ct +6546 -359 6539 -346 6539 -331 ct 6539 -321 6542 -312 6548 -305 ct 6554 -297 6564 -290 6577 -285 ct +6584 -282 6606 -276 6642 -266 ct 6695 -252 6732 -240 6753 -231 ct 6773 -222 6790 -209 6802 -192 ct +6813 -175 6819 -154 6819 -129 ct 6819 -104 6812 -80 6798 -58 ct 6783 -37 6762 -20 6735 -8 ct +6708 3 6677 9 6642 9 ct 6585 9 6542 -1 6512 -25 ct 6482 -49 l 6463 -84 l p ef +pom +gr +gs +pum +15981 14102 t +62 0 m 62 -606 l 289 -606 l 335 -606 372 -600 400 -587 ct 428 -575 450 -556 466 -531 ct +482 -505 490 -479 490 -451 ct 490 -425 483 -400 469 -378 ct 455 -355 434 -336 405 -322 ct +442 -311 470 -293 490 -267 ct 510 -241 519 -211 519 -175 ct 519 -147 513 -120 501 -96 ct +489 -72 475 -53 457 -40 ct 439 -26 417 -16 391 -10 ct 364 -3 331 0 293 0 ct p +142 -351 m 273 -351 l 308 -351 334 -353 349 -358 ct 370 -364 385 -374 395 -388 ct +406 -402 411 -420 411 -441 ct 411 -461 406 -479 397 -494 ct 387 -510 373 -520 355 -526 ct +337 -531 307 -534 263 -534 ct 142 -534 l p +142 -71 m 293 -71 l 319 -71 337 -72 347 -74 ct 366 -77 381 -83 394 -90 ct +406 -98 416 -109 424 -124 ct 432 -139 436 -156 436 -175 ct 436 -198 430 -218 419 -234 ct +407 -251 391 -263 371 -269 ct 350 -276 321 -279 282 -279 ct 142 -279 l p ef +898 -54 m 870 -30 844 -14 818 -4 ct 793 5 765 9 736 9 ct 688 9 651 -1 625 -25 ct +599 -49 586 -79 586 -115 ct 586 -137 591 -156 601 -174 ct 611 -192 623 -206 639 -217 ct +655 -228 673 -236 693 -241 ct 707 -245 729 -249 759 -253 ct 819 -260 863 -268 892 -278 ct +892 -288 892 -295 892 -298 ct 892 -328 885 -349 871 -362 ct 852 -379 824 -387 786 -387 ct +751 -387 725 -381 709 -369 ct 692 -356 680 -335 672 -303 ct 599 -313 l 606 -345 616 -370 632 -389 ct +647 -408 669 -423 697 -433 ct 726 -443 759 -449 797 -449 ct 835 -449 865 -444 888 -435 ct +912 -427 929 -415 940 -402 ct 951 -389 959 -372 963 -351 ct 966 -339 967 -316 967 -283 ct +967 -184 l 967 -114 969 -71 972 -52 ct 975 -34 981 -16 991 0 ct 913 0 l 905 -15 l +900 -33 l p +892 -220 m 865 -209 824 -200 770 -192 ct 740 -187 718 -182 705 -177 ct 693 -171 683 -163 676 -153 ct +669 -142 666 -130 666 -117 ct 666 -98 673 -81 688 -68 ct 703 -55 725 -48 754 -48 ct +783 -48 808 -54 831 -67 ct 853 -79 869 -96 880 -118 ct 888 -135 892 -160 892 -193 ct +p ef +1060 0 m 1060 -439 l 1127 -439 l 1127 -376 l 1160 -425 1206 -449 1267 -449 ct +1294 -449 1318 -444 1340 -434 ct 1362 -425 1379 -412 1390 -397 ct 1401 -382 1409 -363 1413 -342 ct +1416 -328 1417 -304 1417 -270 ct 1417 0 l 1343 0 l 1343 -267 l 1343 -297 1340 -320 1334 -335 ct +1328 -350 1318 -362 1303 -371 ct 1289 -380 1271 -384 1251 -384 ct 1220 -384 1192 -374 1169 -354 ct +1146 -334 1135 -296 1135 -239 ct 1135 0 l p ef +1822 0 m 1822 -55 l 1794 -11 1754 9 1699 9 ct 1664 9 1632 0 1603 -19 ct 1574 -38 1551 -65 1535 -99 ct +1519 -134 1510 -174 1510 -219 ct 1510 -263 1518 -302 1532 -338 ct 1547 -374 1569 -401 1598 -420 ct +1627 -439 1660 -449 1696 -449 ct 1723 -449 1746 -443 1767 -432 ct 1788 -421 1804 -406 1817 -388 ct +1817 -606 l 1891 -606 l 1891 0 l p +1587 -219 m 1587 -162 1599 -120 1623 -93 ct 1646 -65 1674 -51 1706 -51 ct 1739 -51 1767 -64 1789 -91 ct +1812 -117 1824 -158 1824 -212 ct 1824 -273 1812 -317 1789 -345 ct 1766 -373 1737 -387 1703 -387 ct +1670 -387 1642 -374 1620 -346 ct 1598 -319 l 1587 -277 l p ef +2094 0 m 1960 -439 l 2037 -439 l 2107 -185 l 2133 -91 l 2134 -96 2142 -126 2156 -181 ct +2226 -439 l 2302 -439 l 2368 -184 l 2390 -100 l 2415 -185 l 2490 -439 l +2563 -439 l 2425 0 l 2348 0 l 2278 -263 l 2261 -337 l 2172 0 l p ef +2596 -520 m 2596 -606 l 2670 -606 l 2670 -520 l p +2596 0 m 2596 -439 l 2670 -439 l 2670 0 l p ef +3065 0 m 3065 -55 l 3037 -11 2997 9 2942 9 ct 2907 9 2875 0 2846 -19 ct 2817 -38 2794 -65 2778 -99 ct +2762 -134 2753 -174 2753 -219 ct 2753 -263 2761 -302 2775 -338 ct 2790 -374 2812 -401 2841 -420 ct +2870 -439 2903 -449 2939 -449 ct 2966 -449 2989 -443 3010 -432 ct 3031 -421 3047 -406 3060 -388 ct +3060 -606 l 3134 -606 l 3134 0 l p +2830 -219 m 2830 -162 2842 -120 2866 -93 ct 2889 -65 2917 -51 2949 -51 ct 2982 -51 3010 -64 3032 -91 ct +3055 -117 3067 -158 3067 -212 ct 3067 -273 3055 -317 3032 -345 ct 3009 -373 2980 -387 2946 -387 ct +2913 -387 2885 -374 2863 -346 ct 2841 -319 l 2830 -277 l p ef +3419 -66 m 3430 0 l 3409 3 3390 5 3373 5 ct 3346 5 3325 1 3311 -7 ct 3296 -15 3285 -26 3279 -40 ct +3273 -54 3270 -83 3270 -128 ct 3270 -381 l 3215 -381 l 3215 -439 l 3270 -439 l +3270 -547 l 3344 -592 l 3344 -439 l 3419 -439 l 3419 -381 l 3344 -381 l +3344 -124 l 3344 -103 3345 -89 3348 -83 ct 3351 -77 3355 -72 3361 -69 ct 3367 -65 3375 -63 3386 -63 ct +3394 -63 l 3405 -64 l p ef +3495 0 m 3495 -606 l 3570 -606 l 3570 -388 l 3605 -429 3648 -449 3701 -449 ct +3734 -449 3762 -442 3786 -429 ct 3810 -417 3827 -399 3838 -376 ct 3848 -354 3853 -321 3853 -278 ct +3853 0 l 3779 0 l 3779 -278 l 3779 -315 3771 -342 3754 -359 ct 3738 -376 3716 -385 3686 -385 ct +3664 -385 3643 -379 3624 -367 ct 3604 -356 3590 -340 3582 -321 ct 3574 -301 3570 -274 3570 -240 ct +3570 0 l p ef +pom +pum +15888 15055 t +340 0 m 340 -55 l 312 -11 272 9 217 9 ct 182 9 150 0 121 -19 ct 92 -38 69 -65 53 -99 ct +37 -134 28 -174 28 -219 ct 28 -263 36 -302 50 -338 ct 65 -374 87 -401 116 -420 ct +145 -439 178 -449 214 -449 ct 241 -449 264 -443 285 -432 ct 306 -421 322 -406 335 -388 ct +335 -606 l 409 -606 l 409 0 l p +105 -219 m 105 -162 117 -120 141 -93 ct 164 -65 192 -51 224 -51 ct 257 -51 285 -64 307 -91 ct +330 -117 342 -158 342 -212 ct 342 -273 330 -317 307 -345 ct 284 -373 255 -387 221 -387 ct +188 -387 160 -374 138 -346 ct 116 -319 l 105 -277 l p ef +832 -141 m 909 -131 l 897 -86 874 -52 842 -27 ct 809 -2 767 9 716 9 ct 652 9 601 -9 563 -49 ct +525 -88 507 -144 507 -215 ct 507 -289 526 -347 564 -387 ct 602 -428 651 -449 712 -449 ct +770 -449 818 -429 856 -389 ct 893 -349 911 -292 911 -220 ct 911 -216 911 -209 911 -200 ct +583 -200 l 586 -152 600 -115 624 -89 ct 649 -64 680 -51 716 -51 ct 744 -51 767 -58 786 -72 ct +805 -87 l 821 -110 l p +588 -261 m 833 -261 l 830 -298 820 -326 805 -344 ct 781 -373 750 -387 712 -387 ct +678 -387 650 -376 626 -353 ct 603 -330 l 590 -300 l p ef +1295 -160 m 1368 -151 l 1360 -100 1340 -61 1307 -32 ct 1274 -4 1233 9 1185 9 ct +1125 9 1077 -9 1040 -49 ct 1004 -88 986 -144 986 -217 ct 986 -265 993 -306 1009 -342 ct +1025 -378 1049 -404 1081 -422 ct 1113 -440 1148 -449 1186 -449 ct 1233 -449 1272 -437 1303 -412 ct +1333 -388 1353 -354 1361 -310 ct 1289 -299 l 1282 -328 1270 -350 1252 -365 ct +1235 -380 1213 -387 1189 -387 ct 1151 -387 1121 -374 1097 -347 ct 1074 -320 1062 -278 1062 -220 ct +1062 -161 1073 -118 1096 -91 ct 1119 -64 1148 -51 1185 -51 ct 1214 -51 1238 -60 1258 -78 ct +1277 -96 l 1290 -123 l p ef +1432 -520 m 1432 -606 l 1506 -606 l 1506 -520 l p +1432 0 m 1432 -439 l 1506 -439 l 1506 0 l p ef +1616 0 m 1616 -439 l 1683 -439 l 1683 -377 l 1697 -399 1715 -416 1738 -429 ct +1761 -442 1787 -449 1816 -449 ct 1849 -449 1875 -442 1896 -428 ct 1917 -415 1932 -396 1940 -372 ct +1975 -423 2020 -449 2076 -449 ct 2119 -449 2153 -437 2176 -412 ct 2200 -388 2211 -351 2211 -301 ct +2211 0 l 2137 0 l 2137 -276 l 2137 -306 2135 -327 2130 -340 ct 2125 -354 2117 -364 2104 -372 ct +2091 -380 2076 -384 2059 -384 ct 2028 -384 2003 -374 1982 -353 ct 1962 -333 1952 -300 1952 -255 ct +1952 0 l 1877 0 l 1877 -285 l 1877 -318 1871 -343 1859 -359 ct 1847 -376 1827 -384 1800 -384 ct +1779 -384 1759 -379 1741 -368 ct 1724 -357 1711 -340 1703 -319 ct 1695 -298 1691 -267 1691 -227 ct +1691 0 l p ef +2617 -54 m 2589 -30 2563 -14 2537 -4 ct 2512 5 2484 9 2455 9 ct 2407 9 2370 -1 2344 -25 ct +2318 -49 2305 -79 2305 -115 ct 2305 -137 2310 -156 2320 -174 ct 2330 -192 2342 -206 2358 -217 ct +2374 -228 2392 -236 2412 -241 ct 2426 -245 2448 -249 2478 -253 ct 2538 -260 2582 -268 2611 -278 ct +2611 -288 2611 -295 2611 -298 ct 2611 -328 2604 -349 2590 -362 ct 2571 -379 2543 -387 2505 -387 ct +2470 -387 2444 -381 2428 -369 ct 2411 -356 2399 -335 2391 -303 ct 2318 -313 l +2325 -345 2335 -370 2351 -389 ct 2366 -408 2388 -423 2416 -433 ct 2445 -443 2478 -449 2516 -449 ct +2554 -449 2584 -444 2607 -435 ct 2631 -427 2648 -415 2659 -402 ct 2670 -389 2678 -372 2682 -351 ct +2685 -339 2686 -316 2686 -283 ct 2686 -184 l 2686 -114 2688 -71 2691 -52 ct +2694 -34 2700 -16 2710 0 ct 2632 0 l 2624 -15 l 2619 -33 l p +2611 -220 m 2584 -209 2543 -200 2489 -192 ct 2459 -187 2437 -182 2424 -177 ct +2412 -171 2402 -163 2395 -153 ct 2388 -142 2385 -130 2385 -117 ct 2385 -98 2392 -81 2407 -68 ct +2422 -55 2444 -48 2473 -48 ct 2502 -48 2527 -54 2550 -67 ct 2572 -79 2588 -96 2599 -118 ct +2607 -135 2611 -160 2611 -193 ct p ef +2943 -66 m 2954 0 l 2933 3 2914 5 2897 5 ct 2870 5 2849 1 2835 -7 ct 2820 -15 2809 -26 2803 -40 ct +2797 -54 2794 -83 2794 -128 ct 2794 -381 l 2739 -381 l 2739 -439 l 2794 -439 l +2794 -547 l 2868 -592 l 2868 -439 l 2943 -439 l 2943 -381 l 2868 -381 l +2868 -124 l 2868 -103 2869 -89 2872 -83 ct 2875 -77 2879 -72 2885 -69 ct 2891 -65 2899 -63 2910 -63 ct +2918 -63 l 2929 -64 l p ef +3019 -520 m 3019 -606 l 3093 -606 l 3093 -520 l p +3019 0 m 3019 -439 l 3093 -439 l 3093 0 l p ef +3177 -219 m 3177 -300 3199 -361 3244 -400 ct 3282 -432 3328 -449 3383 -449 ct +3443 -449 3492 -429 3531 -389 ct 3569 -350 3588 -295 3588 -225 ct 3588 -169 3580 -124 3563 -92 ct +3546 -60 3521 -34 3489 -16 ct 3456 0 3421 9 3383 9 ct 3321 9 3271 -9 3233 -49 ct +3196 -88 l 3177 -145 l p +3253 -219 m 3253 -163 3265 -121 3290 -93 ct 3314 -65 3345 -51 3383 -51 ct 3420 -51 3450 -65 3475 -93 ct +3499 -121 3512 -164 3512 -222 ct 3512 -276 3499 -317 3475 -345 ct 3450 -373 3419 -387 3383 -387 ct +3345 -387 3314 -373 3290 -345 ct 3265 -317 l 3253 -275 l p ef +3680 0 m 3680 -439 l 3747 -439 l 3747 -376 l 3780 -425 3826 -449 3887 -449 ct +3914 -449 3938 -444 3960 -434 ct 3982 -425 3999 -412 4010 -397 ct 4021 -382 4029 -363 4033 -342 ct +4036 -328 4037 -304 4037 -270 ct 4037 0 l 3963 0 l 3963 -267 l 3963 -297 3960 -320 3954 -335 ct +3948 -350 3938 -362 3923 -371 ct 3909 -380 3891 -384 3871 -384 ct 3840 -384 3812 -374 3789 -354 ct +3766 -334 3755 -296 3755 -239 ct 3755 0 l p ef +pom +pum +16087 16008 t +73 0 m 73 -381 l 7 -381 l 7 -439 l 73 -439 l 73 -485 l 73 -515 76 -537 81 -551 ct +88 -571 101 -586 119 -598 ct 137 -610 162 -616 195 -616 ct 216 -616 239 -614 264 -609 ct +253 -544 l 238 -547 223 -548 209 -548 ct 187 -548 171 -543 161 -533 ct 152 -524 147 -506 147 -479 ct +147 -439 l 233 -439 l 233 -381 l 147 -381 l 147 0 l p ef +580 -54 m 552 -30 526 -14 500 -4 ct 475 5 447 9 418 9 ct 370 9 333 -1 307 -25 ct +281 -49 268 -79 268 -115 ct 268 -137 273 -156 283 -174 ct 293 -192 305 -206 321 -217 ct +337 -228 355 -236 375 -241 ct 389 -245 411 -249 441 -253 ct 501 -260 545 -268 574 -278 ct +574 -288 574 -295 574 -298 ct 574 -328 567 -349 553 -362 ct 534 -379 506 -387 468 -387 ct +433 -387 407 -381 391 -369 ct 374 -356 362 -335 354 -303 ct 281 -313 l 288 -345 298 -370 314 -389 ct +329 -408 351 -423 379 -433 ct 408 -443 441 -449 479 -449 ct 517 -449 547 -444 570 -435 ct +594 -427 611 -415 622 -402 ct 633 -389 641 -372 645 -351 ct 648 -339 649 -316 649 -283 ct +649 -184 l 649 -114 651 -71 654 -52 ct 657 -34 663 -16 673 0 ct 595 0 l 587 -15 l +582 -33 l p +574 -220 m 547 -209 506 -200 452 -192 ct 422 -187 400 -182 387 -177 ct 375 -171 365 -163 358 -153 ct +351 -142 348 -130 348 -117 ct 348 -98 355 -81 370 -68 ct 385 -55 407 -48 436 -48 ct +465 -48 490 -54 513 -67 ct 535 -79 551 -96 562 -118 ct 570 -135 574 -160 574 -193 ct +p ef +1030 -160 m 1103 -151 l 1095 -100 1075 -61 1042 -32 ct 1009 -4 968 9 920 9 ct +860 9 812 -9 775 -49 ct 739 -88 721 -144 721 -217 ct 721 -265 728 -306 744 -342 ct +760 -378 784 -404 816 -422 ct 848 -440 883 -449 921 -449 ct 968 -449 1007 -437 1038 -412 ct +1068 -388 1088 -354 1096 -310 ct 1024 -299 l 1017 -328 1005 -350 987 -365 ct +970 -380 948 -387 924 -387 ct 886 -387 856 -374 832 -347 ct 809 -320 797 -278 797 -220 ct +797 -161 808 -118 831 -91 ct 854 -64 883 -51 920 -51 ct 949 -51 973 -60 993 -78 ct +1012 -96 l 1025 -123 l p ef +1329 -66 m 1340 0 l 1319 3 1300 5 1283 5 ct 1256 5 1235 1 1221 -7 ct 1206 -15 1195 -26 1189 -40 ct +1183 -54 1180 -83 1180 -128 ct 1180 -381 l 1125 -381 l 1125 -439 l 1180 -439 l +1180 -547 l 1254 -592 l 1254 -439 l 1329 -439 l 1329 -381 l 1254 -381 l +1254 -124 l 1254 -103 1255 -89 1258 -83 ct 1261 -77 1265 -72 1271 -69 ct 1277 -65 1285 -63 1296 -63 ct +1304 -63 l 1315 -64 l p ef +1377 -219 m 1377 -300 1399 -361 1444 -400 ct 1482 -432 1528 -449 1583 -449 ct +1643 -449 1692 -429 1731 -389 ct 1769 -350 1788 -295 1788 -225 ct 1788 -169 1780 -124 1763 -92 ct +1746 -60 1721 -34 1689 -16 ct 1656 0 1621 9 1583 9 ct 1521 9 1471 -9 1433 -49 ct +1396 -88 l 1377 -145 l p +1453 -219 m 1453 -163 1465 -121 1490 -93 ct 1514 -65 1545 -51 1583 -51 ct 1620 -51 1650 -65 1675 -93 ct +1699 -121 1712 -164 1712 -222 ct 1712 -276 1699 -317 1675 -345 ct 1650 -373 1619 -387 1583 -387 ct +1545 -387 1514 -373 1490 -345 ct 1465 -317 l 1453 -275 l p ef +1881 0 m 1881 -439 l 1948 -439 l 1948 -372 l 1965 -403 1980 -424 1995 -434 ct +2009 -444 2025 -449 2043 -449 ct 2068 -449 2093 -441 2119 -425 ct 2094 -356 l +2075 -366 2057 -372 2039 -372 ct 2023 -372 2008 -367 1995 -357 ct 1982 -347 1973 -334 1967 -316 ct +1959 -290 1955 -261 1955 -229 ct 1955 0 l p ef +2802 -356 m 2402 -356 l 2402 -425 l 2802 -425 l p +2802 -172 m 2402 -172 l 2402 -241 l 2802 -241 l p ef +3160 0 m 3160 -606 l 3242 -606 l 3561 -130 l 3561 -606 l 3638 -606 l +3638 0 l 3555 0 l 3237 -476 l 3237 0 l p ef +pom +gr +17781 10461 m 17631 10911 l 17931 10910 l 17781 10461 l p ef +17781 13336 m 17781 10821 l ps +gs +pum +17357 3466 t +73 0 m 73 -381 l 7 -381 l 7 -439 l 73 -439 l 73 -485 l 73 -515 76 -537 81 -551 ct +88 -571 101 -586 119 -598 ct 137 -610 162 -616 195 -616 ct 216 -616 239 -614 264 -609 ct +253 -544 l 238 -547 223 -548 209 -548 ct 187 -548 171 -543 161 -533 ct 152 -524 147 -506 147 -479 ct +147 -439 l 233 -439 l 233 -381 l 147 -381 l 147 0 l p ef +264 -131 m 337 -142 l 341 -113 353 -90 372 -74 ct 391 -59 417 -51 451 -51 ct +485 -51 510 -58 527 -72 ct 544 -86 552 -102 552 -121 ct 552 -138 545 -151 530 -160 ct +520 -167 494 -175 454 -186 ct 399 -199 361 -211 340 -221 ct 319 -231 303 -245 292 -263 ct +281 -281 276 -301 276 -322 ct 276 -342 280 -360 289 -376 ct 298 -393 311 -407 326 -418 ct +338 -427 353 -434 373 -440 ct 393 -446 415 -449 438 -449 ct 472 -449 502 -444 528 -434 ct +555 -424 574 -410 586 -393 ct 599 -376 607 -354 612 -325 ct 539 -315 l 536 -338 526 -356 510 -368 ct +494 -381 472 -387 443 -387 ct 409 -387 384 -382 370 -370 ct 355 -359 348 -346 348 -331 ct +348 -321 351 -312 357 -305 ct 363 -297 373 -290 386 -285 ct 393 -282 415 -276 451 -266 ct +504 -252 541 -240 562 -231 ct 582 -222 599 -209 611 -192 ct 622 -175 628 -154 628 -129 ct +628 -104 621 -80 607 -58 ct 592 -37 571 -20 544 -8 ct 517 3 486 9 451 9 ct 394 9 351 -1 321 -25 ct +291 -49 l 272 -84 l p ef +635 10 m 810 -616 l 870 -616 l 694 10 l p ef +937 0 m 937 -606 l 1019 -606 l 1338 -130 l 1338 -606 l 1415 -606 l +1415 0 l 1332 0 l 1014 -476 l 1014 0 l p ef +pom +gr +22227 6350 m 22199 5876 l 21920 5987 l 22227 6350 l p ef +19422 3175 m 19475 3175 l ps +19528 3175 m 19581 3175 l ps +19634 3175 m 19687 3175 l ps +19740 3175 m 19793 3175 l ps +19846 3175 m 19899 3175 l ps +19952 3175 m 20006 3175 l ps +20059 3175 m 20112 3175 l ps +20165 3175 m 20218 3175 l ps +20271 3175 m 20324 3175 l ps +20377 3175 m 20430 3175 l ps +20483 3175 m 20536 3175 l ps +20590 3175 m 20643 3175 l ps +20696 3175 m 20749 3175 l ps +20802 3175 m 20855 3175 l ps +20908 3175 m 20956 3175 l ps +20956 3175 m 20958 3180 l ps +20977 3229 m 20997 3278 l ps +21017 3328 m 21037 3377 l ps +21056 3426 m 21076 3475 l ps +21096 3525 m 21115 3574 l ps +21135 3623 m 21155 3673 l ps +21175 3722 m 21194 3771 l ps +21214 3821 m 21234 3870 l ps +21254 3919 m 21273 3968 l ps +21293 4018 m 21313 4067 l ps +21332 4116 m 21352 4166 l ps +21372 4215 m 21392 4264 l ps +21411 4313 m 21431 4363 l ps +21451 4412 m 21471 4461 l ps +21490 4511 m 21510 4560 l ps +21530 4609 m 21550 4658 l ps +21569 4708 m 21589 4757 l ps +21609 4806 m 21628 4856 l ps +21648 4905 m 21668 4954 l ps +21688 5003 m 21707 5053 l ps +21727 5102 m 21747 5151 l ps +21767 5201 m 21786 5250 l ps +21806 5299 m 21826 5348 l ps +21845 5398 m 21865 5447 l ps +21885 5496 m 21905 5546 l ps +21924 5595 m 21944 5644 l ps +21964 5693 m 21984 5743 l ps +22003 5792 m 22023 5841 l ps +22043 5891 m 22063 5940 l ps +22082 5989 m 22093 6015 l ps +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/usrp/doc/ddc.png b/usrp/doc/ddc.png new file mode 100644 index 00000000..ce35bc2a Binary files /dev/null and b/usrp/doc/ddc.png differ diff --git a/usrp/doc/other/Makefile.am b/usrp/doc/other/Makefile.am new file mode 100644 index 00000000..c10311e6 --- /dev/null +++ b/usrp/doc/other/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + mainpage.dox diff --git a/usrp/doc/other/mainpage.dox b/usrp/doc/other/mainpage.dox new file mode 100644 index 00000000..56068cc5 --- /dev/null +++ b/usrp/doc/other/mainpage.dox @@ -0,0 +1,9 @@ +/*! \mainpage + +The top level interfaces to the USRP are usrp_standard_rx and +usrp_standard_tx. Also take a look at their base classes, +usrp_basic_rx, usrp_basic_tx and usrp_basic. + +See also USRP User's and Developer's Guide + +*/ diff --git a/usrp/doc/usrp-block-diagram.eps b/usrp/doc/usrp-block-diagram.eps new file mode 100644 index 00000000..190b9dee --- /dev/null +++ b/usrp/doc/usrp-block-diagram.eps @@ -0,0 +1,2785 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFE300707800000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFE380E1FE00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C001C0C30700000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E1830300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E3820300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00077000300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0003E000300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0001C000700000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFC01C000E00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFC03E001C00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00037003800000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0006700F000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E381C000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C001C1C18000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00180C30000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00380E7FF00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0070077FF00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300701F80FF80007C00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300707FE0FFE000FF00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300706070C060018380000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070E038C030010180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070C000C030030180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070E000C030000180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300707C00C070000380000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300703FC0FFE0000300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000003007007E0FFC0000700000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000003007000F0FFF0000E00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300700038C030003C00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030071C018C038007000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000038061C018C01800E000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000018060E038C03801C000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000001C0E0F070C070018000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000FFC07FE0FFF003FF80000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000007F001FC0FFC003FF80000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080007E00000000000000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08001FF80000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800381C0000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800700C0000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800600E03808E07C8C0E03180E023000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0000FE0FF8FCFE3F83183F83F800000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0001C70F3C30FC71C31871C3F000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0003038E0C30E0E0E318E0E38000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0003018C0C30C0C06318C0630000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0007018C0C30C0C06318FFE30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0007018C0C30C0C07318FFE30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0067018C0C30C0C07318C0030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800600E7018C0C30C0C06318C0030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800700C3038C0C30C0C06318C0630000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800381C3830C0C30C0E0E318E0E30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08001FF81FF0C0C3CC07FC3187FC30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080007E00FC0C0C1CC01F03181F030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%007FFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000000FFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000010000 +%004000000000000000000000000000020000040000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000200000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000400000000000000000000 +%004000000000000000000000000000020000000000000000000001000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000C000000000000000000000 +%004000000000000000000000000000020000000000000000000000180000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000010000000000000000000000 +%004000000000000000000000000000020000000000000000000000040000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000020001C03FF800FE0000000000 +%00400000000000000000000000000002000000000003C03FF001FE000200000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000040001E03FFC03FF8000000000 +%00400000000000000000000000000002000000000003C03FFC03FF000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000360300E07038000000000 +%00400000000000000000000000000002000000000003C0301C0703800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000036030060601C000000000 +%0040000000000000000000000000000200000000000760300E0E01800040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000073030070C00C000000000 +%004000000000000000000000000000020000000000066030060C01C00020000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000063030030C000000000000 +%004000000000000000000000000000020000000000067030071C00000010000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000063830031C000000000000 +%0040000000000000000000000000000200000000000C3030071800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000E1830031C00000000FFFF +%FFC0000000000000000000000000000200000000000C3030031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400200000C1830031C00000000FFFF +%FFC0000000000000000000000000000200000000001C1830031800000003FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000C1C30031C000000000000 +%00400000000000000000000000000003FFFFF800001C1830031800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFC30030C000000000000 +%0040000000000000000000000000000200000000001FFC30071800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFE30070C00C000000000 +%0040000000000000000000000000000200000000003FFC30061C00C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380630070E00C000000000 +%004000000000000000000000000000020000000000300E30060C01C00000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400020003006300E0701C000000000 +%004000000000000000000000000000020000000000300E300E0E03800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400010003007301E07838000000000 +%0040000000000000000000000000000200000000006006301C0707800040000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000070033FF801FF0000000000 +%00400000000000000000000000000002000000000060073FF803FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400004006003BFE0007C0000000000 +%004000000000000000000000000000020000000000E0033FE000FC000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000400000000000000000000000 +%004000000000000000000000000000020000000000000000000000001000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000003FF800000000003000000000000000000400000080000000000000000000000 +%00400000000000000000000000000002000000000000000000000000800000008000000000003F +%F800000000003000000000000000000400 +%0008000000000003FFC00000000003000000000000000000400000040000000000000000000000 +%00400000000000000000000000000002000000000000000000000001000000008000000000003F +%FC00000000003000000000000000000400 +%000800000000000300E00000000002000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000038 +%0E00000000002000000000000000000400 +%000800000000000300600000000000000000000000000000400000018000000000000000000000 +%0040000000000000000000000000000200000000000000000000000C0000000080000000000030 +%0700000000000000000000000000000400 +%000800000000000300700000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000100000000080000000000030 +%0700000000000000000000000000000400 +%00080000000000030070FE03F03F0330187E000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000030 +%0707E03F03F8338187F000000000000400 +%00080000000000030061EF073873833838E7000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000030 +%070E7073873C31818E7800000000000400 +%000800000000000301E1830E1CE0C3183181800000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000038 +%1E1838E0CE0C31831C1800000000000400 +%0008000000000003FF83018C0CC0E3183181C00000000000400000000400000000000000000000 +%00400000000000000000000000000002000000000000000000000100000000008000000000003F +%FC3018C0CC0631C3180C00000000000400 +%0008000000000003FE03019C01C0E30C6381C00000000000400000000200000000000000000000 +%00400000000000000000000000000002000000000000000000000200000000008000000000003F +%F03018C00C0630C3181C00000000000400 +%00080000000000030703FF9C01FFE30C63FFC00000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000030 +%383FF8C00FFE30C61FFC00000000000400 +%00080000000000030383001C01C0030C6380000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000030 +%183000C00C003066180000000000000400 +%000800000000000301C3001C01C00306C380000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000030 +%1C3000C00C003066180000000000000400 +%000800000000000300E3018C0CC04306C181800000000000400000000000000000000000010000 +%004000000000000000000000000000020000040000000000000000000000000080000000000030 +%0E3818C0CC06306C180C00000000000400 +%000800000000000300E1838E1CE0C307C1C1800000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%071838E0CE0E303C1C1C00000000000400 +%00080000000000030071E7073873C30380E7800000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%071E707387BC30380F7800000000000400 +%00080000000000030030FE03F03F8303807F000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%0387E03F03F8303807F000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800FFC0000000000030000000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFC00000000 +%00030000000000C0000000000000C00400 +%000800FFF000000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF00000000 +%0003000C000000C0000000000000C00400 +%000800E07800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E0780000000 +%0003000C000000C0000000000000C00400 +%000800E01800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C0000000 +%0003000C000000C0000000000000C00400 +%000800E01C00000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00C0000000 +%0003000E000000C0000000000000C00400 +%000800E00C1FC38183FC37E3F0FC1FCDF03F81FE1FC7FC00400000000000000000000000010000 +%0040000000000000000000000000000200000400000000000000000000000000800E00C1FE1818 +%3FE37E1F0FC0FCDF01FC0FE1FC7EC00400 +%000800E00C39E381873C3CE0C1CE1FCF3879C3CF1F8E7C00400000000020000000000000000000 +%0040000000000000000000000000000200000000000000000000200000000000800E00E38E1818 +%73E3EF0C1CF0FCFB879E1CF1F8E7C00400 +%000800E00E7063818C1C3870C3031C0E1C60E3031C1C3C00400000000040000000000000000000 +%0040000000000000000000000000000200000000000000000000100000000000800E00E3071818 +%E1E3830C3030E0E1C6063831C1C1C00400 +%000800E00E0063818C0C3030C7031C0C0CC0600318181C00400000000100000000000000000000 +%0040000000000000000000000000000200000000000000000000040000000000800E00E0071818 +%C0E3030C3038C0C0CE070031C181C00400 +%000800E00E006381980C3030C7039C0C0CC0700718181C00400000000200000000000000000000 +%0040000000000000000000000000000200000000000000000000020000000000800E00E0071818 +%C0E3030C7038C0C0CC0300718180C00400 +%000800E00C1FE381980C3030C7FF9C0C0CC030FF18381C00400000000400000000000000000000 +%0040000000000000000000000000000200000000000000000000010000000000800E00E0FF1819 +%C0E3030C7FF8C0C0EC030FF18180C00400 +%000800E00C3E6381980C3030C7001C0C0CC033E318381C00400000000800000000000000000000 +%0040000000000000000000000000000200000000000000000000008000000000800E00E3E71819 +%C0E3030C7000C0C0EC031E318180C00400 +%000800E00C7063839C0C3030C6001C0C0CC0730318181C00400000001000000000000000000000 +%0040000000000000000000000000000200000000000000000000004000000000800E00C7071818 +%C0E3030C7000C0C0CC0330318180C00400 +%000800E01C6063838C0C3030C7031C0C0CE0670318181C00400000002000000000000000000000 +%0040000000000000000000000000000200000000000000000000002000000000800E01C6071838 +%C0E3030C3030C0C0CE0730318181C00400 +%000800E03860E1878C1C3030C3871C0E1860E707181C3C00400000008000000000000000000000 +%0040000000000000000000000000000200000000000000000000001800000000800E0386071838 +%E1E3030C3830C0E1C706307180C1C00400 +%000800FFF071E1FF877C3030F1CE1C0F3879C39F180E7C00400000010000000000000000000000 +%0040000000000000000000000000000200000000000000000000000400000000800FFF039F1FF8 +%73E3030F1EF0C0FB839E39F180F7C00400 +%000800FFE03F30F983EC303070FC1C0DF01F81FB1807FC00400000020000000000000000000000 +%0040000000000000000000000000000200000000000000000000000200000000800FFE03F30FD8 +%3FE303078FE0C0DF01F81FB9807EC00400 +%0008000000000000000C0000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%00E0000000000000000000000000000400 +%0008000000000000080C0000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%C0C0000000000000000000000000000400 +%00080000000000000C1C0000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%E1C0000000000000000000000000000400 +%000800000000000007F80000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%7F80000000000000000000000000000400 +%000800000000000003E00000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%1E00000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000020001C03FF801FE0000000000 +%00400000000000000000000000000002000000000003C03FF801FE000200000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000040001E03FFC03FF8000000000 +%00400000000000000000000000000002000000000003C03FFC03FF000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000360300E07018000000000 +%00400000000000000000000000000002000000000003E0301C0703800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000036030070E01C000000000 +%0040000000000000000000000000000200000000000660300E0E01800040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000073030070C00C000000000 +%004000000000000000000000000000020000000000066030060C00800020000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000063030030C000000000000 +%004000000000000000000000000000020000000000067030071C00000010000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040010000063830031C000000000000 +%0040000000000000000000000000000200000000000C3030031800000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000E1830031C00000000FFFF +%FFC0000000000000000000000000000200000000000C3830031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000C1C30031C00000000FFFF +%FFC0000000000000000000000000000200000800001C1830031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400200000C1C30031C000000000000 +%00400000000000000000000000000003FFFFF800001C1830031800000002000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFC30030C000000000000 +%0040000000000000000000000000000200000000001FFC30071C00000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFE30070C00C000000000 +%0040000000000000000000000000000200000000003FFC30060C00C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380630070E00C000000000 +%004000000000000000000000000000020000000000300E30060C01C00000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400020003007300E0701C000000000 +%004000000000000000000000000000020000000000300E300E0E03800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003007383C03C78000000000 +%0040000000000000000000000000000200000000006006303C0787000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000070033FF801FF0000000000 +%00400000000000000000000000000002000000000060073FF803FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400004006003BFE0007C0000000000 +%004000000000000000000000000000020000000000E0033FE000F8000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000400000000000000000000000 +%004000000000000000000000000000020000000000000000000000001000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000018000000000000000000000 +%0040000000000000000000000000000200000000000000000000000C0000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000004000000000000000000000 +%004000000000000000000000000000020000000000000000000000100000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000400000000000000000000 +%004000000000000000000000000000020000000000000000000001000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000200000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000FFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF9FF8007C001C000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF9FFE01FF801C000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007001C0F0383C03E000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C070700C036000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C030E00C036000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C030C000063000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C031C000063000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007001C071C0000E3800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF1FFE1C0FE0C1800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FE1FFC1C0FE0C1800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C001C00E1FFC00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000C0061FFC00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000C006380E00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000E006300600000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000781E300700000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C0003FFC700700000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C0000FF0600300000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000007FFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000008000000000000000000000 +%004000000000000000000000000000020000000000000000000000080000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000010000000000000000000000 +%004000000000000000000000000000020000000000000000000000040000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001003FE00060007C0000000000 +%0040000000000000000000000000000200000000003FE000E00078000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002003FF800F001FF0000000000 +%0040000000000000000000000000000200000000003FF800E001FE000200000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000400383E00F003C78000000000 +%004000000000000000000000000000020000000000303C01E00787000100000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000800380E01F80701C000000000 +%004000000000000000000000000000020000000000300E01B00E03800080000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380701980E00C000000000 +%004000000000000000000000000000020000000000300601B00C01C00040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000380301980C008000000000 +%004000000000000000000000000000020000000000300703181C00800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400080003803039C0C000000000000 +%004000000000000000000000000000020000000000300303181C00000008000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400100003803830C1C000000000000 +%0040000000000000000000000000000200000000003003071C1800000004000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003803830C1C000000008000 +%0040000000000000000000000000000200000800003003060C1800000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFC0000380386061C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040020000380387FE1C000000000000 +%00400000000000000000000000000002000000000030030FFE1800000002000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038030FFF0C000000000000 +%00400000000000000000000000000002000000000030070FFE1C00000004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000C00038030C030C00C000000000 +%00400000000000000000000000000002000000000030061C070C00C00018000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038070C030E01C000000000 +%004000000000000000000000000000020000000000300618030E01C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380E1C038701C000000000 +%004000000000000000000000000000020000000000300E18038703800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400008003FFC180183FF8000000000 +%0040000000000000000000000000000200000000003FFC380387FF000080000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003FF83801C1FE0000000000 +%0040000000000000000000000000000200000000003FF8300181FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000007FFE00000000000000000C100000000000400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800000000003FF +%E00000000000000000C100000000000400 +%000800000000003FFE00000000000000000C300000000000400000004000000000000000000000 +%0040000000000000000000000000000200000000000000000000001000000000800000000003FF +%E00000000000000000C300000000000400 +%0008000000000001C0000000000000000000300000000000400000002000000000000000000000 +%00400000000000000000000000000002000000000000000000000020000000008000000000000C +%0000000000000000000300000000000400 +%0008000000000001C0000000000000000000300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0000000000000000000300000000000400 +%0008000000000001C0670F833C03C19E1C0CFC0000000000400000000800000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0270F811C03C09E1C0CFC0000000000400 +%0008000000000001C07F3FE3FF0FE1FF7F0CFC0000000000400000000400000000000000000000 +%00400000000000000000000000000002000000000000000000000100000000008000000000000C +%07F1FE1FF0FF1FF3F0CFC0000000000400 +%0008000000000001C07A30E3C31C31E3C70C300000000000400000000100000000000000000000 +%00400000000000000000000000000002000000000000000000000400000000008000000000000C +%0783061C38C31E3E30C300000000000400 +%0008000000000001C0707063839831C1830C300000000000400000000080000000000000000000 +%00400000000000000000000000000002000000000000000000000800000000008000000000000C +%0703071819C11C1C38C300000000000400 +%0008000000000001C0700063819C01C1830C300000000000400000000040000000000000000000 +%00400000000000000000000000000002000000000000000000001000000000008000000000000C +%0700071819C01C1818C300000000000400 +%0008000000000001C06003E3818F8181830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%07001F1818F81C1818C300000000000400 +%0008000000000001C0603FE38187F181830C30000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC000000000008000000000000C +%0701FF18187F1C1818C300000000000400 +%0008000000000001C06078638180F181830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0703C718180F9C1818C300000000000400 +%0008000000000001C060606381803981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0707071818019C1818C300000000000400 +%0008000000000001C060606381981981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0706071819819C1818C300000000000400 +%0008000000000001C06060E3819C3981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%07070F1819C39C1818C300000000000400 +%0008000000000001C0607FE3818FF181830C3C0000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0703FF1818FF1C1818C3C0000000000400 +%0008000000000001C0601E338187C181830C1C0000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0701F318183E1C1818C1C0000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800FFE0000000000030004000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFE00000000 +%00030004000000C0000000000000C00400 +%000800FFF000000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF00000000 +%0003000C000000C0000000000000C00400 +%000800E03800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E0380000000 +%0003000C000000C0000000000000C00400 +%000800E01C00000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C0000000 +%0003000C000000C0000000000000C00400 +%000800E00C0F838181EC33C3F07819CCE00F007C1B83CC0040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC00000000000800E00C0F81818 +%1E633C1F0780DCCE00F007C1BC3CC00400 +%000800E00C3FE38187FC3FE3F1FE1FCFF83FC1FE1F8FFC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E1FE1818 +%7FE3FE1F1FE0FCFF83FC1FE1FC7FC00400 +%000800E00E30E3818E1C3870C3871E0E1870E3871E9C3C00400000000040000000000000000000 +%0040000000000000000000000000000200000000000000000000100000000000800E00E3061818 +%61E3870C3870E0F1C70E3871E0C3C00400 +%000800E00E7063818C0C3030C3031C0E1CE063031C181C00400000000080000000000000000000 +%0040000000000000000000000000000200000000000000000000080000000000800E00E3071818 +%C0E3030C3030C0E0C6063031C1C1C00400 +%000800E00E0063819C0C3030C6031C0C0CC0700318181C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E0071818 +%C0E3030C3038C0C0CC0300318181C00400 +%000800E00E03E381980C3030C7FF9C0C0CC0303F18381C00400000000400000000000000000000 +%0040000000000000000000000000000200000000000000000000010000000000800E00E03F1819 +%C0E3030C7FF8C0C0EC0301F18180C00400 +%000800E00C3FE381980C3030C7FF9C0C0CC031FF18381C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E1FF1819 +%C0E3030C7FF8C0C0EC031FF18180C00400 +%000800E00C786383980C3030C6001C0C0CC033C318381C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00C3871819 +%C0E3030C7000C0C0EC033C318180C00400 +%000800E01C6063839C0C3030C7001C0C0CC0770318181C00400000002000000000000000000000 +%0040000000000000000000000000000200000000000000000000002000000000800E00C7071818 +%C0E3030C7000C0C0CC0330318180C00400 +%000800E0186063838C0C3030C3031C0C1CE0670718181C00400000004000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C6071838 +%C0E3030C3038C0E0C606303181C1C00400 +%000800E07870E1878E1C3030C3871C0E1870E70F180C3C00400000008000000000000000000000 +%0040000000000000000000000000000200000000000000000000000800000000800E07870F1C78 +%E1E3030C3870C0E1C70E307180C3C00400 +%000800FFF03FF1FD87FC3030F1FE1C0FF03FC3FF180FFC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF03FF0FD8 +%7FE3030F1FE0C0FF83FC3FF1807FC00400 +%000800FFC01E307981EC303070781C0DE01F01F39803CC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFC01F30798 +%1EE3030787C0C0CE00F00F19803CC00400 +%0008000000000000000C0000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%00C0000000000000000000000000000400 +%00080000000000000C0C0000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%C0C0000000000000000000000000000400 +%00080000000000000E380000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%F3C0000000000000000000000000000400 +%000800000000000007F00000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%7F80000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001003FF00060007C0000000000 +%0040000000000000000000000000000200000000003FE000E000FC000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002003FFC00F001FF0000000000 +%0040000000000000000000000000000200000000003FF800E003FE000200000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000381E00F003838000000000 +%004000000000000000000000000000020000000000301C01F00787800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000800380601F80701C000000000 +%004000000000000000000000000000020000000000300E01B00E03800080000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380701980E00C000000000 +%004000000000000000000000000000020000000000300603B00C01C00040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000380301980C000000000000 +%004000000000000000000000000000020000000000300703181C00000010000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400080003803031C0C000000000000 +%004000000000000000000000000000020000000000300303181800000008000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400100003803830C1C000000000000 +%0040000000000000000000000000000200000000003003071C1800000004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFA00003803870E1C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000003FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFC0000380386061C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040020000380307FE0C000000000000 +%00400000000000000000000000000002000000000030030FFE1800000002000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004001000038030FFF0C00C000000000 +%00400000000000000000000000000002000000000030070FFE1C00800004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000C00038030C030C00C000000000 +%00400000000000000000000000000002000000000030061C070C01C00018000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038070C038601C000000000 +%004000000000000000000000000000020000000000300E18030E01800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380E1C0387038000000000 +%004000000000000000000000000000020000000000301E18038703800040000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400008003FFC180183FF8000000000 +%0040000000000000000000000000000200000000003FFC380387FF000080000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003FF83801C1FE0000000000 +%0040000000000000000000000000000200000000003FF0300181FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000007FFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%007FFFFFFFFFFFFFFFFFFFFFFFFFFFFE0000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0.996 c 7835 7938 m 8893 6985 l 11010 6985 l 11010 8890 l 8893 8890 l +7835 7938 l p ef +0 lw 1 lj 0.000 c 7835 7938 m 8893 6985 l 11010 6985 l 11010 8890 l 8893 8890 l +7835 7938 l pc +gs +pum +8520 8228 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +13955 5080 m 11733 5080 l 11733 1270 l 16178 1270 l 16178 5080 l 13955 5080 l +pc +gs +pum +13176 2513 t +69 0 m 69 -605 l 477 -605 l 477 -534 l 149 -534 l 149 -346 l 433 -346 l +433 -275 l 149 -275 l 149 0 l p ef +532 0 m 766 -315 l 560 -605 l 655 -605 l 765 -450 l 788 -418 804 -393 814 -375 ct +827 -397 843 -420 862 -444 ct 984 -605 l 1071 -605 l 858 -320 l 1087 0 l +988 0 l 836 -216 l 827 -228 818 -241 809 -256 ct 796 -234 786 -219 780 -211 ct +628 0 l p ef +1510 -71 m 1510 0 l 1110 0 l 1110 -17 1112 -35 1119 -51 ct 1129 -78 1145 -105 1168 -132 ct +1190 -158 1223 -189 1265 -223 ct 1331 -277 1375 -320 1398 -352 ct 1422 -383 1433 -413 1433 -441 ct +1433 -471 1423 -495 1402 -516 ct 1380 -536 1353 -546 1319 -546 ct 1283 -546 1255 -535 1233 -514 ct +1212 -492 1201 -463 1201 -425 ct 1124 -432 l 1129 -489 1149 -533 1183 -563 ct +1217 -593 1263 -608 1321 -608 ct 1379 -608 1425 -591 1459 -559 ct 1493 -527 1510 -487 1510 -439 ct +1510 -415 1505 -391 1495 -368 ct 1485 -345 1468 -320 1445 -294 ct 1422 -268 1384 -233 1331 -187 ct +1286 -150 1257 -125 1245 -111 ct 1232 -98 1222 -84 1213 -71 ct p ef +pom +pum +12713 3466 t +462 -605 m 542 -605 l 542 -255 l 542 -194 535 -146 522 -110 ct 508 -74 483 -45 447 -23 ct +411 0 364 10 306 10 ct 249 10 202 0 166 -19 ct 130 -38 105 -66 89 -103 ct 74 -140 66 -191 66 -255 ct +66 -605 l 146 -605 l 146 -256 l 146 -203 151 -164 161 -139 ct 171 -114 187 -95 211 -82 ct +235 -68 264 -61 299 -61 ct 358 -61 400 -75 425 -102 ct 450 -128 462 -180 462 -256 ct +p ef +673 -194 m 748 -201 l 752 -170 760 -146 773 -126 ct 786 -107 806 -91 834 -79 ct +862 -67 893 -61 927 -61 ct 958 -61 985 -66 1008 -75 ct 1031 -84 1049 -96 1060 -112 ct +1072 -128 1077 -145 1077 -164 ct 1077 -183 1072 -200 1061 -214 ct 1050 -228 1032 -240 1006 -249 ct +990 -256 954 -266 898 -279 ct 843 -292 804 -305 782 -317 ct 753 -332 731 -351 717 -373 ct +703 -396 696 -421 696 -449 ct 696 -479 704 -508 722 -534 ct 739 -561 764 -581 798 -595 ct +831 -609 868 -615 909 -615 ct 954 -615 993 -608 1028 -594 ct 1062 -579 1088 -558 1107 -530 ct +1125 -502 1135 -470 1136 -434 ct 1060 -429 l 1055 -467 1041 -496 1018 -515 ct +994 -535 959 -545 912 -545 ct 864 -545 828 -536 806 -518 ct 784 -500 773 -479 773 -454 ct +773 -432 781 -414 796 -400 ct 812 -386 852 -372 917 -357 ct 982 -342 1027 -329 1051 -318 ct +1087 -302 1113 -282 1129 -257 ct 1146 -232 1155 -203 1155 -171 ct 1155 -138 1145 -108 1127 -79 ct +1108 -51 1082 -29 1047 -13 ct 1013 2 974 10 931 10 ct 876 10 830 2 793 -13 ct 756 -29 727 -53 706 -85 ct +685 -117 l 674 -154 l p ef +1278 0 m 1278 -605 l 1506 -605 l 1552 -605 1589 -599 1617 -587 ct 1645 -574 1667 -556 1683 -530 ct +1699 -505 1706 -478 1706 -450 ct 1706 -424 1699 -400 1685 -377 ct 1671 -354 1650 -336 1622 -322 ct +1658 -311 1687 -293 1706 -267 ct 1726 -241 1736 -210 1736 -175 ct 1736 -147 1730 -120 1718 -96 ct +1706 -72 1691 -53 1673 -40 ct 1656 -26 1634 -16 1607 -10 ct 1580 -3 1548 0 1509 0 ct +p +1359 -351 m 1490 -351 l 1525 -351 1551 -353 1566 -358 ct 1586 -364 1602 -374 1612 -388 ct +1622 -402 1628 -419 1628 -441 ct 1628 -461 1623 -478 1613 -494 ct 1603 -509 1590 -520 1572 -525 ct +1554 -531 1523 -534 1480 -534 ct 1359 -534 l p +1359 -71 m 1509 -71 l 1535 -71 1553 -72 1564 -74 ct 1582 -77 1598 -83 1610 -90 ct +1623 -98 1633 -109 1641 -124 ct 1649 -139 1653 -156 1653 -175 ct 1653 -198 1647 -217 1635 -234 ct +1624 -251 1608 -262 1587 -269 ct 1567 -276 1537 -279 1499 -279 ct 1359 -279 l +p ef +2436 -71 m 2436 0 l 2036 0 l 2036 -17 2038 -35 2045 -51 ct 2055 -78 2071 -105 2094 -132 ct +2116 -158 2149 -189 2191 -223 ct 2257 -277 2301 -320 2324 -352 ct 2348 -383 2359 -413 2359 -441 ct +2359 -471 2349 -495 2328 -516 ct 2306 -536 2279 -546 2245 -546 ct 2209 -546 2181 -535 2159 -514 ct +2138 -492 2127 -463 2127 -425 ct 2050 -432 l 2055 -489 2075 -533 2109 -563 ct +2143 -593 2189 -608 2247 -608 ct 2305 -608 2351 -591 2385 -559 ct 2419 -527 2436 -487 2436 -439 ct +2436 -415 2431 -391 2421 -368 ct 2411 -345 2394 -320 2371 -294 ct 2348 -268 2310 -233 2257 -187 ct +2212 -150 2183 -125 2171 -111 ct 2158 -98 2148 -84 2139 -71 ct p ef +pom +pum +12091 4419 t +497 -212 m 577 -192 l 560 -126 530 -76 486 -41 ct 443 -6 389 10 326 10 ct +261 10 208 -2 167 -29 ct 126 -56 95 -94 74 -145 ct 52 -195 42 -249 42 -307 ct 42 -370 54 -425 78 -472 ct +102 -519 136 -554 181 -579 ct 225 -603 274 -615 327 -615 ct 388 -615 439 -600 480 -569 ct +522 -538 550 -495 567 -439 ct 488 -420 l 474 -465 453 -497 427 -517 ct 400 -537 366 -547 326 -547 ct +279 -547 240 -536 209 -513 ct 178 -491 156 -461 143 -424 ct 131 -386 124 -347 124 -307 ct +124 -256 132 -211 147 -172 ct 162 -134 185 -105 217 -86 ct 248 -67 283 -58 320 -58 ct +365 -58 403 -71 434 -97 ct 465 -122 l 486 -161 l p ef +663 -219 m 663 -300 685 -360 730 -399 ct 768 -432 814 -448 868 -448 ct 929 -448 978 -428 1016 -389 ct +1054 -349 1074 -295 1074 -225 ct 1074 -169 1065 -124 1048 -92 ct 1031 -59 1007 -34 974 -16 ct +942 0 907 9 868 9 ct 807 9 757 -9 719 -49 ct 682 -88 l 663 -145 l p +739 -219 m 739 -163 751 -121 776 -93 ct 800 -65 831 -51 868 -51 ct 905 -51 936 -65 960 -93 ct +985 -121 997 -164 997 -221 ct 997 -276 985 -317 960 -345 ct 936 -373 905 -387 868 -387 ct +831 -387 800 -373 776 -345 ct 751 -317 l 739 -275 l p ef +1166 0 m 1166 -438 l 1233 -438 l 1233 -376 l 1265 -424 1312 -448 1373 -448 ct +1399 -448 1424 -443 1446 -434 ct 1468 -424 1484 -412 1495 -396 ct 1507 -381 1514 -363 1519 -342 ct +1521 -328 1523 -304 1523 -269 ct 1523 0 l 1448 0 l 1448 -266 l 1448 -297 1446 -319 1440 -334 ct +1434 -349 1424 -361 1409 -370 ct 1394 -379 1377 -384 1357 -384 ct 1325 -384 1298 -374 1275 -354 ct +1252 -333 1241 -295 1241 -239 ct 1241 0 l p ef +1806 -66 m 1816 0 l 1795 3 1777 5 1760 5 ct 1733 5 1712 1 1697 -7 ct 1683 -15 1672 -26 1666 -40 ct +1660 -54 1657 -83 1657 -128 ct 1657 -380 l 1602 -380 l 1602 -438 l 1657 -438 l +1657 -547 l 1731 -591 l 1731 -438 l 1806 -438 l 1806 -380 l 1731 -380 l +1731 -124 l 1731 -103 1732 -89 1735 -83 ct 1737 -77 1742 -72 1748 -68 ct 1753 -65 1762 -63 1773 -63 ct +1781 -63 l 1792 -64 l p ef +1880 0 m 1880 -438 l 1947 -438 l 1947 -372 l 1964 -403 1980 -423 1995 -433 ct +2009 -443 2025 -448 2042 -448 ct 2067 -448 2093 -440 2119 -424 ct 2093 -355 l +2075 -366 2057 -371 2039 -371 ct 2022 -371 2008 -366 1995 -357 ct 1982 -347 1973 -333 1967 -316 ct +1959 -289 1955 -261 1955 -229 ct 1955 0 l p ef +2145 -219 m 2145 -300 2167 -360 2212 -399 ct 2250 -432 2296 -448 2350 -448 ct +2411 -448 2460 -428 2498 -389 ct 2536 -349 2556 -295 2556 -225 ct 2556 -169 2547 -124 2530 -92 ct +2513 -59 2489 -34 2456 -16 ct 2424 0 2389 9 2350 9 ct 2289 9 2239 -9 2201 -49 ct +2164 -88 l 2145 -145 l p +2221 -219 m 2221 -163 2233 -121 2258 -93 ct 2282 -65 2313 -51 2350 -51 ct 2387 -51 2418 -65 2442 -93 ct +2467 -121 2479 -164 2479 -221 ct 2479 -276 2467 -317 2442 -345 ct 2418 -373 2387 -387 2350 -387 ct +2313 -387 2282 -373 2258 -345 ct 2233 -317 l 2221 -275 l p ef +2647 0 m 2647 -605 l 2721 -605 l 2721 0 l p ef +2832 0 m 2832 -605 l 2906 -605 l 2906 0 l p ef +3319 -141 m 3395 -131 l 3383 -86 3361 -52 3328 -27 ct 3295 -2 3253 9 3203 9 ct +3138 9 3087 -9 3050 -49 ct 3012 -88 2993 -144 2993 -215 ct 2993 -289 3012 -346 3050 -387 ct +3089 -428 3138 -448 3198 -448 ct 3257 -448 3305 -428 3342 -388 ct 3379 -348 3398 -292 3398 -220 ct +3398 -215 3398 -209 3397 -200 ct 3070 -200 l 3073 -152 3087 -115 3111 -89 ct +3136 -64 3166 -51 3203 -51 ct 3230 -51 3253 -58 3273 -72 ct 3292 -87 l 3307 -109 l +p +3074 -261 m 3319 -261 l 3316 -298 3307 -326 3291 -344 ct 3268 -373 3237 -387 3199 -387 ct +3165 -387 3136 -376 3113 -353 ct 3090 -330 l 3077 -299 l p ef +3494 0 m 3494 -438 l 3561 -438 l 3561 -372 l 3578 -403 3594 -423 3609 -433 ct +3623 -443 3639 -448 3656 -448 ct 3681 -448 3707 -440 3733 -424 ct 3707 -355 l +3689 -366 3671 -371 3653 -371 ct 3636 -371 3622 -366 3609 -357 ct 3596 -347 3587 -333 3581 -316 ct +3573 -289 3569 -261 3569 -229 ct 3569 0 l p ef +pom +gr +13956 19115 m 11900 19115 l 11900 6350 l 16013 6350 l 16013 19115 l +13956 19115 l pc +gs +pum +12806 13017 t +69 0 m 69 -605 l 477 -605 l 477 -534 l 149 -534 l 149 -346 l 433 -346 l +433 -275 l 149 -275 l 149 0 l p ef +594 0 m 594 -605 l 822 -605 l 862 -605 893 -603 914 -599 ct 944 -594 969 -585 989 -571 ct +1009 -557 1025 -538 1038 -513 ct 1050 -488 1056 -460 1056 -430 ct 1056 -378 1040 -335 1007 -299 ct +974 -264 915 -246 829 -246 ct 674 -246 l 674 0 l p +674 -317 m 830 -317 l 882 -317 919 -327 941 -346 ct 963 -365 973 -392 973 -427 ct +973 -453 967 -474 954 -493 ct 941 -511 925 -522 904 -528 ct 890 -532 865 -534 829 -534 ct +674 -534 l p ef +1433 -237 m 1433 -308 l 1690 -308 l 1690 -84 l 1650 -52 1610 -29 1568 -13 ct +1526 2 1483 10 1439 10 ct 1379 10 1325 -2 1277 -27 ct 1228 -53 1191 -90 1167 -138 ct +1142 -186 1130 -240 1130 -299 ct 1130 -358 1142 -413 1167 -464 ct 1191 -516 1227 -553 1273 -578 ct +1319 -603 1372 -615 1433 -615 ct 1477 -615 1516 -608 1551 -594 ct 1587 -580 1615 -560 1635 -535 ct +1655 -510 1670 -476 1681 -436 ct 1608 -416 l 1599 -447 1588 -471 1574 -489 ct +1561 -506 1542 -520 1517 -531 ct 1492 -542 1464 -547 1433 -547 ct 1397 -547 1365 -541 1338 -530 ct +1311 -519 1290 -504 1273 -486 ct 1257 -468 1244 -448 1235 -426 ct 1220 -389 1212 -348 1212 -304 ct +1212 -250 1221 -205 1240 -169 ct 1259 -133 1286 -106 1321 -88 ct 1357 -70 1394 -61 1434 -61 ct +1469 -61 1503 -68 1536 -82 ct 1569 -95 1594 -109 1611 -124 ct 1611 -237 l p ef +1745 0 m 1977 -605 l 2063 -605 l 2311 0 l 2220 0 l 2149 -183 l 1896 -183 l +1829 0 l p +1919 -248 m 2124 -248 l 2061 -416 l 2042 -467 2028 -509 2018 -541 ct 2010 -503 2000 -464 1986 -426 ct +p ef +pom +gr +0.996 c 7835 17258 m 8893 16305 l 11010 16305 l 11010 18210 l 8893 18210 l +7835 17258 l p ef +0.000 c 7835 17258 m 8893 16305 l 11010 16305 l 11010 18210 l 8893 18210 l +7835 17258 l pc +gs +pum +8520 17542 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 7835 10478 m 8893 9525 l 11010 9525 l 11010 11430 l 8893 11430 l +7835 10478 l p ef +0.000 c 7835 10478 m 8893 9525 l 11010 9525 l 11010 11430 l 8893 11430 l +7835 10478 l pc +gs +pum +8520 10768 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 7835 14618 m 8893 13665 l 11010 13665 l 11010 15570 l 8893 15570 l +7835 14618 l p ef +0.000 c 7835 14618 m 8893 13665 l 11010 13665 l 11010 15570 l 8893 15570 l +7835 14618 l pc +gs +pum +8520 14896 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 7938 m 18926 6985 l 16809 6985 l 16809 8890 l 18926 8890 l +19984 7938 l p ef +0.000 c 19984 7938 m 18926 6985 l 16809 6985 l 16809 8890 l 18926 8890 l +19984 7938 l pc +gs +pum +17489 8228 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 17258 m 18926 16305 l 16809 16305 l 16809 18210 l 18926 18210 l +19984 17258 l p ef +0.000 c 19984 17258 m 18926 16305 l 16809 16305 l 16809 18210 l 18926 18210 l +19984 17258 l pc +gs +pum +17489 17542 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 10478 m 18926 9525 l 16809 9525 l 16809 11430 l 18926 11430 l +19984 10478 l p ef +0.000 c 19984 10478 m 18926 9525 l 16809 9525 l 16809 11430 l 18926 11430 l +19984 10478 l pc +gs +pum +17489 10768 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 14618 m 18926 13665 l 16809 13665 l 16809 15570 l 18926 15570 l +19984 14618 l p ef +0.000 c 19984 14618 m 18926 13665 l 16809 13665 l 16809 15570 l 18926 15570 l +19984 14618 l pc +gs +pum +17489 14896 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +23767 18828 m 20592 18828 l 20592 13113 l 26942 13113 l 26942 18828 l +23767 18828 l pc +gs +pum +22133 15795 t +219 0 m 219 -534 l 19 -534 l 19 -605 l 499 -605 l 499 -534 l 299 -534 l +299 0 l p ef +583 0 m 583 -438 l 650 -438 l 650 -372 l 667 -403 683 -423 698 -433 ct +712 -443 728 -448 745 -448 ct 770 -448 796 -440 822 -424 ct 796 -355 l 778 -366 760 -371 742 -371 ct +725 -371 711 -366 698 -357 ct 685 -347 676 -333 670 -316 ct 662 -289 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -48 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -252 ct 1083 -259 1127 -268 1155 -278 ct +1156 -288 1156 -295 1156 -297 ct 1156 -328 1149 -349 1135 -361 ct 1116 -378 1087 -387 1050 -387 ct +1015 -387 989 -380 973 -368 ct 956 -356 944 -334 936 -303 ct 863 -313 l 869 -344 880 -369 896 -388 ct +911 -408 933 -422 961 -433 ct 990 -443 1023 -448 1061 -448 ct 1098 -448 1129 -444 1152 -435 ct +1175 -426 1193 -415 1204 -402 ct 1215 -388 1222 -371 1227 -351 ct 1229 -338 1231 -316 1231 -282 ct +1231 -183 l 1231 -114 1232 -70 1235 -52 ct 1238 -34 1245 -16 1254 0 ct 1176 0 l +1169 -15 l 1164 -33 l p +1155 -220 m 1128 -209 1088 -199 1034 -192 ct 1003 -187 982 -182 969 -177 ct +956 -171 947 -163 940 -153 ct 933 -142 929 -130 929 -117 ct 929 -97 937 -81 952 -68 ct +967 -54 989 -48 1018 -48 ct 1046 -48 1072 -54 1094 -67 ct 1117 -79 1133 -96 1143 -118 ct +1151 -135 1155 -160 1155 -192 ct p ef +1325 0 m 1325 -438 l 1392 -438 l 1392 -376 l 1424 -424 1471 -448 1532 -448 ct +1558 -448 1583 -443 1605 -434 ct 1627 -424 1643 -412 1654 -396 ct 1666 -381 1673 -363 1678 -342 ct +1680 -328 1682 -304 1682 -269 ct 1682 0 l 1607 0 l 1607 -266 l 1607 -297 1605 -319 1599 -334 ct +1593 -349 1583 -361 1568 -370 ct 1553 -379 1536 -384 1516 -384 ct 1484 -384 1457 -374 1434 -354 ct +1411 -333 1400 -295 1400 -239 ct 1400 0 l p ef +1772 -130 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1898 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2051 -85 2059 -102 2059 -121 ct 2059 -137 2052 -151 2038 -160 ct +2027 -167 2002 -175 1962 -185 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -300 1784 -322 ct 1784 -341 1788 -359 1797 -376 ct 1806 -393 1818 -407 1834 -418 ct +1845 -426 1861 -433 1881 -439 ct 1901 -445 1923 -448 1945 -448 ct 1980 -448 2010 -443 2036 -433 ct +2062 -423 2081 -410 2094 -393 ct 2106 -376 2115 -353 2119 -325 ct 2047 -315 l +2043 -338 2034 -355 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -381 1878 -370 ct +1863 -359 1856 -346 1856 -330 ct 1856 -321 1859 -312 1865 -304 ct 1871 -296 1880 -290 1893 -285 ct +1901 -282 1923 -275 1959 -266 ct 2012 -251 2048 -240 2069 -231 ct 2090 -222 2106 -209 2118 -192 ct +2130 -175 2136 -154 2136 -128 ct 2136 -104 2129 -80 2114 -58 ct 2100 -36 2079 -20 2052 -8 ct +2024 3 1993 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -438 l 2265 -438 l 2265 -377 l 2279 -398 2297 -415 2320 -428 ct +2343 -442 2369 -448 2398 -448 ct 2430 -448 2457 -441 2478 -428 ct 2499 -414 2513 -396 2522 -371 ct +2556 -423 2602 -448 2657 -448 ct 2701 -448 2734 -436 2758 -412 ct 2781 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2716 -327 2712 -340 ct 2707 -353 2698 -364 2685 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2584 -373 2564 -353 ct 2543 -332 2533 -300 2533 -254 ct +2533 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -342 2441 -359 ct 2429 -375 2409 -384 2381 -384 ct +2360 -384 2341 -378 2323 -367 ct 2305 -356 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -605 l 2988 -605 l 2988 -520 l p +2914 0 m 2914 -438 l 2988 -438 l 2988 0 l p ef +3261 -66 m 3271 0 l 3250 3 3232 5 3215 5 ct 3188 5 3167 1 3152 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -380 l 3057 -380 l 3057 -438 l 3112 -438 l +3112 -547 l 3186 -591 l 3186 -438 l 3261 -438 l 3261 -380 l 3186 -380 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3192 -77 3197 -72 3203 -68 ct 3208 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +pom +pum +20955 16748 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +23767 12065 m 20592 12065 l 20592 6350 l 26942 6350 l 26942 12065 l +23767 12065 l pc +gs +pum +22239 9022 t +66 0 m 66 -605 l 335 -605 l 389 -605 430 -600 458 -589 ct 486 -578 508 -559 525 -531 ct +542 -504 550 -473 550 -440 ct 550 -397 536 -361 508 -331 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 451 -223 473 -197 494 -164 ct 600 0 l 499 0 l +419 -125 l 395 -162 376 -190 361 -209 ct 346 -228 332 -242 320 -249 ct 308 -257 296 -263 284 -266 ct +275 -267 260 -268 239 -268 ct 146 -268 l 146 0 l p +146 -338 m 318 -338 l 355 -338 384 -342 404 -349 ct 425 -357 441 -369 451 -386 ct +462 -402 468 -420 468 -440 ct 468 -468 457 -492 436 -510 ct 416 -529 383 -538 338 -538 ct +146 -538 l p ef +965 -141 m 1041 -131 l 1029 -86 1007 -52 974 -27 ct 941 -2 899 9 849 9 ct +784 9 733 -9 696 -49 ct 658 -88 639 -144 639 -215 ct 639 -289 658 -346 696 -387 ct +735 -428 784 -448 844 -448 ct 903 -448 951 -428 988 -388 ct 1025 -348 1044 -292 1044 -220 ct +1044 -215 1044 -209 1043 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 812 -51 849 -51 ct +876 -51 899 -58 919 -72 ct 938 -87 l 953 -109 l p +720 -261 m 965 -261 l 962 -298 953 -326 937 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 782 -376 759 -353 ct 736 -330 l 723 -299 l p ef +1427 -160 m 1500 -151 l 1492 -100 1471 -61 1438 -32 ct 1405 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -48 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -377 1181 -404 1213 -421 ct 1245 -439 1280 -448 1317 -448 ct 1365 -448 1404 -436 1434 -412 ct +1465 -388 1484 -354 1493 -309 ct 1420 -298 l 1413 -328 1401 -350 1384 -365 ct +1366 -380 1345 -387 1320 -387 ct 1283 -387 1252 -374 1229 -347 ct 1206 -320 1194 -277 1194 -219 ct +1194 -160 1205 -118 1228 -91 ct 1250 -64 1280 -51 1316 -51 ct 1345 -51 1370 -60 1389 -78 ct +1409 -95 l 1421 -123 l p ef +1864 -141 m 1940 -131 l 1928 -86 1906 -52 1873 -27 ct 1840 -2 1798 9 1748 9 ct +1683 9 1632 -9 1595 -49 ct 1557 -88 1538 -144 1538 -215 ct 1538 -289 1557 -346 1595 -387 ct +1634 -428 1683 -448 1743 -448 ct 1802 -448 1850 -428 1887 -388 ct 1924 -348 1943 -292 1943 -220 ct +1943 -215 1943 -209 1942 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1711 -51 1748 -51 ct 1775 -51 1798 -58 1818 -72 ct 1837 -87 l 1852 -109 l +p +1619 -261 m 1864 -261 l 1861 -298 1852 -326 1836 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1681 -376 1658 -353 ct 1635 -330 l 1622 -299 l p ef +2040 -520 m 2040 -605 l 2114 -605 l 2114 -520 l p +2040 0 m 2040 -438 l 2114 -438 l 2114 0 l p ef +2347 0 m 2180 -438 l 2259 -438 l 2353 -175 l 2363 -147 2372 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2506 -438 l 2583 -438 l 2417 0 l p ef +2949 -141 m 3025 -131 l 3013 -86 2991 -52 2958 -27 ct 2925 -2 2883 9 2833 9 ct +2768 9 2717 -9 2680 -49 ct 2642 -88 2623 -144 2623 -215 ct 2623 -289 2642 -346 2680 -387 ct +2719 -428 2768 -448 2828 -448 ct 2887 -448 2935 -428 2972 -388 ct 3009 -348 3028 -292 3028 -220 ct +3028 -215 3028 -209 3027 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2796 -51 2833 -51 ct 2860 -51 2883 -58 2903 -72 ct 2922 -87 l 2937 -109 l +p +2704 -261 m 2949 -261 l 2946 -298 2937 -326 2921 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2766 -376 2743 -353 ct 2720 -330 l 2707 -299 l p ef +pom +pum +20955 9975 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +4245 18828 m 1070 18828 l 1070 13113 l 7420 13113 l 7420 18828 l 4245 18828 l +pc +gs +pum +2607 15795 t +219 0 m 219 -534 l 19 -534 l 19 -605 l 499 -605 l 499 -534 l 299 -534 l +299 0 l p ef +583 0 m 583 -438 l 650 -438 l 650 -372 l 667 -403 683 -423 698 -433 ct +712 -443 728 -448 745 -448 ct 770 -448 796 -440 822 -424 ct 796 -355 l 778 -366 760 -371 742 -371 ct +725 -371 711 -366 698 -357 ct 685 -347 676 -333 670 -316 ct 662 -289 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -48 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -252 ct 1083 -259 1127 -268 1155 -278 ct +1156 -288 1156 -295 1156 -297 ct 1156 -328 1149 -349 1135 -361 ct 1116 -378 1087 -387 1050 -387 ct +1015 -387 989 -380 973 -368 ct 956 -356 944 -334 936 -303 ct 863 -313 l 869 -344 880 -369 896 -388 ct +911 -408 933 -422 961 -433 ct 990 -443 1023 -448 1061 -448 ct 1098 -448 1129 -444 1152 -435 ct +1175 -426 1193 -415 1204 -402 ct 1215 -388 1222 -371 1227 -351 ct 1229 -338 1231 -316 1231 -282 ct +1231 -183 l 1231 -114 1232 -70 1235 -52 ct 1238 -34 1245 -16 1254 0 ct 1176 0 l +1169 -15 l 1164 -33 l p +1155 -220 m 1128 -209 1088 -199 1034 -192 ct 1003 -187 982 -182 969 -177 ct +956 -171 947 -163 940 -153 ct 933 -142 929 -130 929 -117 ct 929 -97 937 -81 952 -68 ct +967 -54 989 -48 1018 -48 ct 1046 -48 1072 -54 1094 -67 ct 1117 -79 1133 -96 1143 -118 ct +1151 -135 1155 -160 1155 -192 ct p ef +1325 0 m 1325 -438 l 1392 -438 l 1392 -376 l 1424 -424 1471 -448 1532 -448 ct +1558 -448 1583 -443 1605 -434 ct 1627 -424 1643 -412 1654 -396 ct 1666 -381 1673 -363 1678 -342 ct +1680 -328 1682 -304 1682 -269 ct 1682 0 l 1607 0 l 1607 -266 l 1607 -297 1605 -319 1599 -334 ct +1593 -349 1583 -361 1568 -370 ct 1553 -379 1536 -384 1516 -384 ct 1484 -384 1457 -374 1434 -354 ct +1411 -333 1400 -295 1400 -239 ct 1400 0 l p ef +1772 -130 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1898 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2051 -85 2059 -102 2059 -121 ct 2059 -137 2052 -151 2038 -160 ct +2027 -167 2002 -175 1962 -185 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -300 1784 -322 ct 1784 -341 1788 -359 1797 -376 ct 1806 -393 1818 -407 1834 -418 ct +1845 -426 1861 -433 1881 -439 ct 1901 -445 1923 -448 1945 -448 ct 1980 -448 2010 -443 2036 -433 ct +2062 -423 2081 -410 2094 -393 ct 2106 -376 2115 -353 2119 -325 ct 2047 -315 l +2043 -338 2034 -355 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -381 1878 -370 ct +1863 -359 1856 -346 1856 -330 ct 1856 -321 1859 -312 1865 -304 ct 1871 -296 1880 -290 1893 -285 ct +1901 -282 1923 -275 1959 -266 ct 2012 -251 2048 -240 2069 -231 ct 2090 -222 2106 -209 2118 -192 ct +2130 -175 2136 -154 2136 -128 ct 2136 -104 2129 -80 2114 -58 ct 2100 -36 2079 -20 2052 -8 ct +2024 3 1993 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -438 l 2265 -438 l 2265 -377 l 2279 -398 2297 -415 2320 -428 ct +2343 -442 2369 -448 2398 -448 ct 2430 -448 2457 -441 2478 -428 ct 2499 -414 2513 -396 2522 -371 ct +2556 -423 2602 -448 2657 -448 ct 2701 -448 2734 -436 2758 -412 ct 2781 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2716 -327 2712 -340 ct 2707 -353 2698 -364 2685 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2584 -373 2564 -353 ct 2543 -332 2533 -300 2533 -254 ct +2533 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -342 2441 -359 ct 2429 -375 2409 -384 2381 -384 ct +2360 -384 2341 -378 2323 -367 ct 2305 -356 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -605 l 2988 -605 l 2988 -520 l p +2914 0 m 2914 -438 l 2988 -438 l 2988 0 l p ef +3261 -66 m 3271 0 l 3250 3 3232 5 3215 5 ct 3188 5 3167 1 3152 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -380 l 3057 -380 l 3057 -438 l 3112 -438 l +3112 -547 l 3186 -591 l 3186 -438 l 3261 -438 l 3261 -380 l 3186 -380 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3192 -77 3197 -72 3203 -68 ct 3208 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +pom +pum +1429 16748 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +4245 12065 m 1070 12065 l 1070 6350 l 7420 6350 l 7420 12065 l 4245 12065 l +pc +gs +pum +2713 9022 t +66 0 m 66 -605 l 335 -605 l 389 -605 430 -600 458 -589 ct 486 -578 508 -559 525 -531 ct +542 -504 550 -473 550 -440 ct 550 -397 536 -361 508 -331 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 451 -223 473 -197 494 -164 ct 600 0 l 499 0 l +419 -125 l 395 -162 376 -190 361 -209 ct 346 -228 332 -242 320 -249 ct 308 -257 296 -263 284 -266 ct +275 -267 260 -268 239 -268 ct 146 -268 l 146 0 l p +146 -338 m 318 -338 l 355 -338 384 -342 404 -349 ct 425 -357 441 -369 451 -386 ct +462 -402 468 -420 468 -440 ct 468 -468 457 -492 436 -510 ct 416 -529 383 -538 338 -538 ct +146 -538 l p ef +965 -141 m 1041 -131 l 1029 -86 1007 -52 974 -27 ct 941 -2 899 9 849 9 ct +784 9 733 -9 696 -49 ct 658 -88 639 -144 639 -215 ct 639 -289 658 -346 696 -387 ct +735 -428 784 -448 844 -448 ct 903 -448 951 -428 988 -388 ct 1025 -348 1044 -292 1044 -220 ct +1044 -215 1044 -209 1043 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 812 -51 849 -51 ct +876 -51 899 -58 919 -72 ct 938 -87 l 953 -109 l p +720 -261 m 965 -261 l 962 -298 953 -326 937 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 782 -376 759 -353 ct 736 -330 l 723 -299 l p ef +1427 -160 m 1500 -151 l 1492 -100 1471 -61 1438 -32 ct 1405 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -48 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -377 1181 -404 1213 -421 ct 1245 -439 1280 -448 1317 -448 ct 1365 -448 1404 -436 1434 -412 ct +1465 -388 1484 -354 1493 -309 ct 1420 -298 l 1413 -328 1401 -350 1384 -365 ct +1366 -380 1345 -387 1320 -387 ct 1283 -387 1252 -374 1229 -347 ct 1206 -320 1194 -277 1194 -219 ct +1194 -160 1205 -118 1228 -91 ct 1250 -64 1280 -51 1316 -51 ct 1345 -51 1370 -60 1389 -78 ct +1409 -95 l 1421 -123 l p ef +1864 -141 m 1940 -131 l 1928 -86 1906 -52 1873 -27 ct 1840 -2 1798 9 1748 9 ct +1683 9 1632 -9 1595 -49 ct 1557 -88 1538 -144 1538 -215 ct 1538 -289 1557 -346 1595 -387 ct +1634 -428 1683 -448 1743 -448 ct 1802 -448 1850 -428 1887 -388 ct 1924 -348 1943 -292 1943 -220 ct +1943 -215 1943 -209 1942 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1711 -51 1748 -51 ct 1775 -51 1798 -58 1818 -72 ct 1837 -87 l 1852 -109 l +p +1619 -261 m 1864 -261 l 1861 -298 1852 -326 1836 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1681 -376 1658 -353 ct 1635 -330 l 1622 -299 l p ef +2040 -520 m 2040 -605 l 2114 -605 l 2114 -520 l p +2040 0 m 2040 -438 l 2114 -438 l 2114 0 l p ef +2347 0 m 2180 -438 l 2259 -438 l 2353 -175 l 2363 -147 2372 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2506 -438 l 2583 -438 l 2417 0 l p ef +2949 -141 m 3025 -131 l 3013 -86 2991 -52 2958 -27 ct 2925 -2 2883 9 2833 9 ct +2768 9 2717 -9 2680 -49 ct 2642 -88 2623 -144 2623 -215 ct 2623 -289 2642 -346 2680 -387 ct +2719 -428 2768 -448 2828 -448 ct 2887 -448 2935 -428 2972 -388 ct 3009 -348 3028 -292 3028 -220 ct +3028 -215 3028 -209 3027 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2796 -51 2833 -51 ct 2860 -51 2883 -58 2903 -72 ct 2922 -87 l 2937 -109 l +p +2704 -261 m 2949 -261 l 2946 -298 2937 -326 2921 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2766 -376 2743 -353 ct 2720 -330 l 2707 -299 l p ef +pom +pum +1429 9975 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +51 lw 13970 5080 m 13970 6350 l ps +11010 7920 m 11900 7920 l ps +11010 10460 m 11900 10460 l ps +11010 14605 m 11900 14605 l ps +11010 17245 m 11900 17245 l ps +7835 7955 m 7420 7955 l ps +7835 10460 m 7420 10460 l ps +7835 14605 m 7420 14605 l ps +7835 17245 m 7420 17245 l ps +16013 7955 m 16809 7955 l ps +19984 7920 m 20592 7920 l ps +19984 10460 m 20592 10460 l ps +16013 10495 m 16809 10495 l ps +16013 14605 m 16809 14605 l ps +16013 17245 m 16809 17245 l ps +19984 14605 m 20592 14605 l ps +19984 17245 m 20592 17245 l ps +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/usrp/doc/usrp-block-diagram.png b/usrp/doc/usrp-block-diagram.png new file mode 100644 index 00000000..55a0f0b3 Binary files /dev/null and b/usrp/doc/usrp-block-diagram.png differ diff --git a/usrp/doc/usrp.jpg b/usrp/doc/usrp.jpg new file mode 100644 index 00000000..0ddb5927 Binary files /dev/null and b/usrp/doc/usrp.jpg differ diff --git a/usrp/doc/usrp_guide.xml b/usrp/doc/usrp_guide.xml new file mode 100644 index 00000000..7c4d5d5e --- /dev/null +++ b/usrp/doc/usrp_guide.xml @@ -0,0 +1,399 @@ + + + +
+ + USRP User's and Developer's Guide + + Matt + Ettus + + Ettus Research LLC +
+ Ettus Research LLC + 604 Mariposa Ave + Mountain View, CA 94041 + USA + matt@ettus.com +
+
+
+ + + + This guide explains both basic usage of the USRP as well as how to expand it. + + + +
+ + + Introduction + + The Universal Software Radio Peripheral, or USRP (pronounced "usurp") + is designed to allow general purpose computers to function as high + bandwidth software radios. In essence, it serves as a digital + baseband and IF section of a radio communication system. In addition, + it has a well-defined electrical and mechanical interface to RF + front-ends (daughterboards) which can translate between that IF or + baseband and the RF bands of interest + + + The basic design philosophy behind the USRP has been to do all of the + waveform-specific processing, like modulation and demodulation, on the + host CPU. All of the high-speed general purpose operations like + digital up- and downconversion, decimation and interpolation are done + on the FPGA. + + + It is anticipated that the majority of USRP users will never need to + use anything other than the standard FPGA configuration. However, for + those users that wish to, the FPGA design may be changed or replaced. + All of the interfaces are well defined and documented. + +
+ USRP with Daughterboards + + + + This USRP has 2 BasicTX and 2 BasicRX boards mounted on it. + Notice that the boards on the left are rotated 180 degrees. + + +
+ + + System Requirements + + The USRP requires a PC or Mac with a USB2 interface. + + + + + Capabilities + + The USRP has 4 high-speed analog to digital converters (ADCs), each at + 12 bits per sample, 64 million samples per second. There are also + 4 high-speed digital to analog converters (DACs), each at 14 bits per + sample, 128 million samples per second. These 4 input and 4 output + channels are connected to an Altera Cyclone EP1C12 FPGA. The FPGA, in + turn, connects to a USB2 interface chip, the Cypress FX2, and on to the + computer. The USRP connects to the computer via a high speed USB2 + interface only, and will not work with USB1.1. + +
Universal Software Radio Peripheral + + + + + +
+
+
+ + Getting Started + + Getting all the Software + + The first step in using your USRP system is to get all of GNU Radio installed. This can + sometimes be a daunting process, as there are several other libraries which will need to be + installed first. + + + Library Dependencies + + + SWIG + + We use SWIG (Simple Wrapper Interface Generator) to tie together the C++ and Python code + in the GNU Radio system. We require that you have version 1.3.24 or newer. You'll + probably have to compile it from source, which you can find here: SWIG + + + + FFTW + + FFTW is the library which GNU Radio uses for FFTs. GNU Radio requires version 3.0.1 or + newer, and it must be compiled for single precision. You can get it from the + FFTW Homepage + + + + Boost Library + + Boost provides several low-level structures used in our C++ code. If it is not included in + your OS distribution, you can get it here: Boost + + + + CPP Unit + + CPPUnit provides our unit-testing framework. This creates automated tests to insure that + code does not break when changes are made. Get it at the + CPP Unit Homepage + + + + + + Getting GNU Radio and the USRP code + + There are several packages of software which make up GNU Radio and the USRP support software. + Links to the latest versions of each can be found on the GNU Radio Wiki at + Download Links. Gr-build + can greatly simplify the installation process, and its use it highly recommended. + + + + Following CVS Development + + Development for the USRP proceeds very quickly at times, so some users may want to keep up with + the latest by following the CVS trees. There are three separate software repositories + which contain various parts of the USRP system. + + + + USRP-HW, containing the hardware and FPGA designs. + + + All of the schematics in this repository were created in + gEDA. The board + layouts were created in PCB. + Verilog designs are compiled in Quartus II Web Edition from + Altera. + + + + + USRP-SW, + USRP-SW, containing firmware and host drivers for the USRP + + + Host side drivers and firmware which runs in the USB2 interface chip on the board. + + + + + GNU Radio/gr-usrp + which contains the GNU Radio interface to the USRP + + + + + + + + Using your USRP + + Mechanical Connection + + The USRP ships with a complete set of standoffs, nuts and bolts. There are 20 standoffs, + M3x10mm M-F, of which 4 are intended to be used as "feet" for the USRP. Place them in the 4 + corner holes on the main board, inserting the male part from below. The remaining 16 + are used to hold the daughterboards in place. Four of them should be connected to the male + portion of the 4 standoffs already inserted from below. The remaining 12 should be + connected to the board with the 12 M3x6mm screws from below. At this point there should be + 16 standoffs on the board with the male ends up to serve as a guide for the daughterboards. + The 16 M3 nuts are used to fasten the daughterboards down to the main board. + + + The USRP accomodates 2 TX and 2 RX daughterboards. The placement of the standoffs is designed + to prevent the accidental incorrect connection of daughterboards. The 2 sides of the USRP have + their daughterboard slots rotated 180 degrees. The USRP should not be operated without + standoffs, and daughterboards should never be connected or removed while power is applied. + + + + Electrical Connections + + The USRP is powered by a 6V 4A power converter included in the kit. The converter is + capable of 90-260 Vac, 50/60 Hz operation, and so should work in any country. + If there is a need to use another power supply, the connector is a standard 2.1mm/5.5mm + DC power connector. The USRP itself only needs 5V at 2A, but a 6V supply was chosen to + accomodate future daughterboards. Extra power supplies are available from Ettus Research. + + + The included USB cable should be connected to a USB2-capable socket on a computer. The USRP + does not support USB 1.1 operation at this time. + + + + Troubleshooting + + When first powered up, an LED on the USRP should be flashing at about 3-4x per second. + This indicates that the processor is running, and has put the device in a low power mode. + Once firmware has been downloaded to the USRP, the LED will blink at a slower rate. + If there is no blinking LED, check all power connections, and check for continuity + in the power fuse (F501, near the power connector). If the fuse needs replacement, it + is size 0603, 3 amps. + + + + + + FPGA + + Standard FPGA Configuration + + In the standard fpga configuration, usrp_std, all samples sent over + the USB interface are in 16-bit signed integers in IQ format. When + there are multiple channels (up to 4), the channels are interleaved. + For example, with 4 channels, the sequence would be I0 Q0 I1 Q1 I2 Q2 + I3 Q3 I0 Q0, etc. + + + The USRP can operate in full duplex mode. When in this mode, the + transmit and receive sides are completely independent of one another. + The only consideration is that the combined data rate over the bus + must be 32 Megabytes per second or less. The multiple RX channels + (1,2, or 4) must all be the same data rate (i.e. same decimation + ratio). The same applies to the 1,2, or TX channels, which each must + be at the same data rate (which may be different from the RX rate). + + + On the RX side, each of the 4 ADCs can be routed to either of I or the + Q input of any of the 4 downconverters. This allows for having + multiple channels selected out of the same ADC sample stream. + + + The digital upconverters (DUCs) on the transmit side are actually + contained in the AD9862 CODEC chips, not in the FPGA. The only + transmit signal processing blocks in the FPGA are the interpolators. + The interpolator outputs can be routed to any of the 4 CODEC inputs. + +
Digital Down Converter Block Diagram + + + + + +
+ +
+
+ + Daughterboard Interface + + Power + + Daughterboards are provided with clean regulated 3.3V for the analog + and digital sections. Additionally there is a 6V connection straight from + the wall supply which is intended to supply a 5V LDO regulator. All daughterboards + may draw a combined total of 1.5 A. + + + + Logical Interface + + There are slots for 2 TX daughterboards, labeled TXA and TXB, and 2 + corresponding RX daughterboards, RXA and RXB. Each daughterboard slot has + access to 2 of the 4 high-speed data converter analog signals (DAC outputs + for TX, ADC inputs for RX). This allows each daughterboard which uses real + (not IQ) sampling to have 2 independent RF sections, and 2 antennas + (4 total for the system). If IQ sampling is used, each board can support + a single RF section, for a total of 2 for the whole system. + + + No antialias or reconstruction filtering is provided on the USRP motherboard. + This allows for maximum flexibility in frequency planning for the + daughterboards. The analog input bandwidth of the ADCs is over 200 MHz, so + IF frequencies up to that high may be chosen. If several decibels of loss + is tolerable, and IF frequency as high as 500 MHz can be used. + + + Every daughterboard has an I2C EEPROM (24LC024 or 24LC025) onboard + which identifies the board to the system. This allows the host + software to automatically set up the system properly based on the + installed daughterboard. The EEPROM may also store calibration values + like DC offsets or IQ imbalances. If this EEPROM is not programmed, a + warning message is printed every time USRP software is run. + + + + Analog Interface + + Each RX daughterboard has 2 differential analog inputs + (VINP_A/VINN_A and VINP_B/VINN_B) which are sampled at a rate of 64 MS/s. + The input impedance is approximately 1Kohm. + The motherboard has a software-controllable programmable gain amplifier + on these inputs, with 0 to 20 dB of gain. With gain set to zero, full + scale inputs are 2 Volts peak-to-peak differential. When set to 20 dB, + only .2 V pk-pk differential is needed to reach full scale. + + + If signals are AC-coupled, there is no need to provide DC bias as long as the + internal buffer is turned on. It will provide an approximately 2V bias. + If signals are DC-couple, a DC bias of Vdd/2 (1.65V) should be provided to + both the positive and negative inputs, and the internal buffer should be turned off. + VREF provides a clean 1 V reference. + + + Each TX daughterboard has a pair of differential analog outputs which are + updated at 128 MS/s. The signals (IOUTP_A/IOUTN_A and IOUTP_B/IOUTN_B) are + current-output, each varying between 0 and 20 mA. Since they are high-impedance, + they can be converted into differential voltages with a resistor. + + + In addition to the high-speed signals, each daughterboard has exclusive access to 2 low-speed ADC inputs + (labeled AUX_ADC_A and AUX_ADC_B) which can be read from software. + These are useful for sensing RSSI signal levels, temperatures, bias + levels, etc. Additionally, each board has shared access to 4 low-speed DAC + signals, labeled AUX_DAC_A through AUX_DAC_D. RXA and TXA share one set + of these 4 lines, and RXB and TXB share their own independent set. These + signals are useful for controlling gain of variable-gain amplifiers, for example. + AUX_ADC_REF provides a reference level for gain setting if it is necessary. + + + + + Digital Interface + + + + Connector Pinouts + + RX DBoard Connector + + + + Pin # + Name + Description + + + + + 1 + power + This is power + + + c1 + c4 + + + d1 + d4 + d5 + + + +
+
+
+ + Available Daughterboards + + BasicRX + + + + + BasicTX + + + + +
diff --git a/usrp/firmware/Makefile.am b/usrp/firmware/Makefile.am new file mode 100644 index 00000000..16a03cc5 --- /dev/null +++ b/usrp/firmware/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = include lib src diff --git a/usrp/firmware/include/Makefile.am b/usrp/firmware/include/Makefile.am new file mode 100644 index 00000000..7f58d19f --- /dev/null +++ b/usrp/firmware/include/Makefile.am @@ -0,0 +1,59 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include_HEADERS = \ + usrp_i2c_addr.h \ + usrp_spi_defs.h + + +noinst_HEADERS = \ + delay.h \ + fpga_regs_common.h \ + fpga_regs_common.v \ + fpga_regs_standard.h \ + fpga_regs_standard.v \ + fpga_regs0.h \ + fx2regs.h \ + fx2utils.h \ + i2c.h \ + isr.h \ + syncdelay.h \ + timer.h \ + usb_common.h \ + usb_descriptors.h \ + usb_requests.h \ + usrp_commands.h \ + usrp_config.h \ + usrp_ids.h \ + usrp_interfaces.h + + +CODE_GENERATOR = \ + generate_regs.py + +EXTRA_DIST = \ + $(CODE_GENERATOR) + +fpga_regs_common.v: fpga_regs_common.h generate_regs.py + PYTHONPATH=$(top_srcdir)/usrp/firmware/include $(srcdir)/generate_regs.py $< $@ + +fpga_regs_standard.v: fpga_regs_standard.h generate_regs.py + PYTHONPATH=$(top_srcdir)/usrp/firmware/include $(srcdir)/generate_regs.py $< $@ diff --git a/usrp/firmware/include/delay.h b/usrp/firmware/include/delay.h new file mode 100644 index 00000000..c0ef19af --- /dev/null +++ b/usrp/firmware/include/delay.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _DELAY_H_ +#define _DELAY_H_ + +/* + * delay for approximately usecs microseconds + * Note limit of 255 usecs. + */ +void udelay (unsigned char usecs); + +/* + * delay for approximately msecs milliseconds + */ +void mdelay (unsigned short msecs); + + +#endif /* _DELAY_H_ */ diff --git a/usrp/firmware/include/fpga_regs0.h b/usrp/firmware/include/fpga_regs0.h new file mode 100644 index 00000000..fd591dd0 --- /dev/null +++ b/usrp/firmware/include/fpga_regs0.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _FPGA_REGS0_H_ +#define _FPGA_REGS0_H_ + +#define FR_RX_FREQ_0 0 +#define FR_RX_FREQ_1 1 +#define FR_RX_FREQ_2 2 +#define FR_RX_FREQ_3 3 +#define FR_TX_FREQ_0 4 +#define FR_TX_FREQ_1 5 +#define FR_TX_FREQ_2 6 +#define FR_TX_FREQ_3 7 +#define FR_COMBO 8 + + +#define FR_ADC_CLK_DIV 128 // pseudo regs mapped to FR_COMBO by f/w +#define FR_EXT_CLK_DIV 129 +#define FR_INTERP 130 +#define FR_DECIM 131 + +#endif diff --git a/usrp/firmware/include/fpga_regs_common.h b/usrp/firmware/include/fpga_regs_common.h new file mode 100644 index 00000000..3272fdf3 --- /dev/null +++ b/usrp/firmware/include/fpga_regs_common.h @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_FPGA_REGS_COMMON_H +#define INCLUDED_FPGA_REGS_COMMON_H + +// This file defines registers common to all FPGA configurations. +// Registers 0 to 31 are reserved for use in this file. + + +// The FPGA needs to know the rate that samples are coming from and +// going to the A/D's and D/A's. div = 128e6 / sample_rate + +#define FR_TX_SAMPLE_RATE_DIV 0 +#define FR_RX_SAMPLE_RATE_DIV 1 + +// 2 is available. +// 3 is available. + +#define FR_MASTER_CTRL 4 // master enable and reset controls +# define bmFR_MC_ENABLE_TX (1 << 0) +# define bmFR_MC_ENABLE_RX (1 << 1) +# define bmFR_MC_RESET_TX (1 << 2) +# define bmFR_MC_RESET_RX (1 << 3) + +// i/o direction registers for pins that go to daughterboards. +// Setting the bit makes it an output from the FPGA to the d'board. +// top 16 is mask, low 16 is value + +#define FR_OE_0 5 // slot 0 +#define FR_OE_1 6 +#define FR_OE_2 7 +#define FR_OE_3 8 + +// i/o registers for pins that go to daughterboards. +// top 16 is a mask, low 16 is value + +#define FR_IO_0 9 // slot 0 +#define FR_IO_1 10 +#define FR_IO_2 11 +#define FR_IO_3 12 + +#define FR_MODE 13 +# define bmFR_MODE_NORMAL 0 +# define bmFR_MODE_LOOPBACK (1 << 0) // enable digital loopback +# define bmFR_MODE_RX_COUNTING (1 << 1) // Rx is counting +# define bmFR_MODE_RX_COUNTING_32BIT (1 << 2) // Rx is counting with a 32 bit counter + // low and high 16 bits are multiplexed across channel I and Q + + +// If the corresponding bit is set, internal FPGA debug circuitry +// controls the i/o pins for the associated bank of daughterboard +// i/o pins. Typically used for debugging FPGA designs. + +#define FR_DEBUG_EN 14 +# define bmFR_DEBUG_EN_TX_A (1 << 0) // debug controls TX_A i/o +# define bmFR_DEBUG_EN_RX_A (1 << 1) // debug controls RX_A i/o +# define bmFR_DEBUG_EN_TX_B (1 << 2) // debug controls TX_B i/o +# define bmFR_DEBUG_EN_RX_B (1 << 3) // debug controls RX_B i/o + + +// If the corresponding bit is set, enable the automatic DC +// offset correction control loop. +// +// The 4 low bits are significant: +// +// ADC0 = (1 << 0) +// ADC1 = (1 << 1) +// ADC2 = (1 << 2) +// ADC3 = (1 << 3) +// +// This control loop works if the attached daugherboard blocks DC. +// Currently all daughterboards do block DC. This includes: +// basic rx, dbs_rx, tv_rx, flex_xxx_rx. + +#define FR_DC_OFFSET_CL_EN 15 // DC Offset Control Loop Enable + + +// offset corrections for ADC's and DAC's (2's complement) + +#define FR_ADC_OFFSET_0 16 +#define FR_ADC_OFFSET_1 17 +#define FR_ADC_OFFSET_2 18 +#define FR_ADC_OFFSET_3 19 + + +// ------------------------------------------------------------------------ +// Automatic Transmit/Receive switching +// +// If automatic transmit/receive (ATR) switching is enabled in the +// FR_ATR_CTL register, the presence or absence of data in the FPGA +// transmit fifo selects between two sets of values for each of the 4 +// banks of daughterboard i/o pins. +// +// Each daughterboard slot has 3 16-bit registers associated with it: +// FR_ATR_MASK_*, FR_ATR_TXVAL_* and FR_ATR_RXVAL_* +// +// FR_ATR_MASK_{0,1,2,3}: +// +// These registers determine which of the daugherboard i/o pins are +// affected by ATR switching. If a bit in the mask is set, the +// corresponding i/o bit is controlled by ATR, else it's output +// value comes from the normal i/o pin output register: +// FR_IO_{0,1,2,3}. +// +// FR_ATR_TXVAL_{0,1,2,3}: +// FR_ATR_RXVAL_{0,1,2,3}: +// +// If the Tx fifo contains data, then the bits from TXVAL that are +// selected by MASK are output. Otherwise, the bits from RXVAL that +// are selected by MASK are output. + +#define FR_ATR_MASK_0 20 // slot 0 +#define FR_ATR_TXVAL_0 21 +#define FR_ATR_RXVAL_0 22 + +#define FR_ATR_MASK_1 23 // slot 1 +#define FR_ATR_TXVAL_1 24 +#define FR_ATR_RXVAL_1 25 + +#define FR_ATR_MASK_2 26 // slot 2 +#define FR_ATR_TXVAL_2 27 +#define FR_ATR_RXVAL_2 28 + +#define FR_ATR_MASK_3 29 // slot 3 +#define FR_ATR_TXVAL_3 30 +#define FR_ATR_RXVAL_3 31 + +#endif /* INCLUDED_FPGA_REGS_COMMON_H */ diff --git a/usrp/firmware/include/fpga_regs_common.v b/usrp/firmware/include/fpga_regs_common.v new file mode 100644 index 00000000..ee87ac02 --- /dev/null +++ b/usrp/firmware/include/fpga_regs_common.v @@ -0,0 +1,114 @@ +// +// This file is machine generated from fpga_regs_common.h +// Do not edit by hand; your edits will be overwritten. +// + +// This file defines registers common to all FPGA configurations. +// Registers 0 to 31 are reserved for use in this file. + + +// The FPGA needs to know the rate that samples are coming from and +// going to the A/D's and D/A's. div = 128e6 / sample_rate + +`define FR_TX_SAMPLE_RATE_DIV 7'd0 +`define FR_RX_SAMPLE_RATE_DIV 7'd1 + +// 2 is available. +// 3 is available. + +`define FR_MASTER_CTRL 7'd4 // master enable and reset controls + +// i/o direction registers for pins that go to daughterboards. +// Setting the bit makes it an output from the FPGA to the d'board. +// top 16 is mask, low 16 is value + +`define FR_OE_0 7'd5 // slot 0 +`define FR_OE_1 7'd6 +`define FR_OE_2 7'd7 +`define FR_OE_3 7'd8 + +// i/o registers for pins that go to daughterboards. +// top 16 is a mask, low 16 is value + +`define FR_IO_0 7'd9 // slot 0 +`define FR_IO_1 7'd10 +`define FR_IO_2 7'd11 +`define FR_IO_3 7'd12 + +`define FR_MODE 7'd13 + + +// If the corresponding bit is set, internal FPGA debug circuitry +// controls the i/o pins for the associated bank of daughterboard +// i/o pins. Typically used for debugging FPGA designs. + +`define FR_DEBUG_EN 7'd14 + + +// If the corresponding bit is set, enable the automatic DC +// offset correction control loop. +// +// The 4 low bits are significant: +// +// ADC0 = (1 << 0) +// ADC1 = (1 << 1) +// ADC2 = (1 << 2) +// ADC3 = (1 << 3) +// +// This control loop works if the attached daugherboard blocks DC. +// Currently all daughterboards do block DC. This includes: +// basic rx, dbs_rx, tv_rx, flex_xxx_rx. + +`define FR_DC_OFFSET_CL_EN 7'd15 // DC Offset Control Loop Enable + + +// offset corrections for ADC's and DAC's (2's complement) + +`define FR_ADC_OFFSET_0 7'd16 +`define FR_ADC_OFFSET_1 7'd17 +`define FR_ADC_OFFSET_2 7'd18 +`define FR_ADC_OFFSET_3 7'd19 + + +// ------------------------------------------------------------------------ +// Automatic Transmit/Receive switching +// +// If automatic transmit/receive (ATR) switching is enabled in the +// FR_ATR_CTL register, the presence or absence of data in the FPGA +// transmit fifo selects between two sets of values for each of the 4 +// banks of daughterboard i/o pins. +// +// Each daughterboard slot has 3 16-bit registers associated with it: +// FR_ATR_MASK_*, FR_ATR_TXVAL_* and FR_ATR_RXVAL_* +// +// FR_ATR_MASK_{0,1,2,3}: +// +// These registers determine which of the daugherboard i/o pins are +// affected by ATR switching. If a bit in the mask is set, the +// corresponding i/o bit is controlled by ATR, else it's output +// value comes from the normal i/o pin output register: +// FR_IO_{0,1,2,3}. +// +// FR_ATR_TXVAL_{0,1,2,3}: +// FR_ATR_RXVAL_{0,1,2,3}: +// +// If the Tx fifo contains data, then the bits from TXVAL that are +// selected by MASK are output. Otherwise, the bits from RXVAL that +// are selected by MASK are output. + +`define FR_ATR_MASK_0 7'd20 // slot 0 +`define FR_ATR_TXVAL_0 7'd21 +`define FR_ATR_RXVAL_0 7'd22 + +`define FR_ATR_MASK_1 7'd23 // slot 1 +`define FR_ATR_TXVAL_1 7'd24 +`define FR_ATR_RXVAL_1 7'd25 + +`define FR_ATR_MASK_2 7'd26 // slot 2 +`define FR_ATR_TXVAL_2 7'd27 +`define FR_ATR_RXVAL_2 7'd28 + +`define FR_ATR_MASK_3 7'd29 // slot 3 +`define FR_ATR_TXVAL_3 7'd30 +`define FR_ATR_RXVAL_3 7'd31 + diff --git a/usrp/firmware/include/fpga_regs_standard.h b/usrp/firmware/include/fpga_regs_standard.h new file mode 100644 index 00000000..3c46422e --- /dev/null +++ b/usrp/firmware/include/fpga_regs_standard.h @@ -0,0 +1,284 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_FPGA_REGS_STANDARD_H +#define INCLUDED_FPGA_REGS_STANDARD_H + +// Register numbers 0 to 31 are reserved for use in fpga_regs_common.h. +// Registers 64 to 79 are available for custom FPGA builds. + + +// DDC / DUC + +#define FR_INTERP_RATE 32 // [1,1024] +#define FR_DECIM_RATE 33 // [1,256] + +// DDC center freq + +#define FR_RX_FREQ_0 34 +#define FR_RX_FREQ_1 35 +#define FR_RX_FREQ_2 36 +#define FR_RX_FREQ_3 37 + +// See below for DDC Starting Phase + +// ------------------------------------------------------------------------ +// configure FPGA Rx mux +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-----------------------+-------+-------+-------+-------+-+-----+ +// | must be zero | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH | +// +-----------------------+-------+-------+-------+-------+-+-----+ +// +// There are a maximum of 4 digital downconverters in the the FPGA. +// Each DDC has two 16-bit inputs, I and Q, and two 16-bit outputs, I & Q. +// +// DDC I inputs are specified by the two bit fields I3, I2, I1 & I0 +// +// 0 = DDC input is from ADC 0 +// 1 = DDC input is from ADC 1 +// 2 = DDC input is from ADC 2 +// 3 = DDC input is from ADC 3 +// +// If Z == 1, all DDC Q inputs are set to zero +// If Z == 0, DDC Q inputs are specified by the two bit fields Q3, Q2, Q1 & Q0 +// +// NCH specifies the number of complex channels that are sent across +// the USB. The legal values are 1, 2 or 4, corresponding to 2, 4 or +// 8 16-bit values. + +#define FR_RX_MUX 38 + +// ------------------------------------------------------------------------ +// configure FPGA Tx Mux. +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-----------------------+-------+-------+-------+-------+-+-----+ +// | | DAC3 | DAC2 | DAC1 | DAC0 |0| NCH | +// +-----------------------------------------------+-------+-+-----+ +// +// NCH specifies the number of complex channels that are sent across +// the USB. The legal values are 1 or 2, corresponding to 2 or 4 +// 16-bit values. +// +// There are two interpolators with complex inputs and outputs. +// There are four DACs. (We use the DUC in each AD9862.) +// +// Each 4-bit DACx field specifies the source for the DAC and +// whether or not that DAC is enabled. Each subfield is coded +// like this: +// +// 3 2 1 0 +// +-+-----+ +// |E| N | +// +-+-----+ +// +// Where E is set if the DAC is enabled, and N specifies which +// interpolator output is connected to this DAC. +// +// N which interp output +// --- ------------------- +// 0 chan 0 I +// 1 chan 0 Q +// 2 chan 1 I +// 3 chan 1 Q + +#define FR_TX_MUX 39 + +// ------------------------------------------------------------------------ +// REFCLK control +// +// Control whether a reference clock is sent to the daughterboards, +// and what frequency. The refclk is sent on d'board i/o pin 0. +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-----------------------------------------------+-+------------+ +// | Reserved (Must be zero) |E| DIVISOR | +// +-----------------------------------------------+-+------------+ + +// +// Bit 7 -- 1 turns on refclk, 0 allows IO use +// Bits 6:0 Divider value + +#define FR_TX_A_REFCLK 40 +#define FR_RX_A_REFCLK 41 +#define FR_TX_B_REFCLK 42 +#define FR_RX_B_REFCLK 43 + +# define bmFR_REFCLK_EN 0x80 +# define bmFR_REFCLK_DIVISOR_MASK 0x7f + +// ------------------------------------------------------------------------ +// DDC Starting Phase + +#define FR_RX_PHASE_0 44 +#define FR_RX_PHASE_1 45 +#define FR_RX_PHASE_2 46 +#define FR_RX_PHASE_3 47 + +// ------------------------------------------------------------------------ +// Tx data format control register +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-------------------------------------------------------+-------+ +// | Reserved (Must be zero) | FMT | +// +-------------------------------------------------------+-------+ +// +// FMT values: + +#define FR_TX_FORMAT 48 +# define bmFR_TX_FORMAT_16_IQ 0 // 16-bit I, 16-bit Q + +// ------------------------------------------------------------------------ +// Rx data format control register +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-----------------------------------------+-+-+---------+-------+ +// | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | +// +-----------------------------------------+-+-+---------+-------+ +// +// FMT values: + +#define FR_RX_FORMAT 49 + +# define bmFR_RX_FORMAT_SHIFT_MASK (0x0f << 0) // arithmetic right shift [0, 15] +# define bmFR_RX_FORMAT_SHIFT_SHIFT 0 +# define bmFR_RX_FORMAT_WIDTH_MASK (0x1f << 4) // data width in bits [1, 16] (not all valid) +# define bmFR_RX_FORMAT_WIDTH_SHIFT 4 +# define bmFR_RX_FORMAT_WANT_Q (0x1 << 9) // deliver both I & Q, else just I +# define bmFR_RX_FORMAT_BYPASS_HB (0x1 << 10) // bypass half-band filter + +// The valid combinations currently are: +// +// B Q WIDTH SHIFT +// 0 1 16 0 +// 0 1 8 8 + + +// Possible future values of WIDTH = {4, 2, 1} +// 12 takes a bit more work, since we need to know packet alignment. + +// ------------------------------------------------------------------------ +// FIXME register numbers 50 to 63 are available + +// ------------------------------------------------------------------------ +// Registers 64 to 79 are reserved for user custom FPGA builds. +// The standard USRP software will not touch these. + +#define FR_USER_0 64 +#define FR_USER_1 65 +#define FR_USER_2 66 +#define FR_USER_3 67 +#define FR_USER_4 68 +#define FR_USER_5 69 +#define FR_USER_6 70 +#define FR_USER_7 71 +#define FR_USER_8 72 +#define FR_USER_9 73 +#define FR_USER_10 74 +#define FR_USER_11 75 +#define FR_USER_12 76 +#define FR_USER_13 77 +#define FR_USER_14 78 +#define FR_USER_15 79 + +//Registers needed for multi usrp master/slave configuration +// +//Rx Master/slave control register (FR_RX_MASTER_SLAVE = FR_USER_0) +// +#define FR_RX_MASTER_SLAVE 64 +#define bitnoFR_RX_SYNC 0 +#define bitnoFR_RX_SYNC_MASTER 1 +#define bitnoFR_RX_SYNC_SLAVE 2 +# define bmFR_RX_SYNC (1 < list above. + * addr is the address of the interrupt service routine. + */ +void hook_sv (unsigned char vector_number, unsigned short addr); + +/* + * Hook usb interrupt vector. + * + * vector_number is from the UV_ list above. + * addr is the address of the interrupt service routine. + */ +void hook_uv (unsigned char vector_number, unsigned short addr); + +/* + * Hook fifo/gpif interrupt vector. + * + * vector_number is from the FGV_ list above. + * addr is the address of the interrupt service routine. + */ +void hook_fgv (unsigned char vector_number, unsigned short addr); + +/* + * One time call to enable autovectoring for both USB and FIFO/GPIF + */ +void setup_autovectors (void); + + +/* + * Must be called in each usb interrupt handler + */ +#define clear_usb_irq() \ + EXIF &= ~bmEXIF_USBINT; \ + INT2CLR = 0 + +/* + * Must be calledin each fifo/gpif interrupt handler + */ +#define clear_fifo_gpif_irq() \ + EXIF &= ~bmEXIF_IE4; \ + INT4CLR = 0 + +#endif /* _ISR_H_ */ diff --git a/usrp/firmware/include/syncdelay.h b/usrp/firmware/include/syncdelay.h new file mode 100644 index 00000000..fa67338b --- /dev/null +++ b/usrp/firmware/include/syncdelay.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _SYNCDELAY_H_ +#define _SYNCDELAY_H_ + +/* + * Magic delay required between access to certain xdata registers (TRM page 15-106). + * For our configuration, 48 MHz FX2 / 48 MHz IFCLK, we need three cycles. Each + * NOP is a single cycle.... + * + * From TRM page 15-105: + * + * Under certain conditions, some read and write access to the FX2 registers must + * be separated by a "synchronization delay". The delay is necessary only under the + * following conditions: + * + * - between a write to any register in the 0xE600 - 0xE6FF range and a write to one + * of the registers listed below. + * + * - between a write to one of the registers listed below and a read from any register + * in the 0xE600 - 0xE6FF range. + * + * Registers which require a synchronization delay: + * + * FIFORESET FIFOPINPOLAR + * INPKTEND EPxBCH:L + * EPxFIFOPFH:L EPxAUTOINLENH:L + * EPxFIFOCFG EPxGPIFFLGSEL + * PINFLAGSAB PINFLAGSCD + * EPxFIFOIE EPxFIFOIRQ + * GPIFIE GPIFIRQ + * UDMACRCH:L GPIFADRH:L + * GPIFTRIG EPxGPIFTRIG + * OUTPKTEND REVCTL + * GPIFTCB3 GPIFTCB2 + * GPIFTCB1 GPIFTCB0 + */ + +/* + * FIXME ensure that the peep hole optimizer isn't screwing us + */ +#define SYNCDELAY _asm nop; nop; nop; _endasm +#define NOP _asm nop; _endasm + + +#endif /* _SYNCDELAY_H_ */ diff --git a/usrp/firmware/include/timer.h b/usrp/firmware/include/timer.h new file mode 100644 index 00000000..7bb640e2 --- /dev/null +++ b/usrp/firmware/include/timer.h @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + +/* + * Arrange to have isr_tick_handler called at 100 Hz + */ +void hook_timer_tick (unsigned short isr_tick_handler); + +#define clear_timer_irq() \ + TF2 = 0 /* clear overflow flag */ + + +#endif /* _TIMER_H_ */ diff --git a/usrp/firmware/include/usb_common.h b/usrp/firmware/include/usb_common.h new file mode 100644 index 00000000..f8e26bee --- /dev/null +++ b/usrp/firmware/include/usb_common.h @@ -0,0 +1,37 @@ +/* -*- c -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _USB_COMMON_H_ +#define _USB_COMMON_H_ + +extern volatile bit _usb_got_SUDAV; + +// Provided by user application to handle VENDOR commands. +// returns non-zero if it handled the command. +unsigned char app_vendor_cmd (void); + +void usb_install_handlers (void); +void usb_handle_setup_packet (void); + +#define usb_setup_packet_avail() _usb_got_SUDAV + +#endif /* _USB_COMMON_H_ */ diff --git a/usrp/firmware/include/usb_descriptors.h b/usrp/firmware/include/usb_descriptors.h new file mode 100644 index 00000000..68390d7f --- /dev/null +++ b/usrp/firmware/include/usb_descriptors.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +extern xdata const char high_speed_device_descr[]; +extern xdata const char high_speed_devqual_descr[]; +extern xdata const char high_speed_config_descr[]; + +extern xdata const char full_speed_device_descr[]; +extern xdata const char full_speed_devqual_descr[]; +extern xdata const char full_speed_config_descr[]; + +extern xdata unsigned char nstring_descriptors; +extern xdata char * xdata string_descriptors[]; + +/* + * We patch these locations with info read from the usrp config eeprom + */ +extern xdata char usb_desc_hw_rev_binary_patch_location_0[]; +extern xdata char usb_desc_hw_rev_binary_patch_location_1[]; +extern xdata char usb_desc_hw_rev_ascii_patch_location_0[]; +extern xdata char usb_desc_serial_number_ascii[]; diff --git a/usrp/firmware/include/usb_requests.h b/usrp/firmware/include/usb_requests.h new file mode 100644 index 00000000..c4680b05 --- /dev/null +++ b/usrp/firmware/include/usb_requests.h @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Standard USB requests. +// These are contained in end point 0 setup packets + + +#ifndef _USB_REQUESTS_H_ +#define _USB_REQUESTS_H_ + +// format of bmRequestType byte + +#define bmRT_DIR_MASK (0x1 << 7) +#define bmRT_DIR_IN (1 << 7) +#define bmRT_DIR_OUT (0 << 7) + +#define bmRT_TYPE_MASK (0x3 << 5) +#define bmRT_TYPE_STD (0 << 5) +#define bmRT_TYPE_CLASS (1 << 5) +#define bmRT_TYPE_VENDOR (2 << 5) +#define bmRT_TYPE_RESERVED (3 << 5) + +#define bmRT_RECIP_MASK (0x1f << 0) +#define bmRT_RECIP_DEVICE (0 << 0) +#define bmRT_RECIP_INTERFACE (1 << 0) +#define bmRT_RECIP_ENDPOINT (2 << 0) +#define bmRT_RECIP_OTHER (3 << 0) + + +// standard request codes (bRequest) + +#define RQ_GET_STATUS 0 +#define RQ_CLEAR_FEATURE 1 +#define RQ_RESERVED_2 2 +#define RQ_SET_FEATURE 3 +#define RQ_RESERVED_4 4 +#define RQ_SET_ADDRESS 5 +#define RQ_GET_DESCR 6 +#define RQ_SET_DESCR 7 +#define RQ_GET_CONFIG 8 +#define RQ_SET_CONFIG 9 +#define RQ_GET_INTERFACE 10 +#define RQ_SET_INTERFACE 11 +#define RQ_SYNCH_FRAME 12 + +// standard descriptor types + +#define DT_DEVICE 1 +#define DT_CONFIG 2 +#define DT_STRING 3 +#define DT_INTERFACE 4 +#define DT_ENDPOINT 5 +#define DT_DEVQUAL 6 +#define DT_OTHER_SPEED 7 +#define DT_INTERFACE_POWER 8 + +// standard feature selectors + +#define FS_ENDPOINT_HALT 0 // recip: endpoint +#define FS_DEV_REMOTE_WAKEUP 1 // recip: device +#define FS_TEST_MODE 2 // recip: device + +// Get Status device attributes + +#define bmGSDA_SELF_POWERED 0x01 +#define bmGSDA_REM_WAKEUP 0x02 + + +#endif /* _USB_REQUESTS_H_ */ diff --git a/usrp/firmware/include/usrp_commands.h b/usrp/firmware/include/usrp_commands.h new file mode 100644 index 00000000..24878929 --- /dev/null +++ b/usrp/firmware/include/usrp_commands.h @@ -0,0 +1,99 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2004 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _USRP_COMMANDS_H_ +#define _USRP_COMMANDS_H_ + +#include +#include + +#define MAX_EP0_PKTSIZE 64 // max size of EP0 packet on FX2 + +// ---------------------------------------------------------------- +// Vendor bmRequestType's +// ---------------------------------------------------------------- + +#define VRT_VENDOR_IN 0xC0 +#define VRT_VENDOR_OUT 0x40 + +// ---------------------------------------------------------------- +// USRP Vendor Requests +// +// Note that Cypress reserves [0xA0,0xAF]. +// 0xA0 is the firmware load function. +// ---------------------------------------------------------------- + + +// IN commands + +#define VRQ_GET_STATUS 0x80 +#define GS_TX_UNDERRUN 0 // wIndexL // returns 1 byte +#define GS_RX_OVERRUN 1 // wIndexL // returns 1 byte + +#define VRQ_I2C_READ 0x81 // wValueL: i2c address; length: how much to read + +#define VRQ_SPI_READ 0x82 // wValue: optional header bytes + // wIndexH: enables + // wIndexL: format + // len: how much to read + +// OUT commands + +#define VRQ_SET_LED 0x01 // wValueL off/on {0,1}; wIndexL: which {0,1} + +#define VRQ_FPGA_LOAD 0x02 +# define FL_BEGIN 0 // wIndexL: begin fpga programming cycle. stalls if trouble. +# define FL_XFER 1 // wIndexL: xfer up to 64 bytes of data +# define FL_END 2 // wIndexL: end programming cycle, check for success. + // stalls endpoint if trouble. + +#define VRQ_FPGA_WRITE_REG 0x03 // wIndexL: regno; data: 32-bit regval MSB first +#define VRQ_FPGA_SET_RESET 0x04 // wValueL: {0,1} +#define VRQ_FPGA_SET_TX_ENABLE 0x05 // wValueL: {0,1} +#define VRQ_FPGA_SET_RX_ENABLE 0x06 // wValueL: {0,1} +// see below VRQ_FPGA_SET_{TX,RX}_RESET + +#define VRQ_SET_SLEEP_BITS 0x07 // wValueH: mask; wValueL: bits. set bits given by mask to bits + +# define SLEEP_ADC0 0x01 +# define SLEEP_ADC1 0x02 +# define SLEEP_DAC0 0x04 +# define SLEEP_DAC1 0x08 + +#define VRQ_I2C_WRITE 0x08 // wValueL: i2c address; data: data + +#define VRQ_SPI_WRITE 0x09 // wValue: optional header bytes + // wIndexH: enables + // wIndexL: format + // len: how much to write + +#define VRQ_FPGA_SET_TX_RESET 0x0a // wValueL: {0, 1} +#define VRQ_FPGA_SET_RX_RESET 0x0b // wValueL: {0, 1} + + +// ------------------------------------------------------------------- +// we store the hashes at fixed addresses in the FX2 internal memory + +#define USRP_HASH_SLOT_0_ADDR 0xe1e0 +#define USRP_HASH_SLOT_1_ADDR 0xe1f0 + + + +#endif /* _USRP_COMMANDS_H_ */ diff --git a/usrp/firmware/include/usrp_config.h b/usrp/firmware/include/usrp_config.h new file mode 100644 index 00000000..6d87665c --- /dev/null +++ b/usrp/firmware/include/usrp_config.h @@ -0,0 +1,44 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * configuration stuff for debugging + */ + +/* + * Define to 0 for normal use of port A, i.e., FPGA control bus. + * Define to 1 to write trace to port A for scoping with logic analyzer. + */ +#define UC_TRACE_USING_PORT_A 0 + + +/* + * Define to 0 for normal use of low 3 bits of port E, i.e., A/D, D/A SLEEP bits. + * Define to 1 to enable by default driving the GPIF state to the + * low three bits of port E. + */ +#define UC_START_WITH_GSTATE_OUTPUT_ENABLED 0 + + +/* + * Define to 1 for normal use (the board really has an FPGA on it). + * Define to 0 for debug use on board without FPGA. + */ +#define UC_BOARD_HAS_FPGA 1 diff --git a/usrp/firmware/include/usrp_i2c_addr.h b/usrp/firmware/include/usrp_i2c_addr.h new file mode 100644 index 00000000..738bf2e6 --- /dev/null +++ b/usrp/firmware/include/usrp_i2c_addr.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_USRP_I2C_ADDR_H +#define INCLUDED_USRP_I2C_ADDR_H + +// I2C addresses + +#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx + +#define I2C_ADDR_BOOT (I2C_DEV_EEPROM | 0x0) +#define I2C_ADDR_TX_A (I2C_DEV_EEPROM | 0x4) +#define I2C_ADDR_RX_A (I2C_DEV_EEPROM | 0x5) +#define I2C_ADDR_TX_B (I2C_DEV_EEPROM | 0x6) +#define I2C_ADDR_RX_B (I2C_DEV_EEPROM | 0x7) + + +// format of FX2 BOOT EEPROM +// 00: 0xC0 code for ``Read IDs from EEPROM'' +// 01: 0xFE USB Vendor ID (LSB) +// 02: 0xFF USB Vendor ID (MSB) +// 03: 0x02 USB Product ID (LSB) +// 04: 0x00 USB Product ID (MSB) +// 05: 0x01 USB Device ID (LSB) // rev1 +// 06: 0x00 USB Device ID (MSB) // 0 = unconfig'd (no firmware) +// 07: 0x00 option byte + + +// format of daughterboard EEPROM +// 00: 0xDB code for ``I'm a daughterboard'' +// 01: .. Daughterboard ID (LSB) +// 02: .. Daughterboard ID (MSB) +// 03: .. io bits 7-0 direction (bit set if it's an output from m'board) +// 04: .. io bits 15-8 direction (bit set if it's an output from m'board) +// 05: .. ADC0 DC offset correction (LSB) +// 06: .. ADC0 DC offset correction (MSB) +// 07: .. ADC1 DC offset correction (LSB) +// 08: .. ADC1 DC offset correction (MSB) +// ... +// 1f: .. negative of the sum of bytes [0x00, 0x1e] + +#define DB_EEPROM_MAGIC 0x00 +#define DB_EEPROM_MAGIC_VALUE 0xDB +#define DB_EEPROM_ID_LSB 0x01 +#define DB_EEPROM_ID_MSB 0x02 +#define DB_EEPROM_OE_LSB 0x03 +#define DB_EEPROM_OE_MSB 0x04 +#define DB_EEPROM_OFFSET_0_LSB 0x05 // offset correction for ADC or DAC 0 +#define DB_EEPROM_OFFSET_0_MSB 0x06 +#define DB_EEPROM_OFFSET_1_LSB 0x07 // offset correction for ADC or DAC 1 +#define DB_EEPROM_OFFSET_1_MSB 0x08 +#define DB_EEPROM_CHKSUM 0x1f + +#define DB_EEPROM_CLEN 0x20 // length of common portion of eeprom + +#define DB_EEPROM_CUSTOM_BASE DB_EEPROM_CLEN // first avail offset for + // daughterboard specific use + +#endif /* INCLUDED_USRP_I2C_ADDR_H */ + diff --git a/usrp/firmware/include/usrp_ids.h b/usrp/firmware/include/usrp_ids.h new file mode 100644 index 00000000..65c4755b --- /dev/null +++ b/usrp/firmware/include/usrp_ids.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * USB Vendor and Product IDs that we use + * + * (keep in sync with usb_descriptors.a51) + */ + +#ifndef _USRP_IDS_H_ +#define _USRP_IDS_H_ + +#define USB_VID_CYPRESS 0x04b4 +#define USB_PID_CYPRESS_FX2 0x8613 + + +#define USB_VID_FSF 0xfffe // Free Software Folks +#define USB_PID_FSF_EXP_0 0x0000 // Experimental 0 +#define USB_PID_FSF_EXP_1 0x0001 // Experimental 1 +#define USB_PID_FSF_USRP 0x0002 // Universal Software Radio Peripheral +#define USB_PID_FSF_USRP_reserved 0x0003 // Universal Software Radio Peripheral +#define USB_PID_FSF_SSRP 0x0004 // Simple Software Radio Peripheral +#define USB_PID_FSF_SSRP_reserved 0x0005 // Simple Software Radio Peripheral +#define USB_PID_FSF_HPSDR 0x0006 // High Performance Software Defined Radio (Internal Boot) +#define USB_PID_FSF_HPSDR_HA 0x0007 // High Performance Software Defined Radio (Host Assisted Boot) + +#define USB_PID_FSF_LBNL_UXO 0x0018 // http://recycle.lbl.gov/~ldoolitt/uxo/ + + +#define USB_DID_USRP_0 0x0000 // unconfigured rev 0 USRP +#define USB_DID_USRP_1 0x0001 // unconfigured rev 1 USRP +#define USB_DID_USRP_2 0x0002 // unconfigured rev 2 USRP + +#endif /* _USRP_IDS_H_ */ diff --git a/usrp/firmware/include/usrp_interfaces.h b/usrp/firmware/include/usrp_interfaces.h new file mode 100644 index 00000000..98432d1e --- /dev/null +++ b/usrp/firmware/include/usrp_interfaces.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _USRP_INTERFACES_H_ +#define _USRP_INTERFACES_H_ + +/* + * We've now split the USRP into 3 separate interfaces. + * + * Interface 0 contains only ep0 and is used for command and status. + * Interface 1 is the Tx path and it uses ep2 OUT BULK. + * Interface 2 is the Rx path and it uses ep6 IN BULK. + */ + +#define USRP_CMD_INTERFACE 0 +#define USRP_CMD_ALTINTERFACE 0 +#define USRP_CMD_ENDPOINT 0 + +#define USRP_TX_INTERFACE 1 +#define USRP_TX_ALTINTERFACE 0 +#define USRP_TX_ENDPOINT 2 // streaming data from host to FPGA + +#define USRP_RX_INTERFACE 2 +#define USRP_RX_ALTINTERFACE 0 +#define USRP_RX_ENDPOINT 6 // streaming data from FPGA to host + + +#endif /* _USRP_INTERFACES_H_ */ diff --git a/usrp/firmware/include/usrp_spi_defs.h b/usrp/firmware/include/usrp_spi_defs.h new file mode 100644 index 00000000..8404d7cb --- /dev/null +++ b/usrp/firmware/include/usrp_spi_defs.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP_SPI_DEFS_H +#define INCLUDED_USRP_SPI_DEFS_H + +/* + * defines for the VRQ_SPI_READ and VRQ_SPI_WRITE commands + * + * SPI == "Serial Port Interface". SPI is a 3 wire bus plus a + * separate enable for each peripheral. The common lines are SCLK, + * SDI and SDO. The FX2 always drives SCLK and SDI, the clock and + * data lines from the FX2 to the peripheral. When enabled, a + * peripheral may drive SDO, the data line from the peripheral to the + * FX2. + * + * The SPI_READ and SPI_WRITE commands are formatted identically. + * Each specifies which peripherals to enable, whether the bits should + * be transmistted Most Significant Bit first or Least Significant Bit + * first, the number of bytes in the optional header, and the number + * of bytes to read or write in the body. + * + * The body is limited to 64 bytes. The optional header may contain + * 0, 1 or 2 bytes. For an SPI_WRITE, the header bytes are + * transmitted to the peripheral followed by the the body bytes. For + * an SPI_READ, the header bytes are transmitted to the peripheral, + * then len bytes are read back from the peripheral. + */ + +/* + * SPI_FMT_* goes in wIndexL + */ +#define SPI_FMT_xSB_MASK (1 << 7) +# define SPI_FMT_LSB (1 << 7) // least signficant bit first +# define SPI_FMT_MSB (0 << 7) // most significant bit first +#define SPI_FMT_HDR_MASK (3 << 5) +# define SPI_FMT_HDR_0 (0 << 5) // 0 header bytes +# define SPI_FMT_HDR_1 (1 << 5) // 1 header byte +# define SPI_FMT_HDR_2 (2 << 5) // 2 header bytes + +/* + * SPI_ENABLE_* goes in wIndexH + * + * For the software interface, the enables are active high. + * For reads, it's an error to have more than one enable set. + * + * [FWIW, the hardware implements them as active low. Don't change the + * definitions of these. They are related to usrp_rev1_regs.h] + */ +#define SPI_ENABLE_FPGA 0x01 // select FPGA +#define SPI_ENABLE_CODEC_A 0x02 // select AD9862 A +#define SPI_ENABLE_CODEC_B 0x04 // select AD9862 B +#define SPI_ENABLE_reserved 0x08 +#define SPI_ENABLE_TX_A 0x10 // select d'board TX A +#define SPI_ENABLE_RX_A 0x20 // select d'board RX A +#define SPI_ENABLE_TX_B 0x40 // select d'board TX B +#define SPI_ENABLE_RX_B 0x80 // select d'board RX B + +/* + * If there's one header byte, it goes in wValueL. + * + * If there are two header bytes, they go in wValueH | wValueL. + * The transmit order of the bytes (and bits within them) is + * determined by SPI_FMT_*SB + */ + +#endif /* INCLUDED_USRP_SPI_DEFS_H */ diff --git a/usrp/firmware/lib/Makefile.am b/usrp/firmware/lib/Makefile.am new file mode 100644 index 00000000..3ddafcf1 --- /dev/null +++ b/usrp/firmware/lib/Makefile.am @@ -0,0 +1,83 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + delay.c \ + fx2utils.c \ + i2c.c \ + isr.c \ + timer.c \ + usb_common.c + + + +DEFINES= +INCLUDES=-I$(top_srcdir)/usrp/firmware/include + +# with EA = 0, the FX2 implements a portion of the 8051 "external memory" +# on chip. This memory is mapped like this: +# +# The bottom 8K of memory (0x0000 - 0x1fff) is used for both data and +# code accesses. There's also 512 bytes for data only from 0xe000 - 0xe1ff. +# +# We tell the linker to start the xdata segment at 0x1800, 6K up from +# the bottom. + +LINKOPTS = --code-loc 0x0000 --code-size 0x1800 --xram-loc 0x1800 --xram-size 0x0800 + +LIBRARY = libfx2.lib + +LIBOBJS = \ + delay.rel \ + fx2utils.rel \ + i2c.rel \ + isr.rel \ + timer.rel \ + usb_common.rel + + + +all: libfx2.lib + +%.rel : %.c + $(XCC) $(INCLUDES) $(DEFINES) -c $< -o $@ + +%.rel : %.a51 + $(XAS) $< + + +$(LIBRARY): $(LIBOBJS) + -rm -f $(LIBRARY) + touch $(LIBRARY) + for obj in $(LIBOBJS); do basename $$obj .rel >> $(LIBRARY) ; done + + +CLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib + +DISTCLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib + +install: all + + +# dependencies + diff --git a/usrp/firmware/lib/delay.c b/usrp/firmware/lib/delay.c new file mode 100644 index 00000000..c8bad7f2 --- /dev/null +++ b/usrp/firmware/lib/delay.c @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Delay approximately 1 microsecond (including overhead in udelay). + */ +static void +udelay1 (void) _naked +{ + _asm ; lcall that got us here took 4 bus cycles + ret ; 4 bus cycles + _endasm; +} + +/* + * delay for approximately usecs microseconds + */ +void +udelay (unsigned char usecs) +{ + do { + udelay1 (); + } while (--usecs != 0); +} + + +/* + * Delay approximately 1 millisecond. + * We're running at 48 MHz, so we need 48,000 clock cycles. + * + * Note however, that each bus cycle takes 4 clock cycles (not obvious, + * but explains the factor of 4 problem below). + */ +static void +mdelay1 (void) _naked +{ + _asm + mov dptr,#(-1200 & 0xffff) +002$: + inc dptr ; 3 bus cycles + mov a, dpl ; 2 bus cycles + orl a, dph ; 2 bus cycles + jnz 002$ ; 3 bus cycles + + ret + _endasm; +} + +void +mdelay (unsigned int msecs) +{ + do { + mdelay1 (); + } while (--msecs != 0); +} + + diff --git a/usrp/firmware/lib/fx2utils.c b/usrp/firmware/lib/fx2utils.c new file mode 100644 index 00000000..544302e8 --- /dev/null +++ b/usrp/firmware/lib/fx2utils.c @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "fx2utils.h" +#include "fx2regs.h" +#include "delay.h" + +void +fx2_stall_ep0 (void) +{ + EP0CS |= bmEPSTALL; +} + +void +fx2_reset_data_toggle (unsigned char ep) +{ + TOGCTL = ((ep & 0x80) >> 3 | (ep & 0x0f)); + TOGCTL |= bmRESETTOGGLE; +} + +void +fx2_renumerate (void) +{ + USBCS |= bmDISCON | bmRENUM; + + // mdelay (1500); // FIXME why 1.5 seconds? + mdelay (250); // FIXME why 1.5 seconds? + + USBIRQ = 0xff; // clear any pending USB irqs... + EPIRQ = 0xff; // they're from before the renumeration + + EXIF &= ~bmEXIF_USBINT; + + USBCS &= ~bmDISCON; // reconnect USB +} diff --git a/usrp/firmware/lib/i2c-compiler-bug.c b/usrp/firmware/lib/i2c-compiler-bug.c new file mode 100644 index 00000000..ae97f1af --- /dev/null +++ b/usrp/firmware/lib/i2c-compiler-bug.c @@ -0,0 +1,129 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "i2c.h" +#include "fx2regs.h" +#include + + +// issue a stop bus cycle and wait for completion + + +// returns non-zero if successful, else 0 +unsigned char +i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len) +{ + volatile unsigned char junk; + + if (len == 0) // reading zero bytes always works + return 1; + + // memset (buf, 0, len); // FIXME, remove + + while (I2CS & bmSTOP) // wait for stop to clear + ; + + + I2CS = bmSTART; + I2DAT = (addr << 1) | 1; // write address and direction (1's the read bit) + + while ((I2CS & bmDONE) == 0) + ; + + if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered... + goto fail; + + if (len == 1) + I2CS |= bmLASTRD; + + junk = I2DAT; // trigger the first read cycle + +#if 1 + while (len != 1){ + while ((I2CS & bmDONE) == 0) + ; + + if (I2CS & bmBERR) + goto fail; + + len--; + if (len == 1) + I2CS |= bmLASTRD; + + *buf++ = I2DAT; // get data, trigger another read + } +#endif + + // wait for final byte + + while ((I2CS & bmDONE) == 0) + ; + + if (I2CS & bmBERR) + goto fail; + + I2CS |= bmSTOP; + *buf = I2DAT; + + return 1; + + fail: + I2CS |= bmSTOP; + return 0; +} + + + +// returns non-zero if successful, else 0 +unsigned char +i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len) +{ + while (I2CS & bmSTOP) // wait for stop to clear + ; + + I2CS = bmSTART; + I2DAT = (addr << 1) | 0; // write address and direction (0's the write bit) + + while ((I2CS & bmDONE) == 0) + ; + + if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered... + goto fail; + + while (len > 0){ + I2DAT = *buf++; + len--; + + while ((I2CS & bmDONE) == 0) + ; + + if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered... + goto fail; + } + + I2CS |= bmSTOP; + return 1; + + fail: + I2CS |= bmSTOP; + return 0; +} diff --git a/usrp/firmware/lib/i2c.c b/usrp/firmware/lib/i2c.c new file mode 100644 index 00000000..08a09cf0 --- /dev/null +++ b/usrp/firmware/lib/i2c.c @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "i2c.h" +#include "fx2regs.h" +#include + + +// issue a stop bus cycle and wait for completion + + +// returns non-zero if successful, else 0 +unsigned char +i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len) +{ + volatile unsigned char junk; + + if (len == 0) // reading zero bytes always works + return 1; + + while (I2CS & bmSTOP) // wait for stop to clear + ; + + I2CS = bmSTART; + I2DAT = (addr << 1) | 1; // write address and direction (1's the read bit) + + while ((I2CS & bmDONE) == 0) + ; + + if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered... + goto fail; + + if (len == 1) + I2CS |= bmLASTRD; + + junk = I2DAT; // trigger the first read cycle + + while (--len != 0){ + while ((I2CS & bmDONE) == 0) + ; + + if (I2CS & bmBERR) + goto fail; + + if (len == 1) + I2CS |= bmLASTRD; + + *buf++ = I2DAT; // get data, trigger another read + } + + // wait for final byte + + while ((I2CS & bmDONE) == 0) + ; + + if (I2CS & bmBERR) + goto fail; + + I2CS |= bmSTOP; + *buf = I2DAT; + + return 1; + + fail: + I2CS |= bmSTOP; + return 0; +} + + + +// returns non-zero if successful, else 0 +unsigned char +i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len) +{ + while (I2CS & bmSTOP) // wait for stop to clear + ; + + I2CS = bmSTART; + I2DAT = (addr << 1) | 0; // write address and direction (0's the write bit) + + while ((I2CS & bmDONE) == 0) + ; + + if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered... + goto fail; + + while (len > 0){ + I2DAT = *buf++; + len--; + + while ((I2CS & bmDONE) == 0) + ; + + if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered... + goto fail; + } + + I2CS |= bmSTOP; + return 1; + + fail: + I2CS |= bmSTOP; + return 0; +} diff --git a/usrp/firmware/lib/isr.c b/usrp/firmware/lib/isr.c new file mode 100644 index 00000000..7a201072 --- /dev/null +++ b/usrp/firmware/lib/isr.c @@ -0,0 +1,167 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "isr.h" +#include "fx2regs.h" +#include "syncdelay.h" + +extern xdata unsigned char _standard_interrupt_vector[]; +extern xdata unsigned char _usb_autovector[]; +extern xdata unsigned char _fifo_gpif_autovector[]; + +#define LJMP_OPCODE 0x02 + +/* + * Hook standard interrupt vector. + * + * vector_number is from the SV_ list. + * addr is the address of the interrupt service routine. + */ +void +hook_sv (unsigned char vector_number, unsigned short addr) +{ + bit t; + + // sanity checks + + if (vector_number < SV_MIN || vector_number > SV_MAX) + return; + + if ((vector_number & 0x0f) != 0x03 && (vector_number & 0x0f) != 0x0b) + return; + + t = EA; + EA = 0; + _standard_interrupt_vector[vector_number] = LJMP_OPCODE; + _standard_interrupt_vector[vector_number + 1] = addr >> 8; + _standard_interrupt_vector[vector_number + 2] = addr & 0xff; + EA = t; +} + +/* + * Hook usb interrupt vector. + * + * vector_number is from the UV_ list. + * addr is the address of the interrupt service routine. + */ +void +hook_uv (unsigned char vector_number, unsigned short addr) +{ + bit t; + + // sanity checks + + if (vector_number < UV_MIN || vector_number > UV_MAX) + return; + + if ((vector_number & 0x3) != 0) + return; + + t = EA; + EA = 0; + _usb_autovector[vector_number] = LJMP_OPCODE; + _usb_autovector[vector_number + 1] = addr >> 8; + _usb_autovector[vector_number + 2] = addr & 0xff; + EA = t; +} + +/* + * Hook fifo/gpif interrupt vector. + * + * vector_number is from the FGV_ list. + * addr is the address of the interrupt service routine. + */ +void +hook_fgv (unsigned char vector_number, unsigned short addr) +{ + bit t; + + // sanity checks + + if (vector_number < FGV_MIN || vector_number > FGV_MAX) + return; + + if ((vector_number & 0x3) != 0) + return; + + t = EA; + EA = 0; + _fifo_gpif_autovector[vector_number] = LJMP_OPCODE; + _fifo_gpif_autovector[vector_number + 1] = addr >> 8; + _fifo_gpif_autovector[vector_number + 2] = addr & 0xff; + EA = t; +} + +/* + * One time call to enable autovectoring for both USB and FIFO/GPIF. + * + * This disables all USB and FIFO/GPIF interrupts and clears + * any pending interrupts too. It leaves the master USB and FIFO/GPIF + * interrupts enabled. + */ +void +setup_autovectors (void) +{ + // disable master usb and fifo/gpif interrupt enables + EIUSB = 0; + EIEX4 = 0; + + hook_sv (SV_INT_2, (unsigned short) _usb_autovector); + hook_sv (SV_INT_4, (unsigned short) _fifo_gpif_autovector); + + // disable all fifo interrupt enables + SYNCDELAY; + EP2FIFOIE = 0; SYNCDELAY; + EP4FIFOIE = 0; SYNCDELAY; + EP6FIFOIE = 0; SYNCDELAY; + EP8FIFOIE = 0; SYNCDELAY; + + // clear all pending fifo irqs + EP2FIFOIRQ = 0xff; SYNCDELAY; + EP4FIFOIRQ = 0xff; SYNCDELAY; + EP6FIFOIRQ = 0xff; SYNCDELAY; + EP8FIFOIRQ = 0xff; SYNCDELAY; + + IBNIE = 0; + IBNIRQ = 0xff; + NAKIE = 0; + NAKIRQ = 0xff; + USBIE = 0; + USBIRQ = 0xff; + EPIE = 0; + EPIRQ = 0xff; + SYNCDELAY; GPIFIE = 0; + SYNCDELAY; GPIFIRQ = 0xff; + USBERRIE = 0; + USBERRIRQ = 0xff; + CLRERRCNT = 0; + + INTSETUP = bmAV2EN | bmAV4EN | bmINT4IN; + + // clear master irq's for usb and fifo/gpif + EXIF &= ~bmEXIF_USBINT; + EXIF &= ~bmEXIF_IE4; + + // enable master usb and fifo/gpif interrrupts + EIUSB = 1; + EIEX4 = 1; +} diff --git a/usrp/firmware/lib/timer.c b/usrp/firmware/lib/timer.c new file mode 100644 index 00000000..9e396f46 --- /dev/null +++ b/usrp/firmware/lib/timer.c @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "timer.h" +#include "fx2regs.h" +#include "isr.h" + +/* + * Arrange to have isr_tick_handler called at 100 Hz. + * + * The cpu clock is running at 48e6. The input to the timer + * is 48e6 / 12 = 4e6. + * + * We arrange to have the timer overflow every 40000 clocks == 100 Hz + */ + +#define RELOAD_VALUE ((unsigned short) -40000) + +void +hook_timer_tick (unsigned short isr_tick_handler) +{ + ET2 = 0; // disable timer 2 interrupts + hook_sv (SV_TIMER_2, isr_tick_handler); + + RCAP2H = RELOAD_VALUE >> 8; // setup the auto reload value + RCAP2L = RELOAD_VALUE; + + T2CON = 0x04; // interrupt on overflow; reload; run + ET2 = 1; // enable timer 2 interrupts +} diff --git a/usrp/firmware/lib/usb_common.c b/usrp/firmware/lib/usb_common.c new file mode 100644 index 00000000..731fd685 --- /dev/null +++ b/usrp/firmware/lib/usb_common.c @@ -0,0 +1,385 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "usb_common.h" +#include "fx2regs.h" +#include "syncdelay.h" +#include "fx2utils.h" +#include "isr.h" +#include "usb_descriptors.h" +#include "usb_requests.h" + +extern xdata char str0[]; +extern xdata char str1[]; +extern xdata char str2[]; +extern xdata char str3[]; +extern xdata char str4[]; +extern xdata char str5[]; + + +#define bRequestType SETUPDAT[0] +#define bRequest SETUPDAT[1] +#define wValueL SETUPDAT[2] +#define wValueH SETUPDAT[3] +#define wIndexL SETUPDAT[4] +#define wIndexH SETUPDAT[5] +#define wLengthL SETUPDAT[6] +#define wLengthH SETUPDAT[7] + +#define MSB(x) (((unsigned short) x) >> 8) +#define LSB(x) (((unsigned short) x) & 0xff) + +volatile bit _usb_got_SUDAV; + +unsigned char _usb_config = 0; +unsigned char _usb_alt_setting = 0; // FIXME really 1/interface + +xdata unsigned char *current_device_descr; +xdata unsigned char *current_devqual_descr; +xdata unsigned char *current_config_descr; +xdata unsigned char *other_config_descr; + +static void +setup_descriptors (void) +{ + if (USBCS & bmHSM){ // high speed mode + current_device_descr = high_speed_device_descr; + current_devqual_descr = high_speed_devqual_descr; + current_config_descr = high_speed_config_descr; + other_config_descr = full_speed_config_descr; + } + else { + current_device_descr = full_speed_device_descr; + current_devqual_descr = full_speed_devqual_descr; + current_config_descr = full_speed_config_descr; + other_config_descr = high_speed_config_descr; + } + + // whack the type fields + // FIXME, may not be required. + // current_config_descr[1] = DT_CONFIG; + // other_config_descr[1] = DT_OTHER_SPEED; +} + +static void +isr_SUDAV (void) interrupt +{ + clear_usb_irq (); + _usb_got_SUDAV = 1; +} + +static void +isr_USBRESET (void) interrupt +{ + clear_usb_irq (); + setup_descriptors (); +} + +static void +isr_HIGHSPEED (void) interrupt +{ + clear_usb_irq (); + setup_descriptors (); +} + +void +usb_install_handlers (void) +{ + setup_descriptors (); // ensure that they're set before use + + hook_uv (UV_SUDAV, (unsigned short) isr_SUDAV); + hook_uv (UV_USBRESET, (unsigned short) isr_USBRESET); + hook_uv (UV_HIGHSPEED, (unsigned short) isr_HIGHSPEED); + + USBIE = bmSUDAV | bmURES | bmHSGRANT; +} + +// On the FX2 the only plausible endpoints are 0, 1, 2, 4, 6, 8 +// This doesn't check to see that they're enabled + +unsigned char +plausible_endpoint (unsigned char ep) +{ + ep &= ~0x80; // ignore direction bit + + if (ep > 8) + return 0; + + if (ep == 1) + return 1; + + return (ep & 0x1) == 0; // must be even +} + +// return pointer to control and status register for endpoint. +// only called with plausible_endpoints + +xdata volatile unsigned char * +epcs (unsigned char ep) +{ + if (ep == 0x01) // ep1 has different in and out CS regs + return EP1OUTCS; + + if (ep == 0x81) + return EP1INCS; + + ep &= ~0x80; // ignore direction bit + + if (ep == 0x00) // ep0 + return EP0CS; + + return EP2CS + (ep >> 1); // 2, 4, 6, 8 are consecutive +} + +void +usb_handle_setup_packet (void) +{ + _usb_got_SUDAV = 0; + + // handle the standard requests... + + switch (bRequestType & bmRT_TYPE_MASK){ + + case bmRT_TYPE_CLASS: + case bmRT_TYPE_RESERVED: + fx2_stall_ep0 (); // we don't handle these. indicate error + break; + + case bmRT_TYPE_VENDOR: + // call the application code. + // If it handles the command it returns non-zero + + if (!app_vendor_cmd ()) + fx2_stall_ep0 (); + break; + + case bmRT_TYPE_STD: + // these are the standard requests... + + if ((bRequestType & bmRT_DIR_MASK) == bmRT_DIR_IN){ + + //////////////////////////////////// + // handle the IN requests + //////////////////////////////////// + + switch (bRequest){ + + case RQ_GET_CONFIG: + EP0BUF[0] = _usb_config; // FIXME app should handle + EP0BCH = 0; + EP0BCL = 1; + break; + + // -------------------------------- + + case RQ_GET_INTERFACE: + EP0BUF[0] = _usb_alt_setting; // FIXME app should handle + EP0BCH = 0; + EP0BCL = 1; + break; + + // -------------------------------- + + case RQ_GET_DESCR: + switch (wValueH){ + + case DT_DEVICE: + SUDPTRH = MSB (current_device_descr); + SUDPTRL = LSB (current_device_descr); + break; + + case DT_DEVQUAL: + SUDPTRH = MSB (current_devqual_descr); + SUDPTRL = LSB (current_devqual_descr); + break; + + case DT_CONFIG: + if (0 && wValueL != 1) // FIXME only a single configuration + fx2_stall_ep0 (); + else { + SUDPTRH = MSB (current_config_descr); + SUDPTRL = LSB (current_config_descr); + } + break; + + case DT_OTHER_SPEED: + if (0 && wValueL != 1) // FIXME only a single configuration + fx2_stall_ep0 (); + else { + SUDPTRH = MSB (other_config_descr); + SUDPTRL = LSB (other_config_descr); + } + break; + + case DT_STRING: + if (wValueL >= nstring_descriptors) + fx2_stall_ep0 (); + else { + xdata char *p = string_descriptors[wValueL]; + SUDPTRH = MSB (p); + SUDPTRL = LSB (p); + } + break; + + default: + fx2_stall_ep0 (); // invalid request + break; + } + break; + + // -------------------------------- + + case RQ_GET_STATUS: + switch (bRequestType & bmRT_RECIP_MASK){ + case bmRT_RECIP_DEVICE: + EP0BUF[0] = bmGSDA_SELF_POWERED; // FIXME app should handle + EP0BUF[1] = 0; + EP0BCH = 0; + EP0BCL = 2; + break; + + case bmRT_RECIP_INTERFACE: + EP0BUF[0] = 0; + EP0BUF[1] = 0; + EP0BCH = 0; + EP0BCL = 2; + break; + + case bmRT_RECIP_ENDPOINT: + if (plausible_endpoint (wIndexL)){ + EP0BUF[0] = *epcs (wIndexL) & bmEPSTALL; + EP0BUF[1] = 0; + EP0BCH = 0; + EP0BCL = 2; + } + else + fx2_stall_ep0 (); + break; + + default: + fx2_stall_ep0 (); + break; + } + + // -------------------------------- + + case RQ_SYNCH_FRAME: // not implemented + default: + fx2_stall_ep0 (); + break; + } + } + + else { + + //////////////////////////////////// + // handle the OUT requests + //////////////////////////////////// + + switch (bRequest){ + + case RQ_SET_CONFIG: + _usb_config = wValueL; // FIXME app should handle + break; + + case RQ_SET_INTERFACE: + _usb_alt_setting = wValueL; // FIXME app should handle + break; + + // -------------------------------- + + case RQ_CLEAR_FEATURE: + switch (bRequestType & bmRT_RECIP_MASK){ + + case bmRT_RECIP_DEVICE: + switch (wValueL){ + case FS_DEV_REMOTE_WAKEUP: + default: + fx2_stall_ep0 (); + } + break; + + case bmRT_RECIP_ENDPOINT: + if (wValueL == FS_ENDPOINT_HALT && plausible_endpoint (wIndexL)){ + *epcs (wIndexL) &= ~bmEPSTALL; + fx2_reset_data_toggle (wIndexL); + } + else + fx2_stall_ep0 (); + break; + + default: + fx2_stall_ep0 (); + break; + } + break; + + // -------------------------------- + + case RQ_SET_FEATURE: + switch (bRequestType & bmRT_RECIP_MASK){ + + case bmRT_RECIP_DEVICE: + switch (wValueL){ + case FS_TEST_MODE: + // hardware handles this after we complete SETUP phase handshake + break; + + case FS_DEV_REMOTE_WAKEUP: + default: + fx2_stall_ep0 (); + break; + } + } + break; + + case bmRT_RECIP_ENDPOINT: + switch (wValueL){ + case FS_ENDPOINT_HALT: + if (plausible_endpoint (wIndexL)) + *epcs (wIndexL) |= bmEPSTALL; + else + fx2_stall_ep0 (); + break; + + default: + fx2_stall_ep0 (); + break; + } + break; + + // -------------------------------- + + case RQ_SET_ADDRESS: // handled by fx2 hardware + case RQ_SET_DESCR: // not implemented + default: + fx2_stall_ep0 (); + } + + } + break; + + } // bmRT_TYPE_MASK + + // ack handshake phase of device request + EP0CS |= bmHSNAK; +} diff --git a/usrp/firmware/src/Makefile.am b/usrp/firmware/src/Makefile.am new file mode 100644 index 00000000..e4801372 --- /dev/null +++ b/usrp/firmware/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = common usrp2 diff --git a/usrp/firmware/src/common/Makefile.am b/usrp/firmware/src/common/Makefile.am new file mode 100644 index 00000000..ba3c0e4e --- /dev/null +++ b/usrp/firmware/src/common/Makefile.am @@ -0,0 +1,50 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + _startup.a51 \ + blink_leds.c \ + check_mdelay.c \ + check_udelay.c \ + edit-gpif \ + fpga.h \ + fpga_load.h \ + fpga_load.c \ + gpif.c \ + gpif.gpf \ + init_gpif.c \ + usrp_common.c \ + usrp_globals.h \ + vectors.a51 \ + build_eeprom.py + +all: usrp_gpif.c + +usrp_gpif.c usrp_gpif_inline.h : gpif.c + srcdir=$(srcdir) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h + +CLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h + +DISTCLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h diff --git a/usrp/firmware/src/common/_startup.a51 b/usrp/firmware/src/common/_startup.a51 new file mode 100644 index 00000000..0bffbbee --- /dev/null +++ b/usrp/firmware/src/common/_startup.a51 @@ -0,0 +1,80 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003,2004 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;;; Boston, MA 02111-1307, USA. + + +;;; The default external memory initialization provided by sdcc is not +;;; appropriate to the FX2. This is derived from the sdcc code, but uses +;;; the FX2 specific _MPAGE sfr. + + + ;; .area XISEG (XDATA) ; the initialized external data area + ;; .area XINIT (CODE) ; the code space consts to init XISEG + .area XSEG (XDATA) ; zero initialized xdata + .area USBDESCSEG (XDATA) ; usb descriptors + + + .area CSEG (CODE) + + ;; sfr that sets upper address byte of MOVX using @r0 or @r1 + _MPAGE = 0x0092 + +__sdcc_external_startup:: + ;; This system is now compiled with the --no-xinit-opt + ;; which means that any initialized XDATA is handled + ;; inline by code in the GSINIT segs emitted for each file. + ;; + ;; We zero XSEG and all of the internal ram to ensure + ;; a known good state for uninitialized variables. + +; _mcs51_genRAMCLEAR() start + mov r0,#l_XSEG + mov a,r0 + orl a,#(l_XSEG >> 8) + jz 00002$ + mov r1,#((l_XSEG + 255) >> 8) + mov dptr,#s_XSEG + clr a + +00001$: movx @dptr,a + inc dptr + djnz r0,00001$ + djnz r1,00001$ + + ;; We're about to clear internal memory. This will overwrite + ;; the stack which contains our return address. + ;; Pop our return address into DPH, DPL +00002$: pop dph + pop dpl + + ;; R0 and A contain 0. This loop will execute 256 times. + ;; + ;; FWIW the first iteration writes direct address 0x00, + ;; which is the location of r0. We get lucky, we're + ;; writing the correct value (0) + +00003$: mov @r0,a + djnz r0,00003$ + + push dpl ; restore our return address + push dph + + mov dpl,#0 ; indicate that data init is still required + ret diff --git a/usrp/firmware/src/common/_startup.a51.brittle b/usrp/firmware/src/common/_startup.a51.brittle new file mode 100644 index 00000000..1238f3d7 --- /dev/null +++ b/usrp/firmware/src/common/_startup.a51.brittle @@ -0,0 +1,78 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;;; Boston, MA 02111-1307, USA. + + +;;; The default external memory initialization provided by sdcc is not +;;; appropriate to the FX2. This is derived from the sdcc code, but uses +;;; the FX2 specific _MPAGE sfr. + + + .area XISEG (XDATA) ; the initialized external data area + .area XINIT (CODE) ; the code space consts to init XISEG + .area XSEG (XDATA) ; zero initialized xdata + .area USBDESCSEG (XDATA); usb descriptors + + + ;; BIG TIME KLUDGE! + ;; Look at usrp_main.rst and count the bytes from our + ;; "normal return location" to the first instruction following + ;; the comment: "_mcs51_getRAMCLEAR () start" + + INSTRUCTION_BYTES_TO_SKIP = 0x29 ; valid for sdcc 2.4.0 + + + .area CSEG (CODE) + + ;; sfr that sets upper address byte of MOVX using @r0 or @r1 + _MPAGE = 0x0092 + +__sdcc_external_startup:: +; _mcs51_genXINIT() start + mov r1,#l_XINIT + mov a,r1 + orl a,#(l_XINIT >> 8) + jz 00003$ + mov r2,#((l_XINIT+255) >> 8) + mov dptr,#s_XINIT + mov r0,#s_XISEG + mov _MPAGE,#(s_XISEG >> 8) +00001$: clr a + movc a,@a+dptr + movx @r0,a + inc dptr + inc r0 + cjne r0,#0,00002$ + inc _MPAGE +00002$: djnz r1,00001$ + djnz r2,00001$ + mov _MPAGE,#0xFF +00003$: + + ;; Danger! Total KLUDGE! + ;; We pop the return address, add a magic number to it + ;; then jump to that address. Believe it or not, this + ;; looks like the least kludgy way to handle this, + ;; short of patching the compiler... + + pop dph + pop dpl + mov a,#INSTRUCTION_BYTES_TO_SKIP + jmp @a+dptr diff --git a/usrp/firmware/src/common/blink_leds.c b/usrp/firmware/src/common/blink_leds.c new file mode 100644 index 00000000..4654e73c --- /dev/null +++ b/usrp/firmware/src/common/blink_leds.c @@ -0,0 +1,36 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "usrp_common.h" + +void +main (void) +{ + unsigned short counter = 0; + + init_usrp (); + + while (1){ + unsigned char counter_high = counter >> 8; + set_led_0 (counter_high & 0x40); + set_led_1 (counter_high & 0x80); + counter++; + } +} diff --git a/usrp/firmware/src/common/build_eeprom.py b/usrp/firmware/src/common/build_eeprom.py new file mode 100755 index 00000000..66120592 --- /dev/null +++ b/usrp/firmware/src/common/build_eeprom.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import re +import sys +import os, os.path +from optparse import OptionParser + +# USB Vendor and Product ID's + +VID = 0xfffe # Free Software Folks +PID = 0x0002 # Universal Software Radio Peripheral + + +def hex_to_bytes (s): + if len (s) & 0x1: + raise ValueError, "Length must be even" + r = [] + for i in range (0, len(s), 2): + r.append (int (s[i:i+2], 16)) + return r + +def msb (x): + return (x >> 8) & 0xff + +def lsb (x): + return x & 0xff + +class ihx_rec (object): + def __init__ (self, addr, type, data): + self.addr = addr + self.type = type + self.data = data + +class ihx_file (object): + def __init__ (self): + self.pat = re.compile (r':[0-9A-F]{10,}') + def read (self, file): + r = [] + for line in file: + line = line.strip().upper () + if not self.pat.match (line): + raise ValueError, "Invalid hex record format" + bytes = hex_to_bytes (line[1:]) + sum = reduce (lambda x, y: x + y, bytes, 0) % 256 + if sum != 0: + raise ValueError, "Bad hex checksum" + lenx = bytes[0] + addr = (bytes[1] << 8) + bytes[2] + type = bytes[3] + data = bytes[4:-1] + if lenx != len (data): + raise ValueError, "Invalid hex record (bad length)" + if type != 0: + break; + r.append (ihx_rec (addr, type, data)) + + return r + +def get_code (filename): + """Read the intel hex format file FILENAME and return a tuple + of the code starting address and a list of bytes to load there. + """ + f = open (filename, 'r') + ifx = ihx_file () + r = ifx.read (f) + r.sort (lambda a,b: a.addr - b.addr) + code_start = r[0].addr + code_end = r[-1].addr + len (r[-1].data) + code_len = code_end - code_start + code = [0] * code_len + for x in r: + a = x.addr + l = len (x.data) + code[a-code_start:a-code_start+l] = x.data + return (code_start, code) + + +def build_eeprom_image (filename, rev): + """Build a ``C2 Load'' EEPROM image. + + For details on this format, see section 3.4.3 of + the EZ-USB FX2 Technical Reference Manual + """ + # get the code we want to run + (start_addr, bytes) = get_code (filename) + + devid = rev + + rom_header = [ + 0xC2, # boot from EEPROM + lsb (VID), + msb (VID), + lsb (PID), + msb (PID), + lsb (devid), + msb (devid), + 0 # configuration byte + ] + + # 4 byte header that indicates where to load + # the immediately follow code bytes. + code_header = [ + msb (len (bytes)), + lsb (len (bytes)), + msb (start_addr), + lsb (start_addr) + ] + + # writes 0 to CPUCS reg (brings FX2 out of reset) + trailer = [ + 0x80, + 0x01, + 0xe6, + 0x00, + 0x00 + ] + + image = rom_header + code_header + bytes + trailer + + assert (len (image) <= 256) + return image + +def build_shell_script (out, ihx_filename, rev): + + image = build_eeprom_image (ihx_filename, rev) + + out.write ('#!/bin/sh\n') + out.write ('usrper -x load_firmware /usr/local/share/usrp/rev%d/std.ihx\n' % rev) + out.write ('sleep 1\n') + + # print "len(image) =", len(image) + + i2c_addr = 0x50 + rom_addr = 0x00 + + hex_image = map (lambda x : "%02x" % (x,), image) + + while (len (hex_image) > 0): + l = min (len (hex_image), 16) + out.write ('usrper i2c_write 0x%02x %02x%s\n' % + (i2c_addr, rom_addr, ''.join (hex_image[0:l]))) + hex_image = hex_image[l:] + rom_addr = rom_addr + l + out.write ('sleep 1\n') + +if __name__ == '__main__': + usage = "usage: %prog -r REV [options] bootfile.ihx" + parser = OptionParser (usage=usage) + parser.add_option ("-r", "--rev", type="int", default=-1, + help="Specify USRP revision number REV (2 or 4)") + (options, args) = parser.parse_args () + if len (args) != 1: + parser.print_help () + sys.exit (1) + if options.rev < 0: + sys.stderr.write ( + "You must specify the USRP revision number (2 or 4) with -r REV\n") + sys.exit (1) + + ihx_filename = args[0] + + build_shell_script (sys.stdout, ihx_filename, options.rev) diff --git a/usrp/firmware/src/common/check_mdelay.c b/usrp/firmware/src/common/check_mdelay.c new file mode 100644 index 00000000..8cdadab6 --- /dev/null +++ b/usrp/firmware/src/common/check_mdelay.c @@ -0,0 +1,37 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "usrp_common.h" +#include "delay.h" + +void +main (void) +{ + init_usrp (); + + // CPUCS = 0; // 12 MHz + // CPUCS = bmCLKSPD0; // 24 MHz + CPUCS = bmCLKSPD1; // 48 MHz + + while (1){ + USRP_LED_REG ^= bmLED0; + mdelay (10); + } +} diff --git a/usrp/firmware/src/common/check_udelay.c b/usrp/firmware/src/common/check_udelay.c new file mode 100644 index 00000000..6e1c8400 --- /dev/null +++ b/usrp/firmware/src/common/check_udelay.c @@ -0,0 +1,37 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "usrp_common.h" +#include "delay.h" + +void +main (void) +{ + init_usrp (); + + // CPUCS = 0; // 12 MHz + // CPUCS = bmCLKSPD0; // 24 MHz + CPUCS = bmCLKSPD1; // 48 MHz + + while (1){ + USRP_LED_REG ^= bmLED0; + udelay (250); + } +} diff --git a/usrp/firmware/src/common/edit-gpif b/usrp/firmware/src/common/edit-gpif new file mode 100755 index 00000000..c507f502 --- /dev/null +++ b/usrp/firmware/src/common/edit-gpif @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- Python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and +# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our +# uses. + +import re +import string +import sys + +def check_flow_state (line, flow_state_dict): + mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line) + if mo: + wave = int (mo.group (1)) + data = mo.group (2) + split = data.split (',', 8) + v = map (lambda x : int (x, 16), split) + # print "%s, %s" % (wave, data) + # print "split: ", split + # print "v : ", v + flow_state_dict[wave] = v + + +def delta (xseq, yseq): + # set subtraction + z = [] + for x in xseq: + if x not in yseq: + z.append (x) + return z + + +def write_define (output, name, pairs): + output.write ('#define %s()\t\\\n' % name) + output.write ('do {\t\t\t\t\t\\\n') + for reg, val in pairs: + output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val)) + output.write ('} while (0)\n\n') + +def write_inlines (output, dict): + regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF', + 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT'] + + READ_FLOW_STATE = 2 + WRITE_FLOW_STATE = 3 + + read_info = zip (regs, dict[READ_FLOW_STATE]) + write_info = zip (regs, dict[WRITE_FLOW_STATE]) + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + write_define (output, 'setup_flowstate_common', read_info) + write_define (output, 'setup_flowstate_read', delta (read_info, write_info)) + write_define (output, 'setup_flowstate_write', delta (write_info, read_info)) + + +def edit_gpif (input_name, output_name, inline_name): + input = open (input_name, 'r') + output = open (output_name, 'w') + inline = open (inline_name, 'w') + flow_state_dict = {} + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + + while 1: + line = input.readline () + line = string.replace (line, '\r','') + line = re.sub (r' *$', r'', line) + + check_flow_state (line, flow_state_dict) + + line = re.sub (r'#include', r'// #include', line) + line = re.sub (r'xdata ', r'', line) + if re.search (r'GpifInit', line): + break + + output.write (line) + + output.close () + write_inlines (inline, flow_state_dict) + inline.close () + + +# gpif.c usrp_gpif.c usrp_gpif_inline.h +edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/usrp/firmware/src/common/fpga.h b/usrp/firmware/src/common/fpga.h new file mode 100644 index 00000000..d95db334 --- /dev/null +++ b/usrp/firmware/src/common/fpga.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_FPGA_H +#define INCLUDED_FPGA_H + +#include "fpga_load.h" + +#if defined(HAVE_USRP2) +#include "fpga_rev2.h" +#endif + +#endif /* INCLUDED_FPGA_H */ diff --git a/usrp/firmware/src/common/fpga_load.c b/usrp/firmware/src/common/fpga_load.c new file mode 100644 index 00000000..1c2792d2 --- /dev/null +++ b/usrp/firmware/src/common/fpga_load.c @@ -0,0 +1,193 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "usrp_common.h" +#include "fpga_load.h" +#include "delay.h" + +/* + * setup altera FPGA serial load (PS). + * + * On entry: + * don't care + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ +unsigned char +fpga_load_begin (void) +{ + USRP_ALTERA_CONFIG &= ~bmALTERA_BITS; // clear all bits (NCONFIG low) + udelay (40); // wait 40 us + USRP_ALTERA_CONFIG |= bmALTERA_NCONFIG; // set NCONFIG high + + if (UC_BOARD_HAS_FPGA){ + // FIXME should really cap this loop with a counter so we + // don't hang forever on a hardware failure. + while ((USRP_ALTERA_CONFIG & bmALTERA_NSTATUS) == 0) // wait for NSTATUS to go high + ; + } + + // ready to xfer now + + return 1; +} + +/* + * clock out the low bit of bits. + * + * On entry: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ + + +#if 0 + +static void +clock_out_config_byte (unsigned char bits) +{ + unsigned char i; + + // clock out configuration byte, least significant bit first + + for (i = 0; i < 8; i++){ + + USRP_ALTERA_CONFIG = ((USRP_ALTERA_CONFIG & ~bmALTERA_DATA0) | ((bits & 1) ? bmALTERA_DATA0 : 0)); + USRP_ALTERA_CONFIG |= bmALTERA_DCLK; /* set DCLK to 1 */ + USRP_ALTERA_CONFIG &= ~bmALTERA_DCLK; /* set DCLK to 0 */ + + bits = bits >> 1; + } +} + +#else + +static void +clock_out_config_byte (unsigned char bits) _naked +{ + _asm + mov a, dpl + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + ret + + _endasm; +} + +#endif + +static void +clock_out_bytes (unsigned char bytecount, + unsigned char xdata *p) +{ + while (bytecount-- > 0) + clock_out_config_byte (*p++); +} + +/* + * Transfer block of bytes from packet to FPGA serial configuration port + * + * On entry: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ +unsigned char +fpga_load_xfer (xdata unsigned char *p, unsigned char bytecount) +{ + clock_out_bytes (bytecount, p); + return 1; +} + +/* + * check for successful load... + */ +unsigned char +fpga_load_end (void) +{ + unsigned char status = USRP_ALTERA_CONFIG; + + if (!UC_BOARD_HAS_FPGA) // always true if we don't have FPGA + return 1; + + if ((status & bmALTERA_NSTATUS) == 0) // failed to program + return 0; + + if ((status & bmALTERA_CONF_DONE) == bmALTERA_CONF_DONE) + return 1; // everything's cool + + // I don't think this should happen. It indicates that + // programming is still in progress. + + return 0; +} diff --git a/usrp/firmware/src/common/fpga_load.h b/usrp/firmware/src/common/fpga_load.h new file mode 100644 index 00000000..baf22ded --- /dev/null +++ b/usrp/firmware/src/common/fpga_load.h @@ -0,0 +1,28 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef INCLUDED_FPGA_LOAD_H +#define INCLUDED_FPGA_LOAD_H + +unsigned char fpga_load_begin (void); +unsigned char fpga_load_xfer (xdata unsigned char *p, unsigned char len); +unsigned char fpga_load_end (void); + +#endif /* INCLUDED_FPGA_LOAD_H */ diff --git a/usrp/firmware/src/common/gpif.c b/usrp/firmware/src/common/gpif.c new file mode 100755 index 00000000..489e6e81 --- /dev/null +++ b/usrp/firmware/src/common/gpif.c @@ -0,0 +1,292 @@ +// This program configures the General Programmable Interface (GPIF) for FX2. +// Please do not modify sections of text which are marked as "DO NOT EDIT ...". +// +// DO NOT EDIT ... +// GPIF Initialization +// Interface Timing Async +// Internal Ready Init IntRdy=1 +// CTL Out Tristate-able Binary +// SingleWrite WF Select 1 +// SingleRead WF Select 0 +// FifoWrite WF Select 3 +// FifoRead WF Select 2 +// Data Bus Idle Drive Tristate +// END DO NOT EDIT + +// DO NOT EDIT ... +// GPIF Wave Names +// Wave 0 = singlerd +// Wave 1 = singlewr +// Wave 2 = FIFORd +// Wave 3 = FIFOWr + +// GPIF Ctrl Outputs Level +// CTL 0 = WEN# CMOS +// CTL 1 = REN# CMOS +// CTL 2 = OE# CMOS +// CTL 3 = CLRST CMOS +// CTL 4 = unused CMOS +// CTL 5 = BOGUS CMOS + +// GPIF Rdy Inputs +// RDY0 = EF# +// RDY1 = FF# +// RDY2 = unused +// RDY3 = unused +// RDY4 = unused +// RDY5 = TCXpire +// FIFOFlag = FIFOFlag +// IntReady = IntReady +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 0: singlerd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A +// LFunc +// Term B +// Branch1 +// Branch0 +// Re-Exec +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 1: singlewr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode Activate Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A EF# +// LFunc AND +// Term B EF# +// Branch1 ThenIdle +// Branch0 ElseIdle +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 1 1 1 1 1 1 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 2: FIFORd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1 +// Term A TCXpire TCXpire +// LFunc AND AND +// Term B TCXpire TCXpire +// Branch1 Then 2 ThenIdle +// Branch0 Else 1 ElseIdle +// Re-Exec No No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 1 1 1 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 3: FIFOWr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A TCXpire +// LFunc AND +// Term B TCXpire +// Branch1 ThenIdle +// Branch0 Else 1 +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT + +// GPIF Program Code + +// DO NOT EDIT ... +#include "fx2.h" +#include "fx2regs.h" +#include "fx2sdly.h" // SYNCDELAY macro +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata WaveData[128] = +{ +// Wave 0 +/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 1 +/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 2 +/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F, +// Wave 3 +/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata FlowStates[36] = +{ +/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00, +/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata InitData[7] = +{ +/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00 +}; +// END DO NOT EDIT + +// TO DO: You may add additional code below. + +void GpifInit( void ) +{ + BYTE i; + + // Registers which require a synchronization delay, see section 15.14 + // FIFORESET FIFOPINPOLAR + // INPKTEND OUTPKTEND + // EPxBCH:L REVCTL + // GPIFTCB3 GPIFTCB2 + // GPIFTCB1 GPIFTCB0 + // EPxFIFOPFH:L EPxAUTOINLENH:L + // EPxFIFOCFG EPxGPIFFLGSEL + // PINFLAGSxx EPxFIFOIRQ + // EPxFIFOIE GPIFIRQ + // GPIFIE GPIFADRH:L + // UDMACRCH:L EPxGPIFTRIG + // GPIFTRIG + + // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... + // ...these have been replaced by GPIFTC[B3:B0] registers + + // 8051 doesn't have access to waveform memories 'til + // the part is in GPIF mode. + + IFCONFIG = 0xEE; + // IFCLKSRC=1 , FIFOs executes on internal clk source + // xMHz=1 , 48MHz internal clk rate + // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz + // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk + // ASYNC=1 , master samples asynchronous + // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF + // IFCFG[1:0]=10, FX2 in GPIF master mode + + GPIFABORT = 0xFF; // abort any waveforms pending + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + GPIFWFSELECT = InitData[ 5 ]; + GPIFREADYSTAT = InitData[ 6 ]; + + // use dual autopointer feature... + AUTOPTRSETUP = 0x07; // inc both pointers, + // ...warning: this introduces pdata hole(s) + // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) + + // source + AUTOPTRH1 = MSB( &WaveData ); + AUTOPTRL1 = LSB( &WaveData ); + + // destination + AUTOPTRH2 = 0xE4; + AUTOPTRL2 = 0x00; + + // transfer + for ( i = 0x00; i < 128; i++ ) + { + EXTAUTODAT2 = EXTAUTODAT1; + } + +// Configure GPIF Address pins, output initial value, + PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] + OEC = 0xFF; // and as outputs + PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] + OEE |= 0x80; // and as output + +// ...OR... tri-state GPIFADR[8:0] pins +// PORTCCFG = 0x00; // [7:0] as port I/O +// OEC = 0x00; // and as inputs +// PORTECFG &= 0x7F; // [8] as port I/O +// OEE &= 0x7F; // and as input + +// GPIF address pins update when GPIFADRH/L written + SYNCDELAY; // + GPIFADRH = 0x00; // bits[7:1] always 0 + SYNCDELAY; // + GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 + +// Configure GPIF FlowStates registers for Wave 0 of WaveData + FLOWSTATE = FlowStates[ 0 ]; + FLOWLOGIC = FlowStates[ 1 ]; + FLOWEQ0CTL = FlowStates[ 2 ]; + FLOWEQ1CTL = FlowStates[ 3 ]; + FLOWHOLDOFF = FlowStates[ 4 ]; + FLOWSTB = FlowStates[ 5 ]; + FLOWSTBEDGE = FlowStates[ 6 ]; + FLOWSTBHPERIOD = FlowStates[ 7 ]; +} + diff --git a/usrp/firmware/src/common/gpif.gpf b/usrp/firmware/src/common/gpif.gpf new file mode 100755 index 00000000..a954ac19 Binary files /dev/null and b/usrp/firmware/src/common/gpif.gpf differ diff --git a/usrp/firmware/src/common/init_gpif.c b/usrp/firmware/src/common/init_gpif.c new file mode 100644 index 00000000..40336e65 --- /dev/null +++ b/usrp/firmware/src/common/init_gpif.c @@ -0,0 +1,59 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "usrp_common.h" + +// These are the tables generated by the Cypress GPIF Designer + +extern const char WaveData[128]; +extern const char FlowStates[36]; +extern const char InitData[7]; + +// The tool is kind of screwed up, in that it doesn't configure some +// of the ports correctly. We just use their tables and handle the +// initialization ourselves. They also declare that their static +// initialized data is in xdata, which screws us too. + +void +init_gpif (void) +{ + // we've already setup IFCONFIG before calling this... + + GPIFABORT = 0xFF; // abort any waveforms pending + SYNCDELAY; + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + // Hmmm, what's InitData[ 4 ] ... + GPIFWFSELECT = InitData[ 5 ]; + // GPIFREADYSTAT = InitData[ 6 ]; // I think this register is read only... + + { + BYTE i; + + for (i = 0; i < 128; i++){ + GPIF_WAVE_DATA[i] = WaveData[i]; + } + } + + FLOWSTATE = 0; /* ensure it's off */ +} diff --git a/usrp/firmware/src/common/usrp_common.c b/usrp/firmware/src/common/usrp_common.c new file mode 100644 index 00000000..5daa8df5 --- /dev/null +++ b/usrp/firmware/src/common/usrp_common.c @@ -0,0 +1,109 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * common code for USRP + */ + +#include "usrp_common.h" + +void init_board (void); + +void +init_usrp (void) +{ + CPUCS = bmCLKSPD1; // CPU runs @ 48 MHz + CKCON = 0; // MOVX takes 2 cycles + + // IFCLK is generated internally and runs at 48 MHz; GPIF "master mode" + + IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmIFCLKPOL | bmIFGPIF; + SYNCDELAY; + + // configure IO ports (B and D are used by GPIF) + + IOA = bmPORT_A_INITIAL; // Port A initial state + OEA = bmPORT_A_OUTPUTS; // Port A direction register + + IOC = bmPORT_C_INITIAL; // Port C initial state + OEC = bmPORT_C_OUTPUTS; // Port C direction register + + IOE = bmPORT_E_INITIAL; // Port E initial state + OEE = bmPORT_E_OUTPUTS; // Port E direction register + + + // REVCTL = bmDYN_OUT | bmENH_PKT; // highly recommended by docs + // SYNCDELAY; + + // configure end points + + EP1OUTCFG = bmVALID | bmBULK; SYNCDELAY; + EP1INCFG = bmVALID | bmBULK | bmIN; SYNCDELAY; + + EP2CFG = bmVALID | bmBULK | bmQUADBUF; SYNCDELAY; // 512 quad bulk OUT + EP4CFG = 0; SYNCDELAY; // disabled + EP6CFG = bmVALID | bmBULK | bmQUADBUF | bmIN; SYNCDELAY; // 512 quad bulk IN + EP8CFG = 0; SYNCDELAY; // disabled + + // reset FIFOs + + FIFORESET = bmNAKALL; SYNCDELAY; + FIFORESET = 2; SYNCDELAY; + // FIFORESET = 4; SYNCDELAY; + FIFORESET = 6; SYNCDELAY; + // FIFORESET = 8; SYNCDELAY; + FIFORESET = 0; SYNCDELAY; + + // configure end point FIFOs + + // let core see 0 to 1 transistion of autoout bit + + EP2FIFOCFG = bmWORDWIDE; SYNCDELAY; + EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE; SYNCDELAY; + EP6FIFOCFG = bmAUTOIN | bmWORDWIDE; SYNCDELAY; + + + // prime the pump + +#if 0 + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; +#endif + + EP0BCH = 0; SYNCDELAY; + + // arm EP1OUT so we can receive "out" packets (TRM pg 8-8) + + EP1OUTBC = 0; SYNCDELAY; + + EP2GPIFFLGSEL = 0x01; SYNCDELAY; // For EP2OUT, GPIF uses EF flag + EP6GPIFFLGSEL = 0x02; SYNCDELAY; // For EP6IN, GPIF uses FF flag + + // set autoin length for EP6 + // FIXME should be f(enumeration) + + EP6AUTOINLENH = (512) >> 8; SYNCDELAY; // this is the length for high speed + EP6AUTOINLENL = (512) & 0xff; SYNCDELAY; + + init_board (); +} + diff --git a/usrp/firmware/src/common/usrp_globals.h b/usrp/firmware/src/common/usrp_globals.h new file mode 100644 index 00000000..6caa2348 --- /dev/null +++ b/usrp/firmware/src/common/usrp_globals.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _USRP_GLOBALS_H_ +#define _USRP_GLOBALS_H_ + +extern unsigned char g_tx_enable; +extern unsigned char g_rx_enable; +extern unsigned char g_fpga_reset; +extern unsigned char g_rx_overrun; +extern unsigned char g_tx_underrun; + + +#endif /* _USRP_GLOBALS_H_ */ diff --git a/usrp/firmware/src/common/vectors.a51 b/usrp/firmware/src/common/vectors.a51 new file mode 100644 index 00000000..7fd5f954 --- /dev/null +++ b/usrp/firmware/src/common/vectors.a51 @@ -0,0 +1,180 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;;; Boston, MA 02111-1307, USA. +;;; + +;;; Interrupt vectors. + +;;; N.B. This object module must come first in the list of modules + + .module vectors + +;;; ---------------------------------------------------------------- +;;; standard FX2 interrupt vectors +;;; ---------------------------------------------------------------- + + .area CSEG (CODE) + .area GSINIT (CODE) + .area CSEG (CODE) +__standard_interrupt_vector:: +__reset_vector:: + ljmp s_GSINIT + + ;; 13 8-byte entries. We point them all at __isr_nop + ljmp __isr_nop ; 3 bytes + .ds 5 ; + 5 = 8 bytes for vector slot + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + +__isr_nop:: + reti + +;;; ---------------------------------------------------------------- +;;; the FIFO/GPIF autovector. 14 4-byte entries. +;;; must start on a 128 byte boundary. +;;; ---------------------------------------------------------------- + + . = __reset_vector + 0x0080 + +__fifo_gpif_autovector:: + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + + +;;; ---------------------------------------------------------------- +;;; the USB autovector. 32 4-byte entries. +;;; must start on a 256 byte boundary. +;;; ---------------------------------------------------------------- + + . = __reset_vector + 0x0100 + +__usb_autovector:: + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop diff --git a/usrp/firmware/src/usrp2/Makefile.am b/usrp/firmware/src/usrp2/Makefile.am new file mode 100644 index 00000000..e708312d --- /dev/null +++ b/usrp/firmware/src/usrp2/Makefile.am @@ -0,0 +1,168 @@ +# +# Copyright 2003,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +firmware2dir = $(prefix)/share/usrp/rev2 +firmware2_DATA = std.ihx + +# we put the same stuff in the rev4 directory +firmware4dir = $(prefix)/share/usrp/rev4 +firmware4_DATA = std.ihx + +EXTRA_DIST = \ + edit-gpif \ + _startup.a51 \ + blink_leds.c \ + board_specific.c \ + check_mdelay.c \ + check_udelay.c \ + eeprom_boot.a51 \ + eeprom_init.c \ + eeprom_io.c \ + eeprom_io.h \ + fpga_load.c \ + fpga_rev2.c \ + fpga_rev2.h \ + gpif.c \ + init_gpif.c \ + spi.c \ + spi.h \ + usb_descriptors.a51 \ + usrp_common.c \ + usrp_common.h \ + usrp_gpif.c \ + usrp_main.c \ + usrp_rev2_regs.h \ + vectors.a51 + + +DEFINES=-DHAVE_USRP2 +INCLUDES=-I$(top_srcdir)/usrp/firmware/include -I$(top_srcdir)/usrp/firmware/src/usrp2 -I$(top_srcdir)/usrp/firmware/src/common -I./ -I../common + +# with EA = 0, the FX2 implements a portion of the 8051 "external memory" +# on chip. This memory is mapped like this: +# +# The bottom 8K of memory (0x0000 - 0x1fff) is used for both data and +# code accesses. There's also 512 bytes for data only from 0xe000 - 0xe1ff. +# +# We tell the linker to start the xdata segment at 0x1800, 6K up from +# the bottom. + +MEMOPTS = --code-loc 0x0000 --code-size 0x1800 --xram-loc 0x1800 --xram-size 0x0800 \ + -Wl '-b USBDESCSEG = 0xE000' + +LIBOPTS = -L ../../lib libfx2.lib +LIBDEP = ../../lib/libfx2.lib + +LINKOPTS = $(MEMOPTS) $(LIBOPTS) + +EXECUTABLES = \ + std.ihx \ + blink_leds.ihx \ + check_mdelay.ihx \ + check_udelay.ihx \ + eeprom_boot.ihx + +STARTUP = _startup.rel + +noinst_SCRIPTS = \ + burn-usrp2-eeprom \ + burn-usrp4-eeprom + + +%.rel : %.c + $(XCC) $(INCLUDES) $(DEFINES) \ + -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +%.rel : %.a51 + test -f `basename '$<'` || ln -s '$<' . + test -f ../common/`basename '$<'` -o \ + \! -f `dirname '$<'`/../common/`basename '$<'` \ + || ln -s `dirname '$<'`/../common/`basename '$<'` ../common/. + $(XAS) `basename '$<'` + + +EEPROM_BOOT_OBJS = eeprom_boot.rel eeprom_init.rel $(STARTUP) + +eeprom_boot.ihx: $(EEPROM_BOOT_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(EEPROM_BOOT_OBJS) + +burn-usrp2-eeprom: eeprom_boot.ihx + $(srcdir)/../common/build_eeprom.py -r2 $< > $@ + chmod +x $@ + +burn-usrp4-eeprom: eeprom_boot.ihx + $(srcdir)/../common/build_eeprom.py -r4 $< > $@ + chmod +x $@ + + +BLINK_LEDS_OBJS = blink_leds.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) + +blink_leds.ihx: $(BLINK_LEDS_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(BLINK_LEDS_OBJS) + + +CHECK_MDELAY_OBJS = check_mdelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) + +check_mdelay.ihx: $(CHECK_MDELAY_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(CHECK_MDELAY_OBJS) + + + +CHECK_UDELAY_OBJS = check_udelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) + +check_udelay.ihx: $(CHECK_UDELAY_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(CHECK_UDELAY_OBJS) + + + +USRP_OBJS = \ + vectors.rel \ + usrp_main.rel usrp_common.rel board_specific.rel \ + fpga_load.rel fpga_rev2.rel init_gpif.rel usrp_gpif.rel \ + usb_descriptors.rel spi.rel eeprom_io.rel $(STARTUP) + +std.ihx: $(USRP_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(USRP_OBJS) + +CLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h \ + burn-usrp2-eeprom \ + burn-usrp4-eeprom + +DISTCLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib + +# build gpif stuff + +all: usrp_gpif.c + +usrp_gpif.c usrp_gpif_inline.h : gpif.c + srcdir=$(srcdir) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h + + +# dependencies + +usrp_main.rel: usrp_gpif_inline.h +#usrp_main.rel: fpga.h usrp_common.h ../../include/usrp_commands.h usrp_gpif_inline.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h +#usrp_common.rel: usrp_common.h ../../include/usrp_commands.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h +#fpga.rel: usrp_common.h ../../include/usrp_commands.h fpga.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h +#init_gpif.rel: usrp_common.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h diff --git a/usrp/firmware/src/usrp2/_startup.a51 b/usrp/firmware/src/usrp2/_startup.a51 new file mode 100644 index 00000000..4f530992 --- /dev/null +++ b/usrp/firmware/src/usrp2/_startup.a51 @@ -0,0 +1 @@ + .include "../common/_startup.a51" diff --git a/usrp/firmware/src/usrp2/blink_leds.c b/usrp/firmware/src/usrp2/blink_leds.c new file mode 100644 index 00000000..c633d5d4 --- /dev/null +++ b/usrp/firmware/src/usrp2/blink_leds.c @@ -0,0 +1 @@ +#include "../common/blink_leds.c" diff --git a/usrp/firmware/src/usrp2/board_specific.c b/usrp/firmware/src/usrp2/board_specific.c new file mode 100644 index 00000000..a4ff45c5 --- /dev/null +++ b/usrp/firmware/src/usrp2/board_specific.c @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "usrp_common.h" +#include "spi.h" + +void +set_led_0 (unsigned char on) +{ + if (!on) // active low + USRP_PC |= bmPC_LED0; + else + USRP_PC &= ~bmPC_LED0; +} + +void +set_led_1 (unsigned char on) +{ + if (!on) // active low + USRP_PC |= bmPC_LED1; + else + USRP_PC &= ~bmPC_LED1; +} + +void +toggle_led_0 (void) +{ + USRP_PC ^= bmPC_LED0; +} + +void +toggle_led_1 (void) +{ + USRP_PC ^= bmPC_LED1; +} + +void +la_trace_init (void) +{ +} + +void +set_sleep_bits (unsigned char bits, unsigned char mask) +{ + // NOP on usrp1 +} + +static xdata unsigned char xbuf[1]; + +void +write_9862 (unsigned char which, unsigned char regno, unsigned char value) +{ + xbuf[0] = value; + + spi_write (0, regno & 0x3f, + which == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + xbuf, 1); +} + +void +write_both_9862s (unsigned char regno, unsigned char value) +{ + xbuf[0] = value; + + spi_write (0, regno & 0x3f, + SPI_ENABLE_CODEC_A | SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + xbuf, 1); +} + +#define REG_RX_PWR_DN 1 +#define REG_TX_PWR_DN 8 +#define REG_TX_MODULATOR 20 + +static void +power_down_9862s (void) +{ + write_both_9862s (REG_RX_PWR_DN, 0x01); + write_both_9862s (REG_TX_PWR_DN, 0x0f); // pwr dn digital and analog_both + write_both_9862s (REG_TX_MODULATOR, 0x00); // coarse & fine modulators disabled +} + +void +init_board (void) +{ + la_trace_init (); + init_spi (); + + USRP_PC &= ~bmPC_nRESET; // active low reset + USRP_PC |= bmPC_nRESET; + + power_down_9862s (); +} diff --git a/usrp/firmware/src/usrp2/check_mdelay.c b/usrp/firmware/src/usrp2/check_mdelay.c new file mode 100644 index 00000000..ea4ccdb1 --- /dev/null +++ b/usrp/firmware/src/usrp2/check_mdelay.c @@ -0,0 +1 @@ +#include "../common/check_mdelay.c" diff --git a/usrp/firmware/src/usrp2/check_udelay.c b/usrp/firmware/src/usrp2/check_udelay.c new file mode 100644 index 00000000..d01622e5 --- /dev/null +++ b/usrp/firmware/src/usrp2/check_udelay.c @@ -0,0 +1 @@ +#include "../common/check_udelay.c" diff --git a/usrp/firmware/src/usrp2/edit-gpif b/usrp/firmware/src/usrp2/edit-gpif new file mode 100755 index 00000000..c507f502 --- /dev/null +++ b/usrp/firmware/src/usrp2/edit-gpif @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- Python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and +# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our +# uses. + +import re +import string +import sys + +def check_flow_state (line, flow_state_dict): + mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line) + if mo: + wave = int (mo.group (1)) + data = mo.group (2) + split = data.split (',', 8) + v = map (lambda x : int (x, 16), split) + # print "%s, %s" % (wave, data) + # print "split: ", split + # print "v : ", v + flow_state_dict[wave] = v + + +def delta (xseq, yseq): + # set subtraction + z = [] + for x in xseq: + if x not in yseq: + z.append (x) + return z + + +def write_define (output, name, pairs): + output.write ('#define %s()\t\\\n' % name) + output.write ('do {\t\t\t\t\t\\\n') + for reg, val in pairs: + output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val)) + output.write ('} while (0)\n\n') + +def write_inlines (output, dict): + regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF', + 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT'] + + READ_FLOW_STATE = 2 + WRITE_FLOW_STATE = 3 + + read_info = zip (regs, dict[READ_FLOW_STATE]) + write_info = zip (regs, dict[WRITE_FLOW_STATE]) + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + write_define (output, 'setup_flowstate_common', read_info) + write_define (output, 'setup_flowstate_read', delta (read_info, write_info)) + write_define (output, 'setup_flowstate_write', delta (write_info, read_info)) + + +def edit_gpif (input_name, output_name, inline_name): + input = open (input_name, 'r') + output = open (output_name, 'w') + inline = open (inline_name, 'w') + flow_state_dict = {} + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + + while 1: + line = input.readline () + line = string.replace (line, '\r','') + line = re.sub (r' *$', r'', line) + + check_flow_state (line, flow_state_dict) + + line = re.sub (r'#include', r'// #include', line) + line = re.sub (r'xdata ', r'', line) + if re.search (r'GpifInit', line): + break + + output.write (line) + + output.close () + write_inlines (inline, flow_state_dict) + inline.close () + + +# gpif.c usrp_gpif.c usrp_gpif_inline.h +edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/usrp/firmware/src/usrp2/eeprom_boot.a51 b/usrp/firmware/src/usrp2/eeprom_boot.a51 new file mode 100644 index 00000000..65e45266 --- /dev/null +++ b/usrp/firmware/src/usrp2/eeprom_boot.a51 @@ -0,0 +1,573 @@ +;-------------------------------------------------------- +; Hand tweaked minimal eeprom boot code +;-------------------------------------------------------- + .module eeprom_boot + .optsdcc -mmcs51 --model-small + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- + .globl _eeprom_init + .globl _EP8FIFOBUF + .globl _EP6FIFOBUF + .globl _EP4FIFOBUF + .globl _EP2FIFOBUF + .globl _EP1INBUF + .globl _EP1OUTBUF + .globl _EP0BUF + .globl _CT4 + .globl _CT3 + .globl _CT2 + .globl _CT1 + .globl _USBTEST + .globl _TESTCFG + .globl _DBUG + .globl _UDMACRCQUAL + .globl _UDMACRCL + .globl _UDMACRCH + .globl _GPIFHOLDAMOUNT + .globl _FLOWSTBHPERIOD + .globl _FLOWSTBEDGE + .globl _FLOWSTB + .globl _FLOWHOLDOFF + .globl _FLOWEQ1CTL + .globl _FLOWEQ0CTL + .globl _FLOWLOGIC + .globl _FLOWSTATE + .globl _GPIFABORT + .globl _GPIFREADYSTAT + .globl _GPIFREADYCFG + .globl _XGPIFSGLDATLNOX + .globl _XGPIFSGLDATLX + .globl _XGPIFSGLDATH + .globl _EP8GPIFTRIG + .globl _EP8GPIFPFSTOP + .globl _EP8GPIFFLGSEL + .globl _EP6GPIFTRIG + .globl _EP6GPIFPFSTOP + .globl _EP6GPIFFLGSEL + .globl _EP4GPIFTRIG + .globl _EP4GPIFPFSTOP + .globl _EP4GPIFFLGSEL + .globl _EP2GPIFTRIG + .globl _EP2GPIFPFSTOP + .globl _EP2GPIFFLGSEL + .globl _GPIFTCB0 + .globl _GPIFTCB1 + .globl _GPIFTCB2 + .globl _GPIFTCB3 + .globl _GPIFADRL + .globl _GPIFADRH + .globl _GPIFCTLCFG + .globl _GPIFIDLECTL + .globl _GPIFIDLECS + .globl _GPIFWFSELECT + .globl _SETUPDAT + .globl _SUDPTRCTL + .globl _SUDPTRL + .globl _SUDPTRH + .globl _EP8FIFOBCL + .globl _EP8FIFOBCH + .globl _EP6FIFOBCL + .globl _EP6FIFOBCH + .globl _EP4FIFOBCL + .globl _EP4FIFOBCH + .globl _EP2FIFOBCL + .globl _EP2FIFOBCH + .globl _EP8FIFOFLGS + .globl _EP6FIFOFLGS + .globl _EP4FIFOFLGS + .globl _EP2FIFOFLGS + .globl _EP8CS + .globl _EP6CS + .globl _EP4CS + .globl _EP2CS + .globl _EP1INCS + .globl _EP1OUTCS + .globl _EP0CS + .globl _EP8BCL + .globl _EP8BCH + .globl _EP6BCL + .globl _EP6BCH + .globl _EP4BCL + .globl _EP4BCH + .globl _EP2BCL + .globl _EP2BCH + .globl _EP1INBC + .globl _EP1OUTBC + .globl _EP0BCL + .globl _EP0BCH + .globl _FNADDR + .globl _MICROFRAME + .globl _USBFRAMEL + .globl _USBFRAMEH + .globl _TOGCTL + .globl _WAKEUPCS + .globl _SUSPEND + .globl _USBCS + .globl _XAUTODAT2 + .globl _XAUTODAT1 + .globl _I2CTL + .globl _I2DAT + .globl _I2CS + .globl _PORTECFG + .globl _PORTCCFG + .globl _PORTACFG + .globl _INTSETUP + .globl _INT4IVEC + .globl _INT2IVEC + .globl _CLRERRCNT + .globl _ERRCNTLIM + .globl _USBERRIRQ + .globl _USBERRIE + .globl _GPIFIRQ + .globl _GPIFIE + .globl _EPIRQ + .globl _EPIE + .globl _USBIRQ + .globl _USBIE + .globl _NAKIRQ + .globl _NAKIE + .globl _IBNIRQ + .globl _IBNIE + .globl _EP8FIFOIRQ + .globl _EP8FIFOIE + .globl _EP6FIFOIRQ + .globl _EP6FIFOIE + .globl _EP4FIFOIRQ + .globl _EP4FIFOIE + .globl _EP2FIFOIRQ + .globl _EP2FIFOIE + .globl _OUTPKTEND + .globl _INPKTEND + .globl _EP8ISOINPKTS + .globl _EP6ISOINPKTS + .globl _EP4ISOINPKTS + .globl _EP2ISOINPKTS + .globl _EP8FIFOPFL + .globl _EP8FIFOPFH + .globl _EP6FIFOPFL + .globl _EP6FIFOPFH + .globl _EP4FIFOPFL + .globl _EP4FIFOPFH + .globl _EP2FIFOPFL + .globl _EP2FIFOPFH + .globl _EP8AUTOINLENL + .globl _EP8AUTOINLENH + .globl _EP6AUTOINLENL + .globl _EP6AUTOINLENH + .globl _EP4AUTOINLENL + .globl _EP4AUTOINLENH + .globl _EP2AUTOINLENL + .globl _EP2AUTOINLENH + .globl _EP8FIFOCFG + .globl _EP6FIFOCFG + .globl _EP4FIFOCFG + .globl _EP2FIFOCFG + .globl _EP8CFG + .globl _EP6CFG + .globl _EP4CFG + .globl _EP2CFG + .globl _EP1INCFG + .globl _EP1OUTCFG + .globl _REVCTL + .globl _REVID + .globl _FIFOPINPOLAR + .globl _UART230 + .globl _BPADDRL + .globl _BPADDRH + .globl _BREAKPT + .globl _FIFORESET + .globl _PINFLAGSCD + .globl _PINFLAGSAB + .globl _IFCONFIG + .globl _CPUCS + .globl _RES_WAVEDATA_END + .globl _GPIF_WAVE_DATA +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +_IOA = 0x0080 +_SP = 0x0081 +_DPL = 0x0082 +_DPH = 0x0083 +_DPL1 = 0x0084 +_DPH1 = 0x0085 +_DPS = 0x0086 +_PCON = 0x0087 +_TCON = 0x0088 +_TMOD = 0x0089 +_TL0 = 0x008a +_TL1 = 0x008b +_TH0 = 0x008c +_TH1 = 0x008d +_CKCON = 0x008e +_IOB = 0x0090 +_EXIF = 0x0091 +_MPAGE = 0x0092 +_SCON0 = 0x0098 +_SBUF0 = 0x0099 +_APTR1H = 0x009a +_APTR1L = 0x009b +_AUTODAT1 = 0x009c +_AUTOPTRH2 = 0x009d +_AUTOPTRL2 = 0x009e +_AUTODAT2 = 0x009f +_IOC = 0x00a0 +_INT2CLR = 0x00a1 +_INT4CLR = 0x00a2 +_IE = 0x00a8 +_EP2468STAT = 0x00aa +_EP24FIFOFLGS = 0x00ab +_EP68FIFOFLGS = 0x00ac +_AUTOPTRSETUP = 0x00af +_IOD = 0x00b0 +_IOE = 0x00b1 +_OEA = 0x00b2 +_OEB = 0x00b3 +_OEC = 0x00b4 +_OED = 0x00b5 +_OEE = 0x00b6 +_IP = 0x00b8 +_EP01STAT = 0x00ba +_GPIFTRIG = 0x00bb +_GPIFSGLDATH = 0x00bd +_GPIFSGLDATLX = 0x00be +_GPIFSGLDATLNOX = 0x00bf +_SCON1 = 0x00c0 +_SBUF1 = 0x00c1 +_T2CON = 0x00c8 +_RCAP2L = 0x00ca +_RCAP2H = 0x00cb +_TL2 = 0x00cc +_TH2 = 0x00cd +_PSW = 0x00d0 +_EICON = 0x00d8 +_ACC = 0x00e0 +_EIE = 0x00e8 +_B = 0x00f0 +_EIP = 0x00f8 +;-------------------------------------------------------- +; special function bits +;-------------------------------------------------------- +_SEL = 0x0086 +_IT0 = 0x0088 +_IE0 = 0x0089 +_IT1 = 0x008a +_IE1 = 0x008b +_TR0 = 0x008c +_TF0 = 0x008d +_TR1 = 0x008e +_TF1 = 0x008f +_RI = 0x0098 +_TI = 0x0099 +_RB8 = 0x009a +_TB8 = 0x009b +_REN = 0x009c +_SM2 = 0x009d +_SM1 = 0x009e +_SM0 = 0x009f +_EX0 = 0x00a8 +_ET0 = 0x00a9 +_EX1 = 0x00aa +_ET1 = 0x00ab +_ES0 = 0x00ac +_ET2 = 0x00ad +_ES1 = 0x00ae +_EA = 0x00af +_PX0 = 0x00b8 +_PT0 = 0x00b9 +_PX1 = 0x00ba +_PT1 = 0x00bb +_PS0 = 0x00bc +_PT2 = 0x00bd +_PS1 = 0x00be +_RI1 = 0x00c0 +_TI1 = 0x00c1 +_RB81 = 0x00c2 +_TB81 = 0x00c3 +_REN1 = 0x00c4 +_SM21 = 0x00c5 +_SM11 = 0x00c6 +_SM01 = 0x00c7 +_CP_RL2 = 0x00c8 +_C_T2 = 0x00c9 +_TR2 = 0x00ca +_EXEN2 = 0x00cb +_TCLK = 0x00cc +_RCLK = 0x00cd +_EXF2 = 0x00ce +_TF2 = 0x00cf +_P = 0x00d0 +_FL = 0x00d1 +_OV = 0x00d2 +_RS0 = 0x00d3 +_RS1 = 0x00d4 +_F0 = 0x00d5 +_AC = 0x00d6 +_CY = 0x00d7 +_INT6 = 0x00db +_RESI = 0x00dc +_ERESI = 0x00dd +_SMOD1 = 0x00df +_EIUSB = 0x00e8 +_EI2C = 0x00e9 +_EIEX4 = 0x00ea +_EIEX5 = 0x00eb +_EIEX6 = 0x00ec +_PUSB = 0x00f8 +_PI2C = 0x00f9 +_EIPX4 = 0x00fa +_EIPX5 = 0x00fb +_EIPX6 = 0x00fc +_bitS_CLK = 0x0080 +_bitS_OUT = 0x0081 +_bitS_IN = 0x0082 +_bitALTERA_DATA0 = 0x00a1 +_bitALTERA_DCLK = 0x00a3 +;-------------------------------------------------------- +; overlayable register banks +;-------------------------------------------------------- + .area REG_BANK_0 (REL,OVR,DATA) + .ds 8 +;-------------------------------------------------------- +; internal ram data +;-------------------------------------------------------- + .area DSEG (DATA) +;-------------------------------------------------------- +; overlayable items in internal ram +;-------------------------------------------------------- + .area OSEG (OVR,DATA) +;-------------------------------------------------------- +; Stack segment in internal ram +;-------------------------------------------------------- + .area SSEG (DATA) +__start__stack: + .ds 1 + +;-------------------------------------------------------- +; indirectly addressable internal ram data +;-------------------------------------------------------- + .area ISEG (DATA) +;-------------------------------------------------------- +; bit data +;-------------------------------------------------------- + .area BSEG (BIT) +;-------------------------------------------------------- +; external ram data +;-------------------------------------------------------- + .area XSEG (XDATA) +_GPIF_WAVE_DATA = 0xe400 +_RES_WAVEDATA_END = 0xe480 +_CPUCS = 0xe600 +_IFCONFIG = 0xe601 +_PINFLAGSAB = 0xe602 +_PINFLAGSCD = 0xe603 +_FIFORESET = 0xe604 +_BREAKPT = 0xe605 +_BPADDRH = 0xe606 +_BPADDRL = 0xe607 +_UART230 = 0xe608 +_FIFOPINPOLAR = 0xe609 +_REVID = 0xe60a +_REVCTL = 0xe60b +_EP1OUTCFG = 0xe610 +_EP1INCFG = 0xe611 +_EP2CFG = 0xe612 +_EP4CFG = 0xe613 +_EP6CFG = 0xe614 +_EP8CFG = 0xe615 +_EP2FIFOCFG = 0xe618 +_EP4FIFOCFG = 0xe619 +_EP6FIFOCFG = 0xe61a +_EP8FIFOCFG = 0xe61b +_EP2AUTOINLENH = 0xe620 +_EP2AUTOINLENL = 0xe621 +_EP4AUTOINLENH = 0xe622 +_EP4AUTOINLENL = 0xe623 +_EP6AUTOINLENH = 0xe624 +_EP6AUTOINLENL = 0xe625 +_EP8AUTOINLENH = 0xe626 +_EP8AUTOINLENL = 0xe627 +_EP2FIFOPFH = 0xe630 +_EP2FIFOPFL = 0xe631 +_EP4FIFOPFH = 0xe632 +_EP4FIFOPFL = 0xe633 +_EP6FIFOPFH = 0xe634 +_EP6FIFOPFL = 0xe635 +_EP8FIFOPFH = 0xe636 +_EP8FIFOPFL = 0xe637 +_EP2ISOINPKTS = 0xe640 +_EP4ISOINPKTS = 0xe641 +_EP6ISOINPKTS = 0xe642 +_EP8ISOINPKTS = 0xe643 +_INPKTEND = 0xe648 +_OUTPKTEND = 0xe649 +_EP2FIFOIE = 0xe650 +_EP2FIFOIRQ = 0xe651 +_EP4FIFOIE = 0xe652 +_EP4FIFOIRQ = 0xe653 +_EP6FIFOIE = 0xe654 +_EP6FIFOIRQ = 0xe655 +_EP8FIFOIE = 0xe656 +_EP8FIFOIRQ = 0xe657 +_IBNIE = 0xe658 +_IBNIRQ = 0xe659 +_NAKIE = 0xe65a +_NAKIRQ = 0xe65b +_USBIE = 0xe65c +_USBIRQ = 0xe65d +_EPIE = 0xe65e +_EPIRQ = 0xe65f +_GPIFIE = 0xe660 +_GPIFIRQ = 0xe661 +_USBERRIE = 0xe662 +_USBERRIRQ = 0xe663 +_ERRCNTLIM = 0xe664 +_CLRERRCNT = 0xe665 +_INT2IVEC = 0xe666 +_INT4IVEC = 0xe667 +_INTSETUP = 0xe668 +_PORTACFG = 0xe670 +_PORTCCFG = 0xe671 +_PORTECFG = 0xe672 +_I2CS = 0xe678 +_I2DAT = 0xe679 +_I2CTL = 0xe67a +_XAUTODAT1 = 0xe67b +_XAUTODAT2 = 0xe67c +_USBCS = 0xe680 +_SUSPEND = 0xe681 +_WAKEUPCS = 0xe682 +_TOGCTL = 0xe683 +_USBFRAMEH = 0xe684 +_USBFRAMEL = 0xe685 +_MICROFRAME = 0xe686 +_FNADDR = 0xe687 +_EP0BCH = 0xe68a +_EP0BCL = 0xe68b +_EP1OUTBC = 0xe68d +_EP1INBC = 0xe68f +_EP2BCH = 0xe690 +_EP2BCL = 0xe691 +_EP4BCH = 0xe694 +_EP4BCL = 0xe695 +_EP6BCH = 0xe698 +_EP6BCL = 0xe699 +_EP8BCH = 0xe69c +_EP8BCL = 0xe69d +_EP0CS = 0xe6a0 +_EP1OUTCS = 0xe6a1 +_EP1INCS = 0xe6a2 +_EP2CS = 0xe6a3 +_EP4CS = 0xe6a4 +_EP6CS = 0xe6a5 +_EP8CS = 0xe6a6 +_EP2FIFOFLGS = 0xe6a7 +_EP4FIFOFLGS = 0xe6a8 +_EP6FIFOFLGS = 0xe6a9 +_EP8FIFOFLGS = 0xe6aa +_EP2FIFOBCH = 0xe6ab +_EP2FIFOBCL = 0xe6ac +_EP4FIFOBCH = 0xe6ad +_EP4FIFOBCL = 0xe6ae +_EP6FIFOBCH = 0xe6af +_EP6FIFOBCL = 0xe6b0 +_EP8FIFOBCH = 0xe6b1 +_EP8FIFOBCL = 0xe6b2 +_SUDPTRH = 0xe6b3 +_SUDPTRL = 0xe6b4 +_SUDPTRCTL = 0xe6b5 +_SETUPDAT = 0xe6b8 +_GPIFWFSELECT = 0xe6c0 +_GPIFIDLECS = 0xe6c1 +_GPIFIDLECTL = 0xe6c2 +_GPIFCTLCFG = 0xe6c3 +_GPIFADRH = 0xe6c4 +_GPIFADRL = 0xe6c5 +_GPIFTCB3 = 0xe6ce +_GPIFTCB2 = 0xe6cf +_GPIFTCB1 = 0xe6d0 +_GPIFTCB0 = 0xe6d1 +_EP2GPIFFLGSEL = 0xe6d2 +_EP2GPIFPFSTOP = 0xe6d3 +_EP2GPIFTRIG = 0xe6d4 +_EP4GPIFFLGSEL = 0xe6da +_EP4GPIFPFSTOP = 0xe6db +_EP4GPIFTRIG = 0xe6dc +_EP6GPIFFLGSEL = 0xe6e2 +_EP6GPIFPFSTOP = 0xe6e3 +_EP6GPIFTRIG = 0xe6e4 +_EP8GPIFFLGSEL = 0xe6ea +_EP8GPIFPFSTOP = 0xe6eb +_EP8GPIFTRIG = 0xe6ec +_XGPIFSGLDATH = 0xe6f0 +_XGPIFSGLDATLX = 0xe6f1 +_XGPIFSGLDATLNOX = 0xe6f2 +_GPIFREADYCFG = 0xe6f3 +_GPIFREADYSTAT = 0xe6f4 +_GPIFABORT = 0xe6f5 +_FLOWSTATE = 0xe6c6 +_FLOWLOGIC = 0xe6c7 +_FLOWEQ0CTL = 0xe6c8 +_FLOWEQ1CTL = 0xe6c9 +_FLOWHOLDOFF = 0xe6ca +_FLOWSTB = 0xe6cb +_FLOWSTBEDGE = 0xe6cc +_FLOWSTBHPERIOD = 0xe6cd +_GPIFHOLDAMOUNT = 0xe60c +_UDMACRCH = 0xe67d +_UDMACRCL = 0xe67e +_UDMACRCQUAL = 0xe67f +_DBUG = 0xe6f8 +_TESTCFG = 0xe6f9 +_USBTEST = 0xe6fa +_CT1 = 0xe6fb +_CT2 = 0xe6fc +_CT3 = 0xe6fd +_CT4 = 0xe6fe +_EP0BUF = 0xe740 +_EP1OUTBUF = 0xe780 +_EP1INBUF = 0xe7c0 +_EP2FIFOBUF = 0xf000 +_EP4FIFOBUF = 0xf400 +_EP6FIFOBUF = 0xf800 +_EP8FIFOBUF = 0xfc00 +;-------------------------------------------------------- +; external initialized ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; interrupt vector +;-------------------------------------------------------- + .area CSEG (CODE) +__interrupt_vect: + ljmp __sdcc_gsinit_startup +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- + .area GSINIT (CODE) + .area GSFINAL (CODE) + .area GSINIT (CODE) +__sdcc_gsinit_startup: + mov sp,#__start__stack - 1 + lcall __sdcc_external_startup + mov a,dpl + jz __sdcc_init_data + ljmp __sdcc_program_startup +__sdcc_init_data: + .area GSFINAL (CODE) + ljmp __sdcc_program_startup +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- + .area HOME (CODE) + .area CSEG (CODE) +;-------------------------------------------------------- +; code +;-------------------------------------------------------- + .area CSEG (CODE) +__sdcc_program_startup: + lcall _eeprom_init +; return from _eeprom_init will spin here + sjmp . + .area CSEG (CODE) diff --git a/usrp/firmware/src/usrp2/eeprom_init.c b/usrp/firmware/src/usrp2/eeprom_init.c new file mode 100644 index 00000000..fb949bc8 --- /dev/null +++ b/usrp/firmware/src/usrp2/eeprom_init.c @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "usrp_common.h" +#include "usrp_commands.h" +#include "spi.h" + +/* + * the host side fpga loader code pushes an MD5 hash of the bitstream + * into hash1. + */ +#define USRP_HASH_SIZE 16 +xdata at USRP_HASH_SLOT_0_ADDR unsigned char hash0[USRP_HASH_SIZE]; + + +#define enable_codecs() USRP_PA &= ~(bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B) +#define disable_all() USRP_PA |= (bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B) + +static void +write_byte_msb (unsigned char v); + +void +write_both_9862s (unsigned char header_lo, unsigned char v) +{ + enable_codecs (); + + write_byte_msb (header_lo); + write_byte_msb (v); + + disable_all (); +} + +// ---------------------------------------------------------------- + +static void +write_byte_msb (unsigned char v) +{ + unsigned char n = 8; + do { + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + } while (--n != 0); +} + +// ---------------------------------------------------------------- + +#define REG_RX_PWR_DN 1 +#define REG_TX_PWR_DN 8 +#define REG_TX_MODULATOR 20 + +void eeprom_init (void) +{ + unsigned short counter; + unsigned char i; + + // configure IO ports (B and D are used by GPIF) + + IOA = bmPORT_A_INITIAL; // Port A initial state + OEA = bmPORT_A_OUTPUTS; // Port A direction register + + IOC = bmPORT_C_INITIAL; // Port C initial state + OEC = bmPORT_C_OUTPUTS; // Port C direction register + + IOE = bmPORT_E_INITIAL; // Port E initial state + OEE = bmPORT_E_OUTPUTS; // Port E direction register + + EP0BCH = 0; SYNCDELAY; + + // USBCS &= ~bmRENUM; // chip firmware handles commands + USBCS = 0; // chip firmware handles commands + + USRP_PC &= ~bmPC_nRESET; // active low reset + USRP_PC |= bmPC_nRESET; + + // init_spi (); + bitS_OUT = 0; /* idle state has CLK = 0 */ + + write_both_9862s (REG_RX_PWR_DN, 0x01); + write_both_9862s (REG_TX_PWR_DN, 0x0f); // pwr dn digital and analog_both + write_both_9862s (REG_TX_MODULATOR, 0x00); // coarse & fine modulators disabled + + // zero firmware hash slot + i = 0; + do { + hash0[i] = 0; + i++; + } while (i != USRP_HASH_SIZE); + + counter = 0; + while (1){ + counter++; + if (counter & 0x8000) + IOC ^= bmPC_LED0; + } +} diff --git a/usrp/firmware/src/usrp2/eeprom_io.c b/usrp/firmware/src/usrp2/eeprom_io.c new file mode 100644 index 00000000..1aa51a0b --- /dev/null +++ b/usrp/firmware/src/usrp2/eeprom_io.c @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "eeprom_io.h" +#include "i2c.h" +#include "delay.h" + +// returns non-zero if successful, else 0 +unsigned char +eeprom_read (unsigned char i2c_addr, unsigned char eeprom_offset, + xdata unsigned char *buf, unsigned char len) +{ + // We setup a random read by first doing a "zero byte write". + // Writes carry an address. Reads use an implicit address. + + static xdata unsigned char cmd[1]; + cmd[0] = eeprom_offset; + if (!i2c_write(i2c_addr, cmd, 1)) + return 0; + + return i2c_read(i2c_addr, buf, len); +} + + +#if 0 + +// returns non-zero if successful, else 0 +unsigned char +eeprom_write (unsigned char i2c_addr, unsigned char eeprom_offset, + const xdata unsigned char *buf, unsigned char len) +{ + static xdata unsigned char cmd[2]; + unsigned char ok; + + while (len-- > 0){ + cmd[0] = eeprom_offset++; + cmd[1] = *buf++; + ok = i2c_write(i2c_addr, cmd, 2); + mdelay(10); // delay 10ms worst case write time + if (!ok) + return 0; + } + return 1; +} + +#endif diff --git a/usrp/firmware/src/usrp2/eeprom_io.h b/usrp/firmware/src/usrp2/eeprom_io.h new file mode 100644 index 00000000..ece8036d --- /dev/null +++ b/usrp/firmware/src/usrp2/eeprom_io.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_EEPROM_IO_H +#define INCLUDED_EEPROM_IO_H + + +// returns non-zero if successful, else 0 +unsigned char +eeprom_read (unsigned char i2c_addr, unsigned char eeprom_offset, + xdata unsigned char *buf, unsigned char len); + +// returns non-zero if successful, else 0 +unsigned char +eeprom_write (unsigned char i2c_addr, unsigned char eeprom_offset, + const xdata unsigned char *buf, unsigned char len); + + +#endif /* INCLUDED_EEPROM_IO_H */ diff --git a/usrp/firmware/src/usrp2/fpga_load.c b/usrp/firmware/src/usrp2/fpga_load.c new file mode 100644 index 00000000..b0256e92 --- /dev/null +++ b/usrp/firmware/src/usrp2/fpga_load.c @@ -0,0 +1 @@ +#include "../common/fpga_load.c" diff --git a/usrp/firmware/src/usrp2/fpga_rev2.c b/usrp/firmware/src/usrp2/fpga_rev2.c new file mode 100644 index 00000000..cd282d6d --- /dev/null +++ b/usrp/firmware/src/usrp2/fpga_rev2.c @@ -0,0 +1,122 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "fpga.h" +#include "fpga_regs_common.h" +#include "usrp_common.h" +#include "usrp_globals.h" +#include "spi.h" + +unsigned char g_tx_reset = 0; +unsigned char g_rx_reset = 0; + +void +fpga_write_reg (unsigned char regno, const xdata unsigned char *regval) +{ + spi_write (0, 0x00 | (regno & 0x7f), + SPI_ENABLE_FPGA, + SPI_FMT_MSB | SPI_FMT_HDR_1, + regval, 4); +} + + +static xdata unsigned char regval[4] = {0, 0, 0, 0}; + +static void +write_fpga_master_ctrl (void) +{ + unsigned char v = 0; + if (g_tx_enable) + v |= bmFR_MC_ENABLE_TX; + if (g_rx_enable) + v |= bmFR_MC_ENABLE_RX; + if (g_tx_reset) + v |= bmFR_MC_RESET_TX; + if (g_rx_reset) + v |= bmFR_MC_RESET_RX; + regval[3] = v; + + fpga_write_reg (FR_MASTER_CTRL, regval); +} + +// Resets both AD9862's and the FPGA serial bus interface. + +void +fpga_set_reset (unsigned char on) +{ + on &= 0x1; + + if (on){ + USRP_PC &= ~bmPC_nRESET; // active low + g_tx_enable = 0; + g_rx_enable = 0; + g_tx_reset = 0; + g_rx_reset = 0; + } + else + USRP_PC |= bmPC_nRESET; +} + +void +fpga_set_tx_enable (unsigned char on) +{ + on &= 0x1; + g_tx_enable = on; + + write_fpga_master_ctrl (); + + if (on){ + g_tx_underrun = 0; + fpga_clear_flags (); + } +} + +void +fpga_set_rx_enable (unsigned char on) +{ + on &= 0x1; + g_rx_enable = on; + + write_fpga_master_ctrl (); + if (on){ + g_rx_overrun = 0; + fpga_clear_flags (); + } +} + +void +fpga_set_tx_reset (unsigned char on) +{ + on &= 0x1; + g_tx_reset = on; + + write_fpga_master_ctrl (); +} + +void +fpga_set_rx_reset (unsigned char on) +{ + on &= 0x1; + g_rx_reset = on; + + write_fpga_master_ctrl (); +} diff --git a/usrp/firmware/src/usrp2/fpga_rev2.h b/usrp/firmware/src/usrp2/fpga_rev2.h new file mode 100644 index 00000000..6c04271b --- /dev/null +++ b/usrp/firmware/src/usrp2/fpga_rev2.h @@ -0,0 +1,58 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2004 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef INCLUDED_FPGA_REV1_H +#define INCLUDED_FPGA_REV1_H + +void fpga_set_reset (unsigned char v); +void fpga_set_tx_enable (unsigned char v); +void fpga_set_rx_enable (unsigned char v); +void fpga_set_tx_reset (unsigned char v); +void fpga_set_rx_reset (unsigned char v); + +unsigned char fpga_has_room_for_packet (void); +unsigned char fpga_has_packet_avail (void); + +#if (UC_BOARD_HAS_FPGA) +/* + * return TRUE iff FPGA internal fifo has room for 512 bytes. + */ +#define fpga_has_room_for_packet() (GPIFREADYSTAT & bmFPGA_HAS_SPACE) + +/* + * return TRUE iff FPGA internal fifo has at least 512 bytes available. + */ +#define fpga_has_packet_avail() (GPIFREADYSTAT & bmFPGA_PKT_AVAIL) + +#else /* no FPGA on board. fake it. */ + +#define fpga_has_room_for_packet() TRUE +#define fpga_has_packet_avail() TRUE + +#endif + +#define fpga_clear_flags() \ + do { \ + USRP_PE |= bmPE_FPGA_CLR_STATUS; \ + USRP_PE &= ~bmPE_FPGA_CLR_STATUS; \ + } while (0) + + +#endif /* INCLUDED_FPGA_REV1_H */ diff --git a/usrp/firmware/src/usrp2/gpif.c b/usrp/firmware/src/usrp2/gpif.c new file mode 100644 index 00000000..f6745a43 --- /dev/null +++ b/usrp/firmware/src/usrp2/gpif.c @@ -0,0 +1,292 @@ +// This program configures the General Programmable Interface (GPIF) for FX2. +// Please do not modify sections of text which are marked as "DO NOT EDIT ...". +// +// DO NOT EDIT ... +// GPIF Initialization +// Interface Timing Async +// Internal Ready Init IntRdy=1 +// CTL Out Tristate-able Binary +// SingleWrite WF Select 1 +// SingleRead WF Select 0 +// FifoWrite WF Select 3 +// FifoRead WF Select 2 +// Data Bus Idle Drive Tristate +// END DO NOT EDIT + +// DO NOT EDIT ... +// GPIF Wave Names +// Wave 0 = singlerd +// Wave 1 = singlewr +// Wave 2 = FIFORd +// Wave 3 = FIFOWr + +// GPIF Ctrl Outputs Level +// CTL 0 = WEN# CMOS +// CTL 1 = REN# CMOS +// CTL 2 = OE# CMOS +// CTL 3 = CLRST CMOS +// CTL 4 = unused CMOS +// CTL 5 = BOGUS CMOS + +// GPIF Rdy Inputs +// RDY0 = EF# +// RDY1 = FF# +// RDY2 = unused +// RDY3 = unused +// RDY4 = unused +// RDY5 = TCXpire +// FIFOFlag = FIFOFlag +// IntReady = IntReady +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 0: singlerd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A +// LFunc +// Term B +// Branch1 +// Branch0 +// Re-Exec +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 1: singlewr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode Activate Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A EF# +// LFunc AND +// Term B EF# +// Branch1 ThenIdle +// Branch0 ElseIdle +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 1 1 1 1 1 1 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 2: FIFORd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1 +// Term A TCXpire TCXpire +// LFunc AND AND +// Term B TCXpire TCXpire +// Branch1 Then 2 ThenIdle +// Branch0 Else 1 ElseIdle +// Re-Exec No No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 1 0 0 0 0 0 0 0 +// OE# 1 1 1 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 3: FIFOWr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A TCXpire +// LFunc AND +// Term B TCXpire +// Branch1 ThenIdle +// Branch0 Else 1 +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT + +// GPIF Program Code + +// DO NOT EDIT ... +#include "fx2.h" +#include "fx2regs.h" +#include "fx2sdly.h" // SYNCDELAY macro +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata WaveData[128] = +{ +// Wave 0 +/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 1 +/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 2 +/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F, +// Wave 3 +/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata FlowStates[36] = +{ +/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00, +/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata InitData[7] = +{ +/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00 +}; +// END DO NOT EDIT + +// TO DO: You may add additional code below. + +void GpifInit( void ) +{ + BYTE i; + + // Registers which require a synchronization delay, see section 15.14 + // FIFORESET FIFOPINPOLAR + // INPKTEND OUTPKTEND + // EPxBCH:L REVCTL + // GPIFTCB3 GPIFTCB2 + // GPIFTCB1 GPIFTCB0 + // EPxFIFOPFH:L EPxAUTOINLENH:L + // EPxFIFOCFG EPxGPIFFLGSEL + // PINFLAGSxx EPxFIFOIRQ + // EPxFIFOIE GPIFIRQ + // GPIFIE GPIFADRH:L + // UDMACRCH:L EPxGPIFTRIG + // GPIFTRIG + + // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... + // ...these have been replaced by GPIFTC[B3:B0] registers + + // 8051 doesn't have access to waveform memories 'til + // the part is in GPIF mode. + + IFCONFIG = 0xEE; + // IFCLKSRC=1 , FIFOs executes on internal clk source + // xMHz=1 , 48MHz internal clk rate + // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz + // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk + // ASYNC=1 , master samples asynchronous + // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF + // IFCFG[1:0]=10, FX2 in GPIF master mode + + GPIFABORT = 0xFF; // abort any waveforms pending + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + GPIFWFSELECT = InitData[ 5 ]; + GPIFREADYSTAT = InitData[ 6 ]; + + // use dual autopointer feature... + AUTOPTRSETUP = 0x07; // inc both pointers, + // ...warning: this introduces pdata hole(s) + // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) + + // source + AUTOPTRH1 = MSB( &WaveData ); + AUTOPTRL1 = LSB( &WaveData ); + + // destination + AUTOPTRH2 = 0xE4; + AUTOPTRL2 = 0x00; + + // transfer + for ( i = 0x00; i < 128; i++ ) + { + EXTAUTODAT2 = EXTAUTODAT1; + } + +// Configure GPIF Address pins, output initial value, + PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] + OEC = 0xFF; // and as outputs + PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] + OEE |= 0x80; // and as output + +// ...OR... tri-state GPIFADR[8:0] pins +// PORTCCFG = 0x00; // [7:0] as port I/O +// OEC = 0x00; // and as inputs +// PORTECFG &= 0x7F; // [8] as port I/O +// OEE &= 0x7F; // and as input + +// GPIF address pins update when GPIFADRH/L written + SYNCDELAY; // + GPIFADRH = 0x00; // bits[7:1] always 0 + SYNCDELAY; // + GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 + +// Configure GPIF FlowStates registers for Wave 0 of WaveData + FLOWSTATE = FlowStates[ 0 ]; + FLOWLOGIC = FlowStates[ 1 ]; + FLOWEQ0CTL = FlowStates[ 2 ]; + FLOWEQ1CTL = FlowStates[ 3 ]; + FLOWHOLDOFF = FlowStates[ 4 ]; + FLOWSTB = FlowStates[ 5 ]; + FLOWSTBEDGE = FlowStates[ 6 ]; + FLOWSTBHPERIOD = FlowStates[ 7 ]; +} + diff --git a/usrp/firmware/src/usrp2/gpif.gpf b/usrp/firmware/src/usrp2/gpif.gpf new file mode 100755 index 00000000..854e2539 Binary files /dev/null and b/usrp/firmware/src/usrp2/gpif.gpf differ diff --git a/usrp/firmware/src/usrp2/init_gpif.c b/usrp/firmware/src/usrp2/init_gpif.c new file mode 100644 index 00000000..0f5944b3 --- /dev/null +++ b/usrp/firmware/src/usrp2/init_gpif.c @@ -0,0 +1 @@ +#include "../common/init_gpif.c" diff --git a/usrp/firmware/src/usrp2/spi.c b/usrp/firmware/src/usrp2/spi.c new file mode 100644 index 00000000..0c6abb4d --- /dev/null +++ b/usrp/firmware/src/usrp2/spi.c @@ -0,0 +1,381 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "spi.h" +#include "usrp_rev2_regs.h" + +static void +setup_enables (unsigned char enables) +{ + // Software eanbles are active high. + // Hardware enables are active low. + + // Uhh, the CODECs are active low, but the FPGA is active high... + enables ^= SPI_ENABLE_FPGA; + + // KLUDGE: This code is fragile, but reasonably fast... + // low three bits of enables go into port A + USRP_PA = USRP_PA | (0x7 << 3); // disable FPGA, CODEC_A, CODEC_B + USRP_PA ^= (enables & 0x7) << 3; // enable specified devs + + // high four bits of enables go into port E + USRP_PE = USRP_PE | (0xf << 4); // disable TX_A, RX_A, TX_B, RX_B + USRP_PE ^= (enables & 0xf0); // enable specified devs +} + +#define disable_all() setup_enables (0) + +void +init_spi (void) +{ + disable_all (); /* disable all devs */ + bitS_OUT = 0; /* idle state has CLK = 0 */ +} + +#if 0 +static unsigned char +count_bits8 (unsigned char v) +{ + static unsigned char count4[16] = { + 0, // 0 + 1, // 1 + 1, // 2 + 2, // 3 + 1, // 4 + 2, // 5 + 2, // 6 + 3, // 7 + 1, // 8 + 2, // 9 + 2, // a + 3, // b + 2, // c + 3, // d + 3, // e + 4 // f + }; + return count4[v & 0xf] + count4[(v >> 4) & 0xf]; +} + +#else + +static unsigned char +count_bits8 (unsigned char v) +{ + unsigned char count = 0; + if (v & (1 << 0)) count++; + if (v & (1 << 1)) count++; + if (v & (1 << 2)) count++; + if (v & (1 << 3)) count++; + if (v & (1 << 4)) count++; + if (v & (1 << 5)) count++; + if (v & (1 << 6)) count++; + if (v & (1 << 7)) count++; + return count; +} +#endif + +static void +write_byte_msb (unsigned char v); + +static void +write_bytes_msb (const xdata unsigned char *buf, unsigned char len); + +static void +read_bytes_msb (xdata unsigned char *buf, unsigned char len); + + +// returns non-zero if successful, else 0 +unsigned char +spi_read (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + xdata unsigned char *buf, unsigned char len) +{ + if (count_bits8 (enables) > 1) + return 0; // error, too many enables set + + setup_enables (enables); + + if (format & SPI_FMT_LSB){ // order: LSB +#if 1 + return 0; // error, not implemented +#else + switch (format & SPI_FMR_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_lsb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_lsb (header_lo); + write_byte_lsb (header_hi); + break; + default: + return 0; // error + } + if (len != 0) + read_bytes_lsb (buf, len); +#endif + } + + else { // order: MSB + + switch (format & SPI_FMT_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_msb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_msb (header_hi); + write_byte_msb (header_lo); + break; + default: + return 0; // error + } + if (len != 0) + read_bytes_msb (buf, len); + } + + disable_all (); + return 1; // success +} + + +// returns non-zero if successful, else 0 +unsigned char +spi_write (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + const xdata unsigned char *buf, unsigned char len) +{ + setup_enables (enables); + + if (format & SPI_FMT_LSB){ // order: LSB +#if 1 + return 0; // error, not implemented +#else + switch (format & SPI_FMR_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_lsb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_lsb (header_lo); + write_byte_lsb (header_hi); + break; + default: + return 0; // error + } + if (len != 0) + write_bytes_lsb (buf, len); +#endif + } + + else { // order: MSB + + switch (format & SPI_FMT_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_msb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_msb (header_hi); + write_byte_msb (header_lo); + break; + default: + return 0; // error + } + if (len != 0) + write_bytes_msb (buf, len); + } + + disable_all (); + return 1; // success +} + +// ---------------------------------------------------------------- + +static void +write_byte_msb (unsigned char v) +{ + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; +} + +static void +write_bytes_msb (const xdata unsigned char *buf, unsigned char len) +{ + while (len-- != 0){ + write_byte_msb (*buf++); + } +} + +#if 0 +/* + * This is incorrectly compiled by SDCC 2.4.0 + */ +static unsigned char +read_byte_msb (void) +{ + unsigned char v = 0; + + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + return v; +} +#else +static unsigned char +read_byte_msb (void) _naked +{ + _asm + clr a + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + mov dpl,a + ret + _endasm; +} +#endif + +static void +read_bytes_msb (xdata unsigned char *buf, unsigned char len) +{ + while (len-- != 0){ + *buf++ = read_byte_msb (); + } +} + diff --git a/usrp/firmware/src/usrp2/spi.h b/usrp/firmware/src/usrp2/spi.h new file mode 100644 index 00000000..b17126d0 --- /dev/null +++ b/usrp/firmware/src/usrp2/spi.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_SPI_H +#define INCLUDED_SPI_H + +#include "usrp_spi_defs.h" + +void init_spi (void); // one time call to init + +// returns non-zero if successful, else 0 +unsigned char +spi_read (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + xdata unsigned char *buf, unsigned char len); + +// returns non-zero if successful, else 0 +unsigned char +spi_write (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + const xdata unsigned char *buf, unsigned char len); + + +#endif /* INCLUDED_SPI_H */ diff --git a/usrp/firmware/src/usrp2/usb_descriptors.a51 b/usrp/firmware/src/usrp2/usb_descriptors.a51 new file mode 100644 index 00000000..06a92f5a --- /dev/null +++ b/usrp/firmware/src/usrp2/usb_descriptors.a51 @@ -0,0 +1,404 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;;; Boston, MA 02111-1307, USA. +;;; + +;;; USB Descriptor table for the USRP +;;; +;;; We're a high-speed only device (480 Mb/sec) with 1 configuration +;;; and 3 interfaces. +;;; +;;; interface 0: command and status (ep0 COMMAND) +;;; interface 1: Transmit path (ep2 OUT BULK) +;;; interface 2: Receive path (ep6 IN BULK) + + .module usb_descriptors + + VID_FREE = 0xfffe ; Free Software Folks + PID_USRP = 0x0002 ; USRP + + ;; We distinguish configured from unconfigured USRPs using the Device ID. + ;; If the MSB of the DID is 0, the device is unconfigured. + ;; The LSB of the DID is reserved for hardware revs. + + DID_USRP = 0x0100 ; Device ID (bcd) + + + DSCR_DEVICE = 1 ; Descriptor type: Device + DSCR_CONFIG = 2 ; Descriptor type: Configuration + DSCR_STRING = 3 ; Descriptor type: String + DSCR_INTRFC = 4 ; Descriptor type: Interface + DSCR_ENDPNT = 5 ; Descriptor type: Endpoint + DSCR_DEVQUAL = 6 ; Descriptor type: Device Qualifier + + DSCR_DEVICE_LEN = 18 + DSCR_CONFIG_LEN = 9 + DSCR_INTRFC_LEN = 9 + DSCR_ENDPNT_LEN = 7 + DSCR_DEVQUAL_LEN = 10 + + ET_CONTROL = 0 ; Endpoint type: Control + ET_ISO = 1 ; Endpoint type: Isochronous + ET_BULK = 2 ; Endpoint type: Bulk + ET_INT = 3 ; Endpoint type: Interrupt + + + ;; configuration attributes + bmSELF_POWERED = 1 << 6 + +;;; -------------------------------------------------------- +;;; external ram data +;;;-------------------------------------------------------- + + .area USBDESCSEG (XDATA) + +;;; ---------------------------------------------------------------- +;;; descriptors used when operating at high speed (480Mb/sec) +;;; ---------------------------------------------------------------- + + .even ; descriptors must be 2-byte aligned for SUDPTR{H,L} to work + + ;; The .even directive isn't really honored by the linker. Bummer! + ;; (There's no way to specify an alignment requirement for a given area, + ;; hence when they're concatenated together, even doesn't work.) + ;; + ;; We work around this by telling the linker to put USBDESCSEG + ;; at 0xE000 absolute. This means that the maximimum length of this + ;; segment is 480 bytes, leaving room for the two hash slots + ;; at 0xE1EO to 0xE1FF. + ;; + ;; As of July 7, 2004, this segment is 326 bytes long + +_high_speed_device_descr:: + .db DSCR_DEVICE_LEN + .db DSCR_DEVICE + .db <0x0200 ; Specification version (LSB) + .db >0x0200 ; Specification version (MSB) + .db 0xff ; device class (vendor specific) + .db 0xff ; device subclass (vendor specific) + .db 0xff ; device protocol (vendor specific) + .db 64 ; bMaxPacketSize0 for endpoint 0 + .db VID_FREE ; idVendor + .db PID_USRP ; idProduct +_usb_desc_hw_rev_binary_patch_location_0:: + .db DID_USRP ; bcdDevice + .db SI_VENDOR ; iManufacturer (string index) + .db SI_PRODUCT ; iProduct (string index) + .db SI_SERIAL ; iSerial number (string index) + .db 1 ; bNumConfigurations + +;;; describes the other speed (12Mb/sec) + .even +_high_speed_devqual_descr:: + .db DSCR_DEVQUAL_LEN + .db DSCR_DEVQUAL + .db <0x0200 ; bcdUSB (LSB) + .db >0x0200 ; bcdUSB (MSB) + .db 0xff ; bDeviceClass + .db 0xff ; bDeviceSubClass + .db 0xff ; bDeviceProtocol + .db 64 ; bMaxPacketSize0 + .db 1 ; bNumConfigurations (one config at 12Mb/sec) + .db 0 ; bReserved + + .even +_high_speed_config_descr:: + .db DSCR_CONFIG_LEN + .db DSCR_CONFIG + .db <(_high_speed_config_descr_end - _high_speed_config_descr) ; LSB + .db >(_high_speed_config_descr_end - _high_speed_config_descr) ; MSB + .db 3 ; bNumInterfaces + .db 1 ; bConfigurationValue + .db 0 ; iConfiguration + .db 0x80 | bmSELF_POWERED ; bmAttributes + .db 0 ; bMaxPower + + ;; interface descriptor 0 (command & status, ep0 COMMAND) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 0 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 0 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_COMMAND_AND_STATUS ; iInterface (description) + + ;; interface descriptor 1 (transmit path, ep2 OUT BULK) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 1 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 1 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_TX_PATH ; iInterface (description) + + ;; interface 1's end point + + .db DSCR_ENDPNT_LEN + .db DSCR_ENDPNT + .db 0x02 ; bEndpointAddress (ep 2 OUT) + .db ET_BULK ; bmAttributes + .db <512 ; wMaxPacketSize (LSB) + .db >512 ; wMaxPacketSize (MSB) + .db 0 ; bInterval (iso only) + + ;; interface descriptor 2 (receive path, ep6 IN BULK) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 2 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 1 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_RX_PATH ; iInterface (description) + + ;; interface 2's end point + + .db DSCR_ENDPNT_LEN + .db DSCR_ENDPNT + .db 0x86 ; bEndpointAddress (ep 6 IN) + .db ET_BULK ; bmAttributes + .db <512 ; wMaxPacketSize (LSB) + .db >512 ; wMaxPacketSize (MSB) + .db 0 ; bInterval (iso only) + +_high_speed_config_descr_end: + +;;; ---------------------------------------------------------------- +;;; descriptors used when operating at full speed (12Mb/sec) +;;; ---------------------------------------------------------------- + + .even +_full_speed_device_descr:: + .db DSCR_DEVICE_LEN + .db DSCR_DEVICE + .db <0x0200 ; Specification version (LSB) + .db >0x0200 ; Specification version (MSB) + .db 0xff ; device class (vendor specific) + .db 0xff ; device subclass (vendor specific) + .db 0xff ; device protocol (vendor specific) + .db 64 ; bMaxPacketSize0 for endpoint 0 + .db VID_FREE ; idVendor + .db PID_USRP ; idProduct +_usb_desc_hw_rev_binary_patch_location_1:: + .db DID_USRP ; bcdDevice + .db SI_VENDOR ; iManufacturer (string index) + .db SI_PRODUCT ; iProduct (string index) + .db SI_NONE ; iSerial number (None) + .db 1 ; bNumConfigurations + + +;;; describes the other speed (480Mb/sec) + .even +_full_speed_devqual_descr:: + .db DSCR_DEVQUAL_LEN + .db DSCR_DEVQUAL + .db <0x0200 ; bcdUSB + .db >0x0200 ; bcdUSB + .db 0xff ; bDeviceClass + .db 0xff ; bDeviceSubClass + .db 0xff ; bDeviceProtocol + .db 64 ; bMaxPacketSize0 + .db 1 ; bNumConfigurations (one config at 480Mb/sec) + .db 0 ; bReserved + + .even +_full_speed_config_descr:: + .db DSCR_CONFIG_LEN + .db DSCR_CONFIG + .db <(_full_speed_config_descr_end - _full_speed_config_descr) ; LSB + .db >(_full_speed_config_descr_end - _full_speed_config_descr) ; MSB + .db 1 ; bNumInterfaces + .db 1 ; bConfigurationValue + .db 0 ; iConfiguration + .db 0x80 | bmSELF_POWERED ; bmAttributes + .db 0 ; bMaxPower + + ;; interface descriptor 0 (command & status, ep0 COMMAND) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 0 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 0 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_COMMAND_AND_STATUS ; iInterface (description) + +_full_speed_config_descr_end: + +;;; ---------------------------------------------------------------- +;;; string descriptors +;;; ---------------------------------------------------------------- + +_nstring_descriptors:: + .db (_string_descriptors_end - _string_descriptors) / 2 + +_string_descriptors:: + .db str0 + .db str1 + .db str2 + .db str3 + .db str4 + .db str5 + .db str6 +_string_descriptors_end: + + SI_NONE = 0 + ;; str0 contains the language ID's. + .even +str0: .db str0_end - str0 + .db DSCR_STRING + .db 0 + .db 0 + .db <0x0409 ; magic code for US English (LSB) + .db >0x0409 ; magic code for US English (MSB) +str0_end: + + SI_VENDOR = 1 + .even +str1: .db str1_end - str1 + .db DSCR_STRING + .db 'F, 0 ; 16-bit unicode + .db 'r, 0 + .db 'e, 0 + .db 'e, 0 + .db ' , 0 + .db 'S, 0 + .db 'o, 0 + .db 'f, 0 + .db 't, 0 + .db 'w, 0 + .db 'a, 0 + .db 'r, 0 + .db 'e, 0 + .db ' , 0 + .db 'F, 0 + .db 'o, 0 + .db 'l, 0 + .db 'k, 0 + .db 's, 0 +str1_end: + + SI_PRODUCT = 2 + .even +str2: .db str2_end - str2 + .db DSCR_STRING + .db 'U, 0 + .db 'S, 0 + .db 'R, 0 + .db 'P, 0 + .db ' , 0 + .db 'R, 0 + .db 'e, 0 + .db 'v, 0 + .db ' , 0 +_usb_desc_hw_rev_ascii_patch_location_0:: + .db '?, 0 +str2_end: + + SI_COMMAND_AND_STATUS = 3 + .even +str3: .db str3_end - str3 + .db DSCR_STRING + .db 'C, 0 + .db 'o, 0 + .db 'm, 0 + .db 'm, 0 + .db 'a, 0 + .db 'n, 0 + .db 'd, 0 + .db ' , 0 + .db '&, 0 + .db ' , 0 + .db 'S, 0 + .db 't, 0 + .db 'a, 0 + .db 't, 0 + .db 'u, 0 + .db 's, 0 +str3_end: + + SI_TX_PATH = 4 + .even +str4: .db str4_end - str4 + .db DSCR_STRING + .db 'T, 0 + .db 'r, 0 + .db 'a, 0 + .db 'n, 0 + .db 's, 0 + .db 'm, 0 + .db 'i, 0 + .db 't, 0 + .db ' , 0 + .db 'P, 0 + .db 'a, 0 + .db 't, 0 + .db 'h, 0 +str4_end: + + SI_RX_PATH = 5 + .even +str5: .db str5_end - str5 + .db DSCR_STRING + .db 'R, 0 + .db 'e, 0 + .db 'c, 0 + .db 'e, 0 + .db 'i, 0 + .db 'v, 0 + .db 'e, 0 + .db ' , 0 + .db 'P, 0 + .db 'a, 0 + .db 't, 0 + .db 'h, 0 +str5_end: + + SI_SERIAL = 6 + .even +str6: .db str6_end - str6 + .db DSCR_STRING +_usb_desc_serial_number_ascii:: + .db '3, 0 + .db '., 0 + .db '1, 0 + .db '4, 0 + .db '1, 0 + .db '5, 0 + .db '9, 0 + .db '3, 0 +str6_end: + diff --git a/usrp/firmware/src/usrp2/usrp_common.c b/usrp/firmware/src/usrp2/usrp_common.c new file mode 100644 index 00000000..f389d925 --- /dev/null +++ b/usrp/firmware/src/usrp2/usrp_common.c @@ -0,0 +1 @@ +#include "../common/usrp_common.c" diff --git a/usrp/firmware/src/usrp2/usrp_common.h b/usrp/firmware/src/usrp2/usrp_common.h new file mode 100644 index 00000000..5625b42d --- /dev/null +++ b/usrp/firmware/src/usrp2/usrp_common.h @@ -0,0 +1,77 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2006 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * common defines and prototypes for USRP + * + * In comments below "TRM" refers to the EZ-USB FX2 Technical Reference Manual + */ + +#ifndef _USRPCOMMON_H_ +#define _USRPCOMMON_H_ + +#include +#include +#include + +/* + * From TRM page 15-105: + * + * Under certain conditions, some read and write access to the FX2 + * registers must be separated by a "synchronization delay". The + * delay is necessary only under the following conditions: + * + * - between a write to any register in the 0xE600 - 0xE6FF range + * and a write to one of the registers listed below. + * + * - between a write to one of the registers listed below and a read + * from any register in the 0xE600 - 0xE6FF range. + * + * Registers which require a synchronization delay: + * + * FIFORESET FIFOPINPOLAR + * INPKTEND EPxBCH:L + * EPxFIFOPFH:L EPxAUTOINLENH:L + * EPxFIFOCFG EPxGPIFFLGSEL + * PINFLAGSAB PINFLAGSCD + * EPxFIFOIE EPxFIFOIRQ + * GPIFIE GPIFIRQ + * UDMACRCH:L GPIFADRH:L + * GPIFTRIG EPxGPIFTRIG + * OUTPKTEND REVCTL + * GPIFTCB3 GPIFTCB2 + * GPIFTCB1 GPIFTCB0 + */ + +#define TRUE 1 +#define FALSE 0 + + +void init_usrp (void); +void init_gpif (void); + +void set_led_0 (unsigned char on); +void set_led_1 (unsigned char on); +void toggle_led_0 (void); +void toggle_led_1 (void); + +#define la_trace(v) + +#endif /* _USRPCOMMON_H_ */ diff --git a/usrp/firmware/src/usrp2/usrp_main.c b/usrp/firmware/src/usrp2/usrp_main.c new file mode 100644 index 00000000..0dbba8e5 --- /dev/null +++ b/usrp/firmware/src/usrp2/usrp_main.c @@ -0,0 +1,380 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2004 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "usrp_common.h" +#include "usrp_commands.h" +#include "fpga.h" +#include "usrp_gpif_inline.h" +#include "timer.h" +#include "i2c.h" +#include "isr.h" +#include "usb_common.h" +#include "fx2utils.h" +#include "usrp_globals.h" +#include "usrp_i2c_addr.h" +#include +#include "spi.h" +#include "eeprom_io.h" +#include "usb_descriptors.h" + +/* + * offsets into boot eeprom for configuration values + */ +#define HW_REV_OFFSET 5 +#define SERIAL_NO_OFFSET 248 +#define SERIAL_NO_LEN 8 + + +#define bRequestType SETUPDAT[0] +#define bRequest SETUPDAT[1] +#define wValueL SETUPDAT[2] +#define wValueH SETUPDAT[3] +#define wIndexL SETUPDAT[4] +#define wIndexH SETUPDAT[5] +#define wLengthL SETUPDAT[6] +#define wLengthH SETUPDAT[7] + + +unsigned char g_tx_enable = 0; +unsigned char g_rx_enable = 0; +unsigned char g_rx_overrun = 0; +unsigned char g_tx_underrun = 0; + +/* + * the host side fpga loader code pushes an MD5 hash of the bitstream + * into hash1. + */ +#define USRP_HASH_SIZE 16 +xdata at USRP_HASH_SLOT_1_ADDR unsigned char hash1[USRP_HASH_SIZE]; + +static void +get_ep0_data (void) +{ + EP0BCL = 0; // arm EP0 for OUT xfer. This sets the busy bit + + while (EP0CS & bmEPBUSY) // wait for busy to clear + ; +} + +/* + * Handle our "Vendor Extension" commands on endpoint 0. + * If we handle this one, return non-zero. + */ +unsigned char +app_vendor_cmd (void) +{ + if (bRequestType == VRT_VENDOR_IN){ + + ///////////////////////////////// + // handle the IN requests + ///////////////////////////////// + + switch (bRequest){ + + case VRQ_GET_STATUS: + switch (wIndexL){ + + case GS_TX_UNDERRUN: + EP0BUF[0] = g_tx_underrun; + g_tx_underrun = 0; + EP0BCH = 0; + EP0BCL = 1; + break; + + case GS_RX_OVERRUN: + EP0BUF[0] = g_rx_overrun; + g_rx_overrun = 0; + EP0BCH = 0; + EP0BCL = 1; + break; + + default: + return 0; + } + break; + + case VRQ_I2C_READ: + if (!i2c_read (wValueL, EP0BUF, wLengthL)) + return 0; + + EP0BCH = 0; + EP0BCL = wLengthL; + break; + + case VRQ_SPI_READ: + if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL)) + return 0; + + EP0BCH = 0; + EP0BCL = wLengthL; + break; + + default: + return 0; + } + } + + else if (bRequestType == VRT_VENDOR_OUT){ + + ///////////////////////////////// + // handle the OUT requests + ///////////////////////////////// + + switch (bRequest){ + + case VRQ_SET_LED: + switch (wIndexL){ + case 0: + set_led_0 (wValueL); + break; + + case 1: + set_led_1 (wValueL); + break; + + default: + return 0; + } + break; + + case VRQ_FPGA_LOAD: + switch (wIndexL){ // sub-command + case FL_BEGIN: + return fpga_load_begin (); + + case FL_XFER: + get_ep0_data (); + return fpga_load_xfer (EP0BUF, EP0BCL); + + case FL_END: + return fpga_load_end (); + + default: + return 0; + } + break; + + + case VRQ_FPGA_SET_RESET: + fpga_set_reset (wValueL); + break; + + case VRQ_FPGA_SET_TX_ENABLE: + fpga_set_tx_enable (wValueL); + break; + + case VRQ_FPGA_SET_RX_ENABLE: + fpga_set_rx_enable (wValueL); + break; + + case VRQ_FPGA_SET_TX_RESET: + fpga_set_tx_reset (wValueL); + break; + + case VRQ_FPGA_SET_RX_RESET: + fpga_set_rx_reset (wValueL); + break; + + case VRQ_I2C_WRITE: + get_ep0_data (); + if (!i2c_write (wValueL, EP0BUF, EP0BCL)) + return 0; + break; + + case VRQ_SPI_WRITE: + get_ep0_data (); + if (!spi_write (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, EP0BCL)) + return 0; + break; + + default: + return 0; + } + + } + else + return 0; // invalid bRequestType + + return 1; +} + + + +static void +main_loop (void) +{ + setup_flowstate_common (); + + while (1){ + + if (usb_setup_packet_avail ()) + usb_handle_setup_packet (); + + + if (GPIFTRIG & bmGPIF_IDLE){ + + // OK, GPIF is idle. Let's try to give it some work. + + // First check for underruns and overruns + + if (UC_BOARD_HAS_FPGA && (USRP_PA & (bmPA_TX_UNDERRUN | bmPA_RX_OVERRUN))){ + + // record the under/over run + if (USRP_PA & bmPA_TX_UNDERRUN) + g_tx_underrun = 1; + + if (USRP_PA & bmPA_RX_OVERRUN) + g_rx_overrun = 1; + + // tell the FPGA to clear the flags + fpga_clear_flags (); + } + + // Next see if there are any "OUT" packets waiting for our attention, + // and if so, if there's room in the FPGA's FIFO for them. + + if (g_tx_enable && !(EP24FIFOFLGS & 0x02)){ // USB end point fifo is not empty... + + if (fpga_has_room_for_packet ()){ // ... and FPGA has room for packet + + GPIFTCB1 = 0x01; SYNCDELAY; + GPIFTCB0 = 0x00; SYNCDELAY; + + setup_flowstate_write (); + + SYNCDELAY; + GPIFTRIG = bmGPIF_EP2_START | bmGPIF_WRITE; // start the xfer + SYNCDELAY; + + while (!(GPIFTRIG & bmGPIF_IDLE)){ + // wait for the transaction to complete + } + } + } + + // See if there are any requests for "IN" packets, and if so + // whether the FPGA's got any packets for us. + + if (g_rx_enable && !(EP6CS & bmEPFULL)){ // USB end point fifo is not full... + + if (fpga_has_packet_avail ()){ // ... and FPGA has packet available + + GPIFTCB1 = 0x01; SYNCDELAY; + GPIFTCB0 = 0x00; SYNCDELAY; + + setup_flowstate_read (); + + SYNCDELAY; + GPIFTRIG = bmGPIF_EP6_START | bmGPIF_READ; // start the xfer + SYNCDELAY; + + while (!(GPIFTRIG & bmGPIF_IDLE)){ + // wait for the transaction to complete + } + + SYNCDELAY; + INPKTEND = 6; // tell USB we filled buffer (6 is our endpoint num) + } + } + } + } +} + + +/* + * called at 100 Hz from timer2 interrupt + * + * Toggle led 0 + */ +void +isr_tick (void) interrupt +{ + static unsigned char count = 1; + + if (--count == 0){ + count = 50; + USRP_LED_REG ^= bmLED0; + } + + clear_timer_irq (); +} + +/* + * Read h/w rev code and serial number out of boot eeprom and + * patch the usb descriptors with the values. + */ +void +patch_usb_descriptors(void) +{ + static xdata unsigned char hw_rev; + static xdata unsigned char serial_no[8]; + unsigned char i; + + eeprom_read(I2C_ADDR_BOOT, HW_REV_OFFSET, &hw_rev, 1); // LSB of device id + usb_desc_hw_rev_binary_patch_location_0[0] = hw_rev; + usb_desc_hw_rev_binary_patch_location_1[0] = hw_rev; + usb_desc_hw_rev_ascii_patch_location_0[0] = hw_rev + '0'; // FIXME if we get > 9 + + eeprom_read(I2C_ADDR_BOOT, SERIAL_NO_OFFSET, serial_no, SERIAL_NO_LEN); + + for (i = 0; i < SERIAL_NO_LEN; i++){ + unsigned char ch = serial_no[i]; + if (ch == 0xff) // make unprogrammed EEPROM default to '0' + ch = '0'; + usb_desc_serial_number_ascii[i << 1] = ch; + } +} + +void +main (void) +{ +#if 0 + g_rx_enable = 0; // FIXME (work around initialization bug) + g_tx_enable = 0; + g_rx_overrun = 0; + g_tx_underrun = 0; +#endif + + memset (hash1, 0, USRP_HASH_SIZE); // zero fpga bitstream hash. This forces reload + + init_usrp (); + init_gpif (); + + // if (UC_START_WITH_GSTATE_OUTPUT_ENABLED) + IFCONFIG |= bmGSTATE; // no conflict, start with it on + + set_led_0 (0); + set_led_1 (0); + + EA = 0; // disable all interrupts + + patch_usb_descriptors(); + + setup_autovectors (); + usb_install_handlers (); + hook_timer_tick ((unsigned short) isr_tick); + + EIEX4 = 1; // disable INT4 FIXME + EA = 1; // global interrupt enable + + fx2_renumerate (); // simulates disconnect / reconnect + + main_loop (); +} diff --git a/usrp/firmware/src/usrp2/usrp_rev2_regs.h b/usrp/firmware/src/usrp2/usrp_rev2_regs.h new file mode 100644 index 00000000..e18003f7 --- /dev/null +++ b/usrp/firmware/src/usrp2/usrp_rev2_regs.h @@ -0,0 +1,163 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * These are the register definitions for the Rev 1 USRP prototype + * The Rev 1 is the version with the AD9862's and daughterboards + */ + +#ifndef _USRP_REV1_REGS_H_ +#define _USRP_REV1_REGS_H_ + +#include "fx2regs.h" + +/* + * Port A (bit addressable): + */ + +#define USRP_PA IOA // Port A +#define USRP_PA_OE OEA // Port A direction register + +#define bmPA_S_CLK bmBIT0 // SPI serial clock +#define bmPA_S_DATA_TO_PERIPH bmBIT1 // SPI SDI (peripheral rel name) +#define bmPA_S_DATA_FROM_PERIPH bmBIT2 // SPI SDO (peripheral rel name) +#define bmPA_SEN_FPGA bmBIT3 // serial enable for FPGA (active low) +#define bmPA_SEN_CODEC_A bmBIT4 // serial enable AD9862 A (active low) +#define bmPA_SEN_CODEC_B bmBIT5 // serial enable AD9862 B (active low) +//#define bmPA_FX2_2 bmBIT6 // misc pin to FPGA (overflow) +//#define bmPA_FX2_3 bmBIT7 // misc pin to FPGA (underflow) +#define bmPA_RX_OVERRUN bmBIT6 // misc pin to FPGA (overflow) +#define bmPA_TX_UNDERRUN bmBIT7 // misc pin to FPGA (underflow) + + +sbit at 0x80+0 bitS_CLK; // 0x80 is the bit address of PORT A +sbit at 0x80+1 bitS_OUT; // out from FX2 point of view +sbit at 0x80+2 bitS_IN; // in from FX2 point of view + + +/* all outputs except S_DATA_FROM_PERIPH, FX2_2, FX2_3 */ + +#define bmPORT_A_OUTPUTS (bmPA_S_CLK \ + | bmPA_S_DATA_TO_PERIPH \ + | bmPA_SEN_FPGA \ + | bmPA_SEN_CODEC_A \ + | bmPA_SEN_CODEC_B \ + ) + +#define bmPORT_A_INITIAL (bmPA_SEN_FPGA | bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B) + + +/* Port B: GPIF FD[7:0] */ + +/* + * Port C (bit addressable): + * 5:1 FPGA configuration + */ + +#define USRP_PC IOC // Port C +#define USRP_PC_OE OEC // Port C direction register + +#define USRP_ALTERA_CONFIG USRP_PC + +#define bmPC_nRESET bmBIT0 // reset line to codecs (active low) +#define bmALTERA_DATA0 bmBIT1 +#define bmALTERA_NCONFIG bmBIT2 +#define bmALTERA_DCLK bmBIT3 +#define bmALTERA_CONF_DONE bmBIT4 +#define bmALTERA_NSTATUS bmBIT5 +#define bmPC_LED0 bmBIT6 // active low +#define bmPC_LED1 bmBIT7 // active low + +sbit at 0xA0+1 bitALTERA_DATA0; // 0xA0 is the bit address of PORT C +sbit at 0xA0+3 bitALTERA_DCLK; + + +#define bmALTERA_BITS (bmALTERA_DATA0 \ + | bmALTERA_NCONFIG \ + | bmALTERA_DCLK \ + | bmALTERA_CONF_DONE \ + | bmALTERA_NSTATUS) + +#define bmPORT_C_OUTPUTS (bmPC_nRESET \ + | bmALTERA_DATA0 \ + | bmALTERA_NCONFIG \ + | bmALTERA_DCLK \ + | bmPC_LED0 \ + | bmPC_LED1 \ + ) + +#define bmPORT_C_INITIAL (bmPC_LED0 | bmPC_LED1) + + +#define USRP_LED_REG USRP_PC +#define bmLED0 bmPC_LED0 +#define bmLED1 bmPC_LED1 + + +/* Port D: GPIF FD[15:8] */ + +/* Port E: not bit addressible */ + +#define USRP_PE IOE // Port E +#define USRP_PE_OE OEE // Port E direction register + +#define bmPE_PE0 bmBIT0 // GPIF debug output +#define bmPE_PE1 bmBIT1 // GPIF debug output +#define bmPE_PE2 bmBIT2 // GPIF debug output +#define bmPE_FPGA_CLR_STATUS bmBIT3 // misc pin to FPGA (clear status) +#define bmPE_SEN_TX_A bmBIT4 // serial enable d'board TX A (active low) +#define bmPE_SEN_RX_A bmBIT5 // serial enable d'board RX A (active low) +#define bmPE_SEN_TX_B bmBIT6 // serial enable d'board TX B (active low) +#define bmPE_SEN_RX_B bmBIT7 // serial enable d'board RX B (active low) + + +#define bmPORT_E_OUTPUTS (bmPE_FPGA_CLR_STATUS \ + | bmPE_SEN_TX_A \ + | bmPE_SEN_RX_A \ + | bmPE_SEN_TX_B \ + | bmPE_SEN_RX_B \ + ) + + +#define bmPORT_E_INITIAL (bmPE_SEN_TX_A \ + | bmPE_SEN_RX_A \ + | bmPE_SEN_TX_B \ + | bmPE_SEN_RX_B \ + ) + +/* + * FPGA output lines that are tied to FX2 RDYx inputs. + * These are readable using GPIFREADYSTAT. + */ +#define bmFPGA_HAS_SPACE bmBIT0 // usbrdy[0] has room for 512 byte packet +#define bmFPGA_PKT_AVAIL bmBIT1 // usbrdy[1] has >= 512 bytes available +// #define bmTX_UNDERRUN bmBIT2 // usbrdy[2] D/A ran out of data +// #define bmRX_OVERRUN bmBIT3 // usbrdy[3] A/D ran out of buffer + +/* + * FPGA input lines that are tied to the FX2 CTLx outputs. + * + * These are controlled by the GPIF microprogram... + */ +// WR bmBIT0 // usbctl[0] +// RD bmBIT1 // usbctl[1] +// OE bmBIT2 // usbctl[2] + +#endif /* _USRP_REV1_REGS_H_ */ diff --git a/usrp/firmware/src/usrp2/vectors.a51 b/usrp/firmware/src/usrp2/vectors.a51 new file mode 100644 index 00000000..fa579ba8 --- /dev/null +++ b/usrp/firmware/src/usrp2/vectors.a51 @@ -0,0 +1 @@ + .include "../common/vectors.a51" diff --git a/usrp/fpga/Makefile.am b/usrp/fpga/Makefile.am new file mode 100644 index 00000000..61227f05 --- /dev/null +++ b/usrp/fpga/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = rbf + +include Makefile.extra diff --git a/usrp/fpga/Makefile.extra b/usrp/fpga/Makefile.extra new file mode 100644 index 00000000..c3ccaa04 --- /dev/null +++ b/usrp/fpga/Makefile.extra @@ -0,0 +1,150 @@ +EXTRA_DIST = \ + gen_makefile_extra.py \ + megacells/accum32.bsf \ + megacells/accum32.cmp \ + megacells/accum32.inc \ + megacells/accum32.v \ + megacells/accum32_bb.v \ + megacells/accum32_inst.v \ + megacells/add32.bsf \ + megacells/add32.cmp \ + megacells/add32.inc \ + megacells/add32.v \ + megacells/add32_bb.v \ + megacells/add32_inst.v \ + megacells/addsub16.bsf \ + megacells/addsub16.cmp \ + megacells/addsub16.inc \ + megacells/addsub16.v \ + megacells/addsub16_bb.v \ + megacells/addsub16_inst.v \ + megacells/bustri.bsf \ + megacells/bustri.cmp \ + megacells/bustri.inc \ + megacells/bustri.v \ + megacells/bustri_bb.v \ + megacells/bustri_inst.v \ + megacells/clk_doubler.v \ + megacells/clk_doubler_bb.v \ + megacells/dspclkpll.v \ + megacells/dspclkpll_bb.v \ + megacells/fifo_2k.v \ + megacells/fifo_2k_bb.v \ + megacells/fifo_4k.v \ + megacells/fifo_4k_bb.v \ + megacells/mylpm_addsub.bsf \ + megacells/mylpm_addsub.cmp \ + megacells/mylpm_addsub.inc \ + megacells/mylpm_addsub.v \ + megacells/mylpm_addsub_bb.v \ + megacells/mylpm_addsub_inst.v \ + megacells/pll.v \ + megacells/pll_bb.v \ + megacells/pll_inst.v \ + megacells/sub32.bsf \ + megacells/sub32.cmp \ + megacells/sub32.inc \ + megacells/sub32.v \ + megacells/sub32_bb.v \ + megacells/sub32_inst.v \ + models/bustri.v \ + models/fifo.v \ + models/fifo_1c_1k.v \ + models/fifo_1c_2k.v \ + models/fifo_1c_4k.v \ + models/fifo_1k.v \ + models/fifo_2k.v \ + models/fifo_4k.v \ + models/pll.v \ + models/ssram.v \ + sdr_lib/adc_interface.v \ + sdr_lib/bidir_reg.v \ + sdr_lib/bus_interface.v \ + sdr_lib/cic_decim.v \ + sdr_lib/cic_int_shifter.v \ + sdr_lib/cic_interp.v \ + sdr_lib/clk_divider.v \ + sdr_lib/cordic.v \ + sdr_lib/cordic_stage.v \ + sdr_lib/ddc.v \ + sdr_lib/dpram.v \ + sdr_lib/duc.v \ + sdr_lib/ext_fifo.v \ + sdr_lib/gen_cordic_consts.py \ + sdr_lib/gen_sync.v \ + sdr_lib/hb/acc.v \ + sdr_lib/hb/coeff_ram.v \ + sdr_lib/hb/coeff_rom.v \ + sdr_lib/hb/halfband_decim.v \ + sdr_lib/hb/halfband_interp.v \ + sdr_lib/hb/hbd_tb/test_hbd.v \ + sdr_lib/hb/mac.v \ + sdr_lib/hb/mult.v \ + sdr_lib/hb/ram16_2port.v \ + sdr_lib/hb/ram16_2sum.v \ + sdr_lib/hb/ram32_2sum.v \ + sdr_lib/io_pins.v \ + sdr_lib/master_control.v \ + sdr_lib/master_control_multi.v \ + sdr_lib/phase_acc.v \ + sdr_lib/ram.v \ + sdr_lib/ram16.v \ + sdr_lib/ram32.v \ + sdr_lib/ram64.v \ + sdr_lib/rx_buffer.v \ + sdr_lib/rx_chain.v \ + sdr_lib/rx_chain_dual.v \ + sdr_lib/rx_dcoffset.v \ + sdr_lib/serial_io.v \ + sdr_lib/setting_reg.v \ + sdr_lib/setting_reg_masked.v \ + sdr_lib/sign_extend.v \ + sdr_lib/strobe_gen.v \ + sdr_lib/tx_buffer.v \ + sdr_lib/tx_chain.v \ + sdr_lib/tx_chain_hb.v \ + tb/cbus_tb.v \ + tb/cordic_tb.v \ + tb/decim_tb.v \ + tb/fullchip_tb.v \ + tb/interp_tb.v \ + tb/justinterp_tb.v \ + tb/usrp_tasks.v \ + toplevel/mrfm/biquad_2stage.v \ + toplevel/mrfm/biquad_6stage.v \ + toplevel/mrfm/mrfm.csf \ + toplevel/mrfm/mrfm.esf \ + toplevel/mrfm/mrfm.psf \ + toplevel/mrfm/mrfm.py \ + toplevel/mrfm/mrfm.qpf \ + toplevel/mrfm/mrfm.qsf \ + toplevel/mrfm/mrfm.v \ + toplevel/mrfm/mrfm.vh \ + toplevel/mrfm/mrfm_compensator.v \ + toplevel/mrfm/mrfm_fft.py \ + toplevel/mrfm/mrfm_proc.v \ + toplevel/mrfm/shifter.v \ + toplevel/sizetest/sizetest.csf \ + toplevel/sizetest/sizetest.psf \ + toplevel/sizetest/sizetest.v \ + toplevel/usrp_multi/usrp_multi.csf \ + toplevel/usrp_multi/usrp_multi.esf \ + toplevel/usrp_multi/usrp_multi.psf \ + toplevel/usrp_multi/usrp_multi.qpf \ + toplevel/usrp_multi/usrp_multi.qsf \ + toplevel/usrp_multi/usrp_multi.v \ + toplevel/usrp_multi/usrp_multi.vh \ + toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh \ + toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh \ + toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh \ + toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh \ + toplevel/usrp_multi/usrp_std.vh \ + toplevel/usrp_std/usrp_std.csf \ + toplevel/usrp_std/usrp_std.esf \ + toplevel/usrp_std/usrp_std.psf \ + toplevel/usrp_std/usrp_std.qpf \ + toplevel/usrp_std/usrp_std.qsf \ + toplevel/usrp_std/usrp_std.v \ + toplevel/usrp_std/usrp_std.vh \ + toplevel/usrp_std/usrp_std_config_2rxhb_2tx.vh \ + toplevel/usrp_std/usrp_std_config_4rx_0tx.vh diff --git a/usrp/fpga/TODO b/usrp/fpga/TODO new file mode 100644 index 00000000..76287c3d --- /dev/null +++ b/usrp/fpga/TODO @@ -0,0 +1,23 @@ + + +Area Reduction +============== +Reduce one or both stages of dec/interp to max rate of 8 instead of 16 +Optimize CICs to minimize registers +Reduce width of RX CORDIC +Fix CORDIC wasted logic cells from bad synthesis +Progressively narrow x,y,z on CORDIC +16-bit wide FIFOs, split IQ/channels on other side (?) + +Enhancements +============ +Halfband filter in Spartan 3 +Muxing of inputs +Switch over to newfc +RAM interface? + +Other +===== +Capture/Transmit straight samples (no DUC/DDC) + + diff --git a/usrp/fpga/gen_makefile_extra.py b/usrp/fpga/gen_makefile_extra.py new file mode 100755 index 00000000..165a8494 --- /dev/null +++ b/usrp/fpga/gen_makefile_extra.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Generate Makefile.extra +""" + +import sys +import os.path + +extensions_we_like = ( + '.v', '.vh', + '.csf', '.esf', '.psf', '.qpf', '.qsf', + '.inc', '.cmp', '.bsf', + '.py') + +def visit(keepers, dirname, names): + if 'rbf' in names: + names.remove('rbf') + if 'CVS' in names: + names.remove('CVS') + + if dirname == '.': + dirname = '' + if dirname.startswith('./'): + dirname = dirname[2:] + + for n in names: + base, ext = os.path.splitext(n) + if ext in extensions_we_like: + keepers.append(os.path.join(dirname, n)) + +def generate(f): + keepers = [] + os.path.walk('.', visit, keepers) + keepers.sort() + write_keepers(keepers, f) + +def write_keepers(files, outf): + m = reduce(max, map(len, files), 0) + e = 'EXTRA_DIST =' + outf.write('%s%s \\\n' % (e, (m-len(e)+8) * ' ')) + for f in files[:-1]: + outf.write('\t%s%s \\\n' % (f, (m-len(f)) * ' ')) + outf.write('\t%s\n' % (files[-1],)) + +if __name__ == '__main__': + generate(open('Makefile.extra','w')) diff --git a/usrp/fpga/megacells/accum32.bsf b/usrp/fpga/megacells/accum32.bsf new file mode 100755 index 00000000..494a8200 --- /dev/null +++ b/usrp/fpga/megacells/accum32.bsf @@ -0,0 +1,86 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2003 Altera Corporation +Any megafunction design, and related netlist (encrypted or decrypted), +support information, device programming or simulation file, and any other +associated documentation or information provided by Altera or a partner +under Altera's Megafunction Partnership Program may be used only +to program PLD devices (but not masked PLD devices) from Altera. Any +other use of such megafunction design, netlist, support information, +device programming or simulation file, or any other related documentation +or information is prohibited for any other purpose, including, but not +limited to modification, reverse engineering, de-compiling, or use with +any other silicon devices, unless such use is explicitly licensed under +a separate agreement with Altera or a megafunction partner. Title to the +intellectual property, including patents, copyrights, trademarks, trade +secrets, or maskworks, embodied in any such megafunction design, netlist, +support information, device programming or simulation file, or any other +related documentation or information provided by Altera or a megafunction +partner, remains with Altera, the megafunction partner, or their respective +licensors. No other licenses, including any licenses needed under any third +party's intellectual property, are provided herein. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 240 120) + (text "accum32" (rect 87 2 166 21)(font "Arial" (font_size 10))) + (text "inst" (rect 8 101 31 116)(font "Arial" )) + (port + (pt 0 40) + (input) + (text "data[31..0]" (rect 0 0 73 16)(font "Arial" (font_size 8))) + (text "data[31..0]" (rect 20 24 82 40)(font "Arial" (font_size 8))) + (line (pt 0 40)(pt 16 40)(line_width 3)) + ) + (port + (pt 0 56) + (input) + (text "clock" (rect 0 0 36 16)(font "Arial" (font_size 8))) + (text "clock" (rect 20 40 51 56)(font "Arial" (font_size 8))) + (line (pt 0 56)(pt 16 56)(line_width 1)) + ) + (port + (pt 0 72) + (input) + (text "clken" (rect 0 0 36 16)(font "Arial" (font_size 8))) + (text "clken" (rect 20 56 51 72)(font "Arial" (font_size 8))) + (line (pt 0 72)(pt 16 72)(line_width 1)) + ) + (port + (pt 0 96) + (input) + (text "aclr" (rect 0 0 24 16)(font "Arial" (font_size 8))) + (text "aclr" (rect 20 80 41 96)(font "Arial" (font_size 8))) + (line (pt 0 96)(pt 16 96)(line_width 1)) + ) + (port + (pt 240 56) + (output) + (text "result[31..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "result[31..0]" (rect 152 40 221 56)(font "Arial" (font_size 8))) + (line (pt 240 56)(pt 224 56)(line_width 3)) + ) + (drawing + (text "acc" (rect 102 48 123 64)(font "Arial" (font_size 8))) + (text "SIGNED" (rect 177 18 214 32)(font "Arial" )) + (line (pt 16 16)(pt 224 16)(line_width 1)) + (line (pt 16 16)(pt 16 104)(line_width 1)) + (line (pt 16 104)(pt 224 104)(line_width 1)) + (line (pt 224 16)(pt 224 104)(line_width 1)) + (line (pt 88 24)(pt 136 48)(line_width 1)) + (line (pt 136 64)(pt 136 48)(line_width 1)) + (line (pt 88 88)(pt 136 64)(line_width 1)) + (line (pt 88 24)(pt 88 88)(line_width 1)) + (line (pt 16 40)(pt 88 40)(line_width 1)) + (line (pt 16 56)(pt 88 56)(line_width 1)) + (line (pt 136 56)(pt 224 56)(line_width 1)) + (line (pt 16 72)(pt 88 72)(line_width 1)) + (line (pt 16 72)(pt 88 72)(line_width 1)) + (line (pt 16 96)(pt 104 96)(line_width 1)) + (line (pt 104 96)(pt 104 80)(line_width 1)) + ) +) diff --git a/usrp/fpga/megacells/accum32.cmp b/usrp/fpga/megacells/accum32.cmp new file mode 100755 index 00000000..55b5fdc2 --- /dev/null +++ b/usrp/fpga/megacells/accum32.cmp @@ -0,0 +1,31 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +component accum32 + PORT + ( + data : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + clock : IN STD_LOGIC := '0'; + clken : IN STD_LOGIC := '1'; + aclr : IN STD_LOGIC := '0'; + result : OUT STD_LOGIC_VECTOR (31 DOWNTO 0) + ); +end component; diff --git a/usrp/fpga/megacells/accum32.inc b/usrp/fpga/megacells/accum32.inc new file mode 100755 index 00000000..6c669002 --- /dev/null +++ b/usrp/fpga/megacells/accum32.inc @@ -0,0 +1,32 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +FUNCTION accum32 +( + data[31..0], + clock, + clken, + aclr +) + +RETURNS ( + result[31..0] +); diff --git a/usrp/fpga/megacells/accum32.v b/usrp/fpga/megacells/accum32.v new file mode 100755 index 00000000..ce50cbbf --- /dev/null +++ b/usrp/fpga/megacells/accum32.v @@ -0,0 +1,765 @@ +// megafunction wizard: %ALTACCUMULATE%CBX% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altaccumulate + +// ============================================================ +// File Name: accum32.v +// Megafunction Name(s): +// altaccumulate +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +//altaccumulate DEVICE_FAMILY=Cyclone LPM_REPRESENTATION=SIGNED WIDTH_IN=32 WIDTH_OUT=32 aclr clken clock data result +//VERSION_BEGIN 3.0 cbx_altaccumulate 2003:04:08:16:04:48:SJ cbx_mgl 2003:06:11:11:00:44:SJ cbx_stratix 2003:05:16:10:26:50:SJ VERSION_END + +//synthesis_resources = lut 32 +module accum32_accum_nta + ( + aclr, + clken, + clock, + data, + result) /* synthesis synthesis_clearbox=1 */; + input aclr; + input clken; + input clock; + input [31:0] data; + output [31:0] result; + + wire [0:0] wire_acc_cella_0cout; + wire [0:0] wire_acc_cella_1cout; + wire [0:0] wire_acc_cella_2cout; + wire [0:0] wire_acc_cella_3cout; + wire [0:0] wire_acc_cella_4cout; + wire [0:0] wire_acc_cella_5cout; + wire [0:0] wire_acc_cella_6cout; + wire [0:0] wire_acc_cella_7cout; + wire [0:0] wire_acc_cella_8cout; + wire [0:0] wire_acc_cella_9cout; + wire [0:0] wire_acc_cella_10cout; + wire [0:0] wire_acc_cella_11cout; + wire [0:0] wire_acc_cella_12cout; + wire [0:0] wire_acc_cella_13cout; + wire [0:0] wire_acc_cella_14cout; + wire [0:0] wire_acc_cella_15cout; + wire [0:0] wire_acc_cella_16cout; + wire [0:0] wire_acc_cella_17cout; + wire [0:0] wire_acc_cella_18cout; + wire [0:0] wire_acc_cella_19cout; + wire [0:0] wire_acc_cella_20cout; + wire [0:0] wire_acc_cella_21cout; + wire [0:0] wire_acc_cella_22cout; + wire [0:0] wire_acc_cella_23cout; + wire [0:0] wire_acc_cella_24cout; + wire [0:0] wire_acc_cella_25cout; + wire [0:0] wire_acc_cella_26cout; + wire [0:0] wire_acc_cella_27cout; + wire [0:0] wire_acc_cella_28cout; + wire [0:0] wire_acc_cella_29cout; + wire [0:0] wire_acc_cella_30cout; + wire [31:0] wire_acc_cella_dataa; + wire [31:0] wire_acc_cella_datab; + wire [31:0] wire_acc_cella_datac; + wire [31:0] wire_acc_cella_regout; + wire sload; + + stratix_lcell acc_cella_0 + ( + .aclr(aclr), + .cin(1'b0), + .clk(clock), + .cout(wire_acc_cella_0cout[0:0]), + .dataa(wire_acc_cella_dataa[0:0]), + .datab(wire_acc_cella_datab[0:0]), + .datac(wire_acc_cella_datac[0:0]), + .ena(clken), + .regout(wire_acc_cella_regout[0:0]), + .sload(sload)); + defparam + acc_cella_0.cin_used = "true", + acc_cella_0.lut_mask = "96e8", + acc_cella_0.operation_mode = "arithmetic", + acc_cella_0.sum_lutc_input = "cin", + acc_cella_0.synch_mode = "on", + acc_cella_0.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_1 + ( + .aclr(aclr), + .cin(wire_acc_cella_0cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_1cout[0:0]), + .dataa(wire_acc_cella_dataa[1:1]), + .datab(wire_acc_cella_datab[1:1]), + .datac(wire_acc_cella_datac[1:1]), + .ena(clken), + .regout(wire_acc_cella_regout[1:1]), + .sload(sload)); + defparam + acc_cella_1.cin_used = "true", + acc_cella_1.lut_mask = "96e8", + acc_cella_1.operation_mode = "arithmetic", + acc_cella_1.sum_lutc_input = "cin", + acc_cella_1.synch_mode = "on", + acc_cella_1.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_2 + ( + .aclr(aclr), + .cin(wire_acc_cella_1cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_2cout[0:0]), + .dataa(wire_acc_cella_dataa[2:2]), + .datab(wire_acc_cella_datab[2:2]), + .datac(wire_acc_cella_datac[2:2]), + .ena(clken), + .regout(wire_acc_cella_regout[2:2]), + .sload(sload)); + defparam + acc_cella_2.cin_used = "true", + acc_cella_2.lut_mask = "96e8", + acc_cella_2.operation_mode = "arithmetic", + acc_cella_2.sum_lutc_input = "cin", + acc_cella_2.synch_mode = "on", + acc_cella_2.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_3 + ( + .aclr(aclr), + .cin(wire_acc_cella_2cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_3cout[0:0]), + .dataa(wire_acc_cella_dataa[3:3]), + .datab(wire_acc_cella_datab[3:3]), + .datac(wire_acc_cella_datac[3:3]), + .ena(clken), + .regout(wire_acc_cella_regout[3:3]), + .sload(sload)); + defparam + acc_cella_3.cin_used = "true", + acc_cella_3.lut_mask = "96e8", + acc_cella_3.operation_mode = "arithmetic", + acc_cella_3.sum_lutc_input = "cin", + acc_cella_3.synch_mode = "on", + acc_cella_3.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_4 + ( + .aclr(aclr), + .cin(wire_acc_cella_3cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_4cout[0:0]), + .dataa(wire_acc_cella_dataa[4:4]), + .datab(wire_acc_cella_datab[4:4]), + .datac(wire_acc_cella_datac[4:4]), + .ena(clken), + .regout(wire_acc_cella_regout[4:4]), + .sload(sload)); + defparam + acc_cella_4.cin_used = "true", + acc_cella_4.lut_mask = "96e8", + acc_cella_4.operation_mode = "arithmetic", + acc_cella_4.sum_lutc_input = "cin", + acc_cella_4.synch_mode = "on", + acc_cella_4.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_5 + ( + .aclr(aclr), + .cin(wire_acc_cella_4cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_5cout[0:0]), + .dataa(wire_acc_cella_dataa[5:5]), + .datab(wire_acc_cella_datab[5:5]), + .datac(wire_acc_cella_datac[5:5]), + .ena(clken), + .regout(wire_acc_cella_regout[5:5]), + .sload(sload)); + defparam + acc_cella_5.cin_used = "true", + acc_cella_5.lut_mask = "96e8", + acc_cella_5.operation_mode = "arithmetic", + acc_cella_5.sum_lutc_input = "cin", + acc_cella_5.synch_mode = "on", + acc_cella_5.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_6 + ( + .aclr(aclr), + .cin(wire_acc_cella_5cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_6cout[0:0]), + .dataa(wire_acc_cella_dataa[6:6]), + .datab(wire_acc_cella_datab[6:6]), + .datac(wire_acc_cella_datac[6:6]), + .ena(clken), + .regout(wire_acc_cella_regout[6:6]), + .sload(sload)); + defparam + acc_cella_6.cin_used = "true", + acc_cella_6.lut_mask = "96e8", + acc_cella_6.operation_mode = "arithmetic", + acc_cella_6.sum_lutc_input = "cin", + acc_cella_6.synch_mode = "on", + acc_cella_6.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_7 + ( + .aclr(aclr), + .cin(wire_acc_cella_6cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_7cout[0:0]), + .dataa(wire_acc_cella_dataa[7:7]), + .datab(wire_acc_cella_datab[7:7]), + .datac(wire_acc_cella_datac[7:7]), + .ena(clken), + .regout(wire_acc_cella_regout[7:7]), + .sload(sload)); + defparam + acc_cella_7.cin_used = "true", + acc_cella_7.lut_mask = "96e8", + acc_cella_7.operation_mode = "arithmetic", + acc_cella_7.sum_lutc_input = "cin", + acc_cella_7.synch_mode = "on", + acc_cella_7.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_8 + ( + .aclr(aclr), + .cin(wire_acc_cella_7cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_8cout[0:0]), + .dataa(wire_acc_cella_dataa[8:8]), + .datab(wire_acc_cella_datab[8:8]), + .datac(wire_acc_cella_datac[8:8]), + .ena(clken), + .regout(wire_acc_cella_regout[8:8]), + .sload(sload)); + defparam + acc_cella_8.cin_used = "true", + acc_cella_8.lut_mask = "96e8", + acc_cella_8.operation_mode = "arithmetic", + acc_cella_8.sum_lutc_input = "cin", + acc_cella_8.synch_mode = "on", + acc_cella_8.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_9 + ( + .aclr(aclr), + .cin(wire_acc_cella_8cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_9cout[0:0]), + .dataa(wire_acc_cella_dataa[9:9]), + .datab(wire_acc_cella_datab[9:9]), + .datac(wire_acc_cella_datac[9:9]), + .ena(clken), + .regout(wire_acc_cella_regout[9:9]), + .sload(sload)); + defparam + acc_cella_9.cin_used = "true", + acc_cella_9.lut_mask = "96e8", + acc_cella_9.operation_mode = "arithmetic", + acc_cella_9.sum_lutc_input = "cin", + acc_cella_9.synch_mode = "on", + acc_cella_9.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_10 + ( + .aclr(aclr), + .cin(wire_acc_cella_9cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_10cout[0:0]), + .dataa(wire_acc_cella_dataa[10:10]), + .datab(wire_acc_cella_datab[10:10]), + .datac(wire_acc_cella_datac[10:10]), + .ena(clken), + .regout(wire_acc_cella_regout[10:10]), + .sload(sload)); + defparam + acc_cella_10.cin_used = "true", + acc_cella_10.lut_mask = "96e8", + acc_cella_10.operation_mode = "arithmetic", + acc_cella_10.sum_lutc_input = "cin", + acc_cella_10.synch_mode = "on", + acc_cella_10.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_11 + ( + .aclr(aclr), + .cin(wire_acc_cella_10cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_11cout[0:0]), + .dataa(wire_acc_cella_dataa[11:11]), + .datab(wire_acc_cella_datab[11:11]), + .datac(wire_acc_cella_datac[11:11]), + .ena(clken), + .regout(wire_acc_cella_regout[11:11]), + .sload(sload)); + defparam + acc_cella_11.cin_used = "true", + acc_cella_11.lut_mask = "96e8", + acc_cella_11.operation_mode = "arithmetic", + acc_cella_11.sum_lutc_input = "cin", + acc_cella_11.synch_mode = "on", + acc_cella_11.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_12 + ( + .aclr(aclr), + .cin(wire_acc_cella_11cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_12cout[0:0]), + .dataa(wire_acc_cella_dataa[12:12]), + .datab(wire_acc_cella_datab[12:12]), + .datac(wire_acc_cella_datac[12:12]), + .ena(clken), + .regout(wire_acc_cella_regout[12:12]), + .sload(sload)); + defparam + acc_cella_12.cin_used = "true", + acc_cella_12.lut_mask = "96e8", + acc_cella_12.operation_mode = "arithmetic", + acc_cella_12.sum_lutc_input = "cin", + acc_cella_12.synch_mode = "on", + acc_cella_12.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_13 + ( + .aclr(aclr), + .cin(wire_acc_cella_12cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_13cout[0:0]), + .dataa(wire_acc_cella_dataa[13:13]), + .datab(wire_acc_cella_datab[13:13]), + .datac(wire_acc_cella_datac[13:13]), + .ena(clken), + .regout(wire_acc_cella_regout[13:13]), + .sload(sload)); + defparam + acc_cella_13.cin_used = "true", + acc_cella_13.lut_mask = "96e8", + acc_cella_13.operation_mode = "arithmetic", + acc_cella_13.sum_lutc_input = "cin", + acc_cella_13.synch_mode = "on", + acc_cella_13.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_14 + ( + .aclr(aclr), + .cin(wire_acc_cella_13cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_14cout[0:0]), + .dataa(wire_acc_cella_dataa[14:14]), + .datab(wire_acc_cella_datab[14:14]), + .datac(wire_acc_cella_datac[14:14]), + .ena(clken), + .regout(wire_acc_cella_regout[14:14]), + .sload(sload)); + defparam + acc_cella_14.cin_used = "true", + acc_cella_14.lut_mask = "96e8", + acc_cella_14.operation_mode = "arithmetic", + acc_cella_14.sum_lutc_input = "cin", + acc_cella_14.synch_mode = "on", + acc_cella_14.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_15 + ( + .aclr(aclr), + .cin(wire_acc_cella_14cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_15cout[0:0]), + .dataa(wire_acc_cella_dataa[15:15]), + .datab(wire_acc_cella_datab[15:15]), + .datac(wire_acc_cella_datac[15:15]), + .ena(clken), + .regout(wire_acc_cella_regout[15:15]), + .sload(sload)); + defparam + acc_cella_15.cin_used = "true", + acc_cella_15.lut_mask = "96e8", + acc_cella_15.operation_mode = "arithmetic", + acc_cella_15.sum_lutc_input = "cin", + acc_cella_15.synch_mode = "on", + acc_cella_15.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_16 + ( + .aclr(aclr), + .cin(wire_acc_cella_15cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_16cout[0:0]), + .dataa(wire_acc_cella_dataa[16:16]), + .datab(wire_acc_cella_datab[16:16]), + .datac(wire_acc_cella_datac[16:16]), + .ena(clken), + .regout(wire_acc_cella_regout[16:16]), + .sload(sload)); + defparam + acc_cella_16.cin_used = "true", + acc_cella_16.lut_mask = "96e8", + acc_cella_16.operation_mode = "arithmetic", + acc_cella_16.sum_lutc_input = "cin", + acc_cella_16.synch_mode = "on", + acc_cella_16.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_17 + ( + .aclr(aclr), + .cin(wire_acc_cella_16cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_17cout[0:0]), + .dataa(wire_acc_cella_dataa[17:17]), + .datab(wire_acc_cella_datab[17:17]), + .datac(wire_acc_cella_datac[17:17]), + .ena(clken), + .regout(wire_acc_cella_regout[17:17]), + .sload(sload)); + defparam + acc_cella_17.cin_used = "true", + acc_cella_17.lut_mask = "96e8", + acc_cella_17.operation_mode = "arithmetic", + acc_cella_17.sum_lutc_input = "cin", + acc_cella_17.synch_mode = "on", + acc_cella_17.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_18 + ( + .aclr(aclr), + .cin(wire_acc_cella_17cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_18cout[0:0]), + .dataa(wire_acc_cella_dataa[18:18]), + .datab(wire_acc_cella_datab[18:18]), + .datac(wire_acc_cella_datac[18:18]), + .ena(clken), + .regout(wire_acc_cella_regout[18:18]), + .sload(sload)); + defparam + acc_cella_18.cin_used = "true", + acc_cella_18.lut_mask = "96e8", + acc_cella_18.operation_mode = "arithmetic", + acc_cella_18.sum_lutc_input = "cin", + acc_cella_18.synch_mode = "on", + acc_cella_18.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_19 + ( + .aclr(aclr), + .cin(wire_acc_cella_18cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_19cout[0:0]), + .dataa(wire_acc_cella_dataa[19:19]), + .datab(wire_acc_cella_datab[19:19]), + .datac(wire_acc_cella_datac[19:19]), + .ena(clken), + .regout(wire_acc_cella_regout[19:19]), + .sload(sload)); + defparam + acc_cella_19.cin_used = "true", + acc_cella_19.lut_mask = "96e8", + acc_cella_19.operation_mode = "arithmetic", + acc_cella_19.sum_lutc_input = "cin", + acc_cella_19.synch_mode = "on", + acc_cella_19.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_20 + ( + .aclr(aclr), + .cin(wire_acc_cella_19cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_20cout[0:0]), + .dataa(wire_acc_cella_dataa[20:20]), + .datab(wire_acc_cella_datab[20:20]), + .datac(wire_acc_cella_datac[20:20]), + .ena(clken), + .regout(wire_acc_cella_regout[20:20]), + .sload(sload)); + defparam + acc_cella_20.cin_used = "true", + acc_cella_20.lut_mask = "96e8", + acc_cella_20.operation_mode = "arithmetic", + acc_cella_20.sum_lutc_input = "cin", + acc_cella_20.synch_mode = "on", + acc_cella_20.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_21 + ( + .aclr(aclr), + .cin(wire_acc_cella_20cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_21cout[0:0]), + .dataa(wire_acc_cella_dataa[21:21]), + .datab(wire_acc_cella_datab[21:21]), + .datac(wire_acc_cella_datac[21:21]), + .ena(clken), + .regout(wire_acc_cella_regout[21:21]), + .sload(sload)); + defparam + acc_cella_21.cin_used = "true", + acc_cella_21.lut_mask = "96e8", + acc_cella_21.operation_mode = "arithmetic", + acc_cella_21.sum_lutc_input = "cin", + acc_cella_21.synch_mode = "on", + acc_cella_21.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_22 + ( + .aclr(aclr), + .cin(wire_acc_cella_21cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_22cout[0:0]), + .dataa(wire_acc_cella_dataa[22:22]), + .datab(wire_acc_cella_datab[22:22]), + .datac(wire_acc_cella_datac[22:22]), + .ena(clken), + .regout(wire_acc_cella_regout[22:22]), + .sload(sload)); + defparam + acc_cella_22.cin_used = "true", + acc_cella_22.lut_mask = "96e8", + acc_cella_22.operation_mode = "arithmetic", + acc_cella_22.sum_lutc_input = "cin", + acc_cella_22.synch_mode = "on", + acc_cella_22.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_23 + ( + .aclr(aclr), + .cin(wire_acc_cella_22cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_23cout[0:0]), + .dataa(wire_acc_cella_dataa[23:23]), + .datab(wire_acc_cella_datab[23:23]), + .datac(wire_acc_cella_datac[23:23]), + .ena(clken), + .regout(wire_acc_cella_regout[23:23]), + .sload(sload)); + defparam + acc_cella_23.cin_used = "true", + acc_cella_23.lut_mask = "96e8", + acc_cella_23.operation_mode = "arithmetic", + acc_cella_23.sum_lutc_input = "cin", + acc_cella_23.synch_mode = "on", + acc_cella_23.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_24 + ( + .aclr(aclr), + .cin(wire_acc_cella_23cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_24cout[0:0]), + .dataa(wire_acc_cella_dataa[24:24]), + .datab(wire_acc_cella_datab[24:24]), + .datac(wire_acc_cella_datac[24:24]), + .ena(clken), + .regout(wire_acc_cella_regout[24:24]), + .sload(sload)); + defparam + acc_cella_24.cin_used = "true", + acc_cella_24.lut_mask = "96e8", + acc_cella_24.operation_mode = "arithmetic", + acc_cella_24.sum_lutc_input = "cin", + acc_cella_24.synch_mode = "on", + acc_cella_24.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_25 + ( + .aclr(aclr), + .cin(wire_acc_cella_24cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_25cout[0:0]), + .dataa(wire_acc_cella_dataa[25:25]), + .datab(wire_acc_cella_datab[25:25]), + .datac(wire_acc_cella_datac[25:25]), + .ena(clken), + .regout(wire_acc_cella_regout[25:25]), + .sload(sload)); + defparam + acc_cella_25.cin_used = "true", + acc_cella_25.lut_mask = "96e8", + acc_cella_25.operation_mode = "arithmetic", + acc_cella_25.sum_lutc_input = "cin", + acc_cella_25.synch_mode = "on", + acc_cella_25.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_26 + ( + .aclr(aclr), + .cin(wire_acc_cella_25cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_26cout[0:0]), + .dataa(wire_acc_cella_dataa[26:26]), + .datab(wire_acc_cella_datab[26:26]), + .datac(wire_acc_cella_datac[26:26]), + .ena(clken), + .regout(wire_acc_cella_regout[26:26]), + .sload(sload)); + defparam + acc_cella_26.cin_used = "true", + acc_cella_26.lut_mask = "96e8", + acc_cella_26.operation_mode = "arithmetic", + acc_cella_26.sum_lutc_input = "cin", + acc_cella_26.synch_mode = "on", + acc_cella_26.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_27 + ( + .aclr(aclr), + .cin(wire_acc_cella_26cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_27cout[0:0]), + .dataa(wire_acc_cella_dataa[27:27]), + .datab(wire_acc_cella_datab[27:27]), + .datac(wire_acc_cella_datac[27:27]), + .ena(clken), + .regout(wire_acc_cella_regout[27:27]), + .sload(sload)); + defparam + acc_cella_27.cin_used = "true", + acc_cella_27.lut_mask = "96e8", + acc_cella_27.operation_mode = "arithmetic", + acc_cella_27.sum_lutc_input = "cin", + acc_cella_27.synch_mode = "on", + acc_cella_27.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_28 + ( + .aclr(aclr), + .cin(wire_acc_cella_27cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_28cout[0:0]), + .dataa(wire_acc_cella_dataa[28:28]), + .datab(wire_acc_cella_datab[28:28]), + .datac(wire_acc_cella_datac[28:28]), + .ena(clken), + .regout(wire_acc_cella_regout[28:28]), + .sload(sload)); + defparam + acc_cella_28.cin_used = "true", + acc_cella_28.lut_mask = "96e8", + acc_cella_28.operation_mode = "arithmetic", + acc_cella_28.sum_lutc_input = "cin", + acc_cella_28.synch_mode = "on", + acc_cella_28.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_29 + ( + .aclr(aclr), + .cin(wire_acc_cella_28cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_29cout[0:0]), + .dataa(wire_acc_cella_dataa[29:29]), + .datab(wire_acc_cella_datab[29:29]), + .datac(wire_acc_cella_datac[29:29]), + .ena(clken), + .regout(wire_acc_cella_regout[29:29]), + .sload(sload)); + defparam + acc_cella_29.cin_used = "true", + acc_cella_29.lut_mask = "96e8", + acc_cella_29.operation_mode = "arithmetic", + acc_cella_29.sum_lutc_input = "cin", + acc_cella_29.synch_mode = "on", + acc_cella_29.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_30 + ( + .aclr(aclr), + .cin(wire_acc_cella_29cout[0:0]), + .clk(clock), + .cout(wire_acc_cella_30cout[0:0]), + .dataa(wire_acc_cella_dataa[30:30]), + .datab(wire_acc_cella_datab[30:30]), + .datac(wire_acc_cella_datac[30:30]), + .ena(clken), + .regout(wire_acc_cella_regout[30:30]), + .sload(sload)); + defparam + acc_cella_30.cin_used = "true", + acc_cella_30.lut_mask = "96e8", + acc_cella_30.operation_mode = "arithmetic", + acc_cella_30.sum_lutc_input = "cin", + acc_cella_30.synch_mode = "on", + acc_cella_30.lpm_type = "stratix_lcell"; + stratix_lcell acc_cella_31 + ( + .aclr(aclr), + .cin(wire_acc_cella_30cout[0:0]), + .clk(clock), + .dataa(wire_acc_cella_dataa[31:31]), + .datab(wire_acc_cella_datab[31:31]), + .datac(wire_acc_cella_datac[31:31]), + .ena(clken), + .regout(wire_acc_cella_regout[31:31]), + .sload(sload)); + defparam + acc_cella_31.cin_used = "true", + acc_cella_31.lut_mask = "9696", + acc_cella_31.operation_mode = "normal", + acc_cella_31.sum_lutc_input = "cin", + acc_cella_31.synch_mode = "on", + acc_cella_31.lpm_type = "stratix_lcell"; + assign + wire_acc_cella_dataa = data, + wire_acc_cella_datab = wire_acc_cella_regout, + wire_acc_cella_datac = data; + assign + result = wire_acc_cella_regout, + sload = 1'b0; +endmodule //accum32_accum_nta +//VALID FILE + + +module accum32 ( + data, + clock, + clken, + aclr, + result)/* synthesis synthesis_clearbox = 1 */; + + input [31:0] data; + input clock; + input clken; + input aclr; + output [31:0] result; + + wire [31:0] sub_wire0; + wire [31:0] result = sub_wire0[31:0]; + + accum32_accum_nta accum32_accum_nta_component ( + .clken (clken), + .aclr (aclr), + .clock (clock), + .data (data), + .result (sub_wire0)); + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: WIDTH_IN NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_OUT NUMERIC "32" +// Retrieval info: PRIVATE: LPM_REPRESENTATION NUMERIC "0" +// Retrieval info: PRIVATE: SLOAD NUMERIC "0" +// Retrieval info: PRIVATE: ADD_SUB NUMERIC "0" +// Retrieval info: PRIVATE: CIN NUMERIC "0" +// Retrieval info: PRIVATE: CLKEN NUMERIC "1" +// Retrieval info: PRIVATE: ACLR NUMERIC "1" +// Retrieval info: PRIVATE: COUT NUMERIC "0" +// Retrieval info: PRIVATE: OVERFLOW NUMERIC "0" +// Retrieval info: PRIVATE: LATENCY NUMERIC "0" +// Retrieval info: PRIVATE: EXTRA_LATENCY NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: WIDTH_IN NUMERIC "32" +// Retrieval info: CONSTANT: WIDTH_OUT NUMERIC "32" +// Retrieval info: CONSTANT: LPM_REPRESENTATION STRING "SIGNED" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altaccumulate" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0] +// Retrieval info: USED_PORT: result 0 0 32 0 OUTPUT NODEFVAL result[31..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT GND clock +// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT VCC clken +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr +// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0 +// Retrieval info: CONNECT: result 0 0 32 0 @result 0 0 32 0 +// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @clken 0 0 0 0 clken 0 0 0 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all diff --git a/usrp/fpga/megacells/accum32_bb.v b/usrp/fpga/megacells/accum32_bb.v new file mode 100755 index 00000000..142bde88 --- /dev/null +++ b/usrp/fpga/megacells/accum32_bb.v @@ -0,0 +1,35 @@ +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module accum32 ( + data, + clock, + clken, + aclr, + result)/* synthesis synthesis_clearbox = 1 */; + + input [31:0] data; + input clock; + input clken; + input aclr; + output [31:0] result; + +endmodule + diff --git a/usrp/fpga/megacells/accum32_inst.v b/usrp/fpga/megacells/accum32_inst.v new file mode 100755 index 00000000..c354acca --- /dev/null +++ b/usrp/fpga/megacells/accum32_inst.v @@ -0,0 +1,7 @@ +accum32 accum32_inst ( + .data ( data_sig ), + .clock ( clock_sig ), + .clken ( clken_sig ), + .aclr ( aclr_sig ), + .result ( result_sig ) + ); diff --git a/usrp/fpga/megacells/add32.bsf b/usrp/fpga/megacells/add32.bsf new file mode 100755 index 00000000..b2da9fc2 --- /dev/null +++ b/usrp/fpga/megacells/add32.bsf @@ -0,0 +1,62 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2003 Altera Corporation +Any megafunction design, and related netlist (encrypted or decrypted), +support information, device programming or simulation file, and any other +associated documentation or information provided by Altera or a partner +under Altera's Megafunction Partnership Program may be used only +to program PLD devices (but not masked PLD devices) from Altera. Any +other use of such megafunction design, netlist, support information, +device programming or simulation file, or any other related documentation +or information is prohibited for any other purpose, including, but not +limited to modification, reverse engineering, de-compiling, or use with +any other silicon devices, unless such use is explicitly licensed under +a separate agreement with Altera or a megafunction partner. Title to the +intellectual property, including patents, copyrights, trademarks, trade +secrets, or maskworks, embodied in any such megafunction design, netlist, +support information, device programming or simulation file, or any other +related documentation or information provided by Altera or a megafunction +partner, remains with Altera, the megafunction partner, or their respective +licensors. No other licenses, including any licenses needed under any third +party's intellectual property, are provided herein. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 160 96) + (text "add32" (rect 58 2 111 21)(font "Arial" (font_size 10))) + (text "inst" (rect 8 77 31 92)(font "Arial" )) + (port + (pt 0 40) + (input) + (text "dataa[7..0]" (rect 0 0 73 16)(font "Arial" (font_size 8))) + (text "dataa[7..0]" (rect 4 24 66 40)(font "Arial" (font_size 8))) + (line (pt 0 40)(pt 64 40)(line_width 3)) + ) + (port + (pt 0 72) + (input) + (text "datab[7..0]" (rect 0 0 73 16)(font "Arial" (font_size 8))) + (text "datab[7..0]" (rect 4 56 66 72)(font "Arial" (font_size 8))) + (line (pt 0 72)(pt 64 72)(line_width 3)) + ) + (port + (pt 160 56) + (output) + (text "result[7..0]" (rect 0 0 73 16)(font "Arial" (font_size 8))) + (text "result[7..0]" (rect 95 40 157 56)(font "Arial" (font_size 8))) + (line (pt 160 56)(pt 96 56)(line_width 3)) + ) + (drawing + (text "A" (rect 66 32 75 48)(font "Arial" (font_size 8))) + (text "B" (rect 66 64 75 80)(font "Arial" (font_size 8))) + (text "A+B" (rect 68 48 94 64)(font "Arial" (font_size 8))) + (line (pt 64 32)(pt 96 40)(line_width 1)) + (line (pt 96 40)(pt 96 72)(line_width 1)) + (line (pt 96 72)(pt 64 80)(line_width 1)) + (line (pt 64 80)(pt 64 32)(line_width 1)) + ) +) diff --git a/usrp/fpga/megacells/add32.cmp b/usrp/fpga/megacells/add32.cmp new file mode 100755 index 00000000..3b120176 --- /dev/null +++ b/usrp/fpga/megacells/add32.cmp @@ -0,0 +1,29 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +component add32 + PORT + ( + dataa : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + datab : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + result : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) + ); +end component; diff --git a/usrp/fpga/megacells/add32.inc b/usrp/fpga/megacells/add32.inc new file mode 100755 index 00000000..67552571 --- /dev/null +++ b/usrp/fpga/megacells/add32.inc @@ -0,0 +1,30 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +FUNCTION add32 +( + dataa[7..0], + datab[7..0] +) + +RETURNS ( + result[7..0] +); diff --git a/usrp/fpga/megacells/add32.v b/usrp/fpga/megacells/add32.v new file mode 100755 index 00000000..d8090617 --- /dev/null +++ b/usrp/fpga/megacells/add32.v @@ -0,0 +1,221 @@ +// megafunction wizard: %LPM_ADD_SUB%CBX% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: lpm_add_sub + +// ============================================================ +// File Name: add32.v +// Megafunction Name(s): +// lpm_add_sub +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +//lpm_add_sub DEVICE_FAMILY=Cyclone LPM_DIRECTION=ADD LPM_WIDTH=8 dataa datab result +//VERSION_BEGIN 3.0 cbx_lpm_add_sub 2003:04:10:18:28:42:SJ cbx_mgl 2003:06:11:11:00:44:SJ cbx_stratix 2003:05:16:10:26:50:SJ VERSION_END + +//synthesis_resources = lut 8 +module add32_add_sub_nq7 + ( + dataa, + datab, + result) /* synthesis synthesis_clearbox=1 */; + input [7:0] dataa; + input [7:0] datab; + output [7:0] result; + + wire [7:0] wire_add_sub_cella_combout; + wire [0:0] wire_add_sub_cella_0cout; + wire [0:0] wire_add_sub_cella_1cout; + wire [0:0] wire_add_sub_cella_2cout; + wire [0:0] wire_add_sub_cella_3cout; + wire [0:0] wire_add_sub_cella_4cout; + wire [0:0] wire_add_sub_cella_5cout; + wire [0:0] wire_add_sub_cella_6cout; + wire [7:0] wire_add_sub_cella_dataa; + wire [7:0] wire_add_sub_cella_datab; + + stratix_lcell add_sub_cella_0 + ( + .cin(1'b0), + .combout(wire_add_sub_cella_combout[0:0]), + .cout(wire_add_sub_cella_0cout[0:0]), + .dataa(wire_add_sub_cella_dataa[0:0]), + .datab(wire_add_sub_cella_datab[0:0])); + defparam + add_sub_cella_0.cin_used = "true", + add_sub_cella_0.lut_mask = "96e8", + add_sub_cella_0.operation_mode = "arithmetic", + add_sub_cella_0.sum_lutc_input = "cin", + add_sub_cella_0.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_1 + ( + .cin(wire_add_sub_cella_0cout[0:0]), + .combout(wire_add_sub_cella_combout[1:1]), + .cout(wire_add_sub_cella_1cout[0:0]), + .dataa(wire_add_sub_cella_dataa[1:1]), + .datab(wire_add_sub_cella_datab[1:1])); + defparam + add_sub_cella_1.cin_used = "true", + add_sub_cella_1.lut_mask = "96e8", + add_sub_cella_1.operation_mode = "arithmetic", + add_sub_cella_1.sum_lutc_input = "cin", + add_sub_cella_1.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_2 + ( + .cin(wire_add_sub_cella_1cout[0:0]), + .combout(wire_add_sub_cella_combout[2:2]), + .cout(wire_add_sub_cella_2cout[0:0]), + .dataa(wire_add_sub_cella_dataa[2:2]), + .datab(wire_add_sub_cella_datab[2:2])); + defparam + add_sub_cella_2.cin_used = "true", + add_sub_cella_2.lut_mask = "96e8", + add_sub_cella_2.operation_mode = "arithmetic", + add_sub_cella_2.sum_lutc_input = "cin", + add_sub_cella_2.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_3 + ( + .cin(wire_add_sub_cella_2cout[0:0]), + .combout(wire_add_sub_cella_combout[3:3]), + .cout(wire_add_sub_cella_3cout[0:0]), + .dataa(wire_add_sub_cella_dataa[3:3]), + .datab(wire_add_sub_cella_datab[3:3])); + defparam + add_sub_cella_3.cin_used = "true", + add_sub_cella_3.lut_mask = "96e8", + add_sub_cella_3.operation_mode = "arithmetic", + add_sub_cella_3.sum_lutc_input = "cin", + add_sub_cella_3.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_4 + ( + .cin(wire_add_sub_cella_3cout[0:0]), + .combout(wire_add_sub_cella_combout[4:4]), + .cout(wire_add_sub_cella_4cout[0:0]), + .dataa(wire_add_sub_cella_dataa[4:4]), + .datab(wire_add_sub_cella_datab[4:4])); + defparam + add_sub_cella_4.cin_used = "true", + add_sub_cella_4.lut_mask = "96e8", + add_sub_cella_4.operation_mode = "arithmetic", + add_sub_cella_4.sum_lutc_input = "cin", + add_sub_cella_4.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_5 + ( + .cin(wire_add_sub_cella_4cout[0:0]), + .combout(wire_add_sub_cella_combout[5:5]), + .cout(wire_add_sub_cella_5cout[0:0]), + .dataa(wire_add_sub_cella_dataa[5:5]), + .datab(wire_add_sub_cella_datab[5:5])); + defparam + add_sub_cella_5.cin_used = "true", + add_sub_cella_5.lut_mask = "96e8", + add_sub_cella_5.operation_mode = "arithmetic", + add_sub_cella_5.sum_lutc_input = "cin", + add_sub_cella_5.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_6 + ( + .cin(wire_add_sub_cella_5cout[0:0]), + .combout(wire_add_sub_cella_combout[6:6]), + .cout(wire_add_sub_cella_6cout[0:0]), + .dataa(wire_add_sub_cella_dataa[6:6]), + .datab(wire_add_sub_cella_datab[6:6])); + defparam + add_sub_cella_6.cin_used = "true", + add_sub_cella_6.lut_mask = "96e8", + add_sub_cella_6.operation_mode = "arithmetic", + add_sub_cella_6.sum_lutc_input = "cin", + add_sub_cella_6.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_7 + ( + .cin(wire_add_sub_cella_6cout[0:0]), + .combout(wire_add_sub_cella_combout[7:7]), + .dataa(wire_add_sub_cella_dataa[7:7]), + .datab(wire_add_sub_cella_datab[7:7])); + defparam + add_sub_cella_7.cin_used = "true", + add_sub_cella_7.lut_mask = "9696", + add_sub_cella_7.operation_mode = "normal", + add_sub_cella_7.sum_lutc_input = "cin", + add_sub_cella_7.lpm_type = "stratix_lcell"; + assign + wire_add_sub_cella_dataa = dataa, + wire_add_sub_cella_datab = datab; + assign + result = wire_add_sub_cella_combout; +endmodule //add32_add_sub_nq7 +//VALID FILE + + +module add32 ( + dataa, + datab, + result)/* synthesis synthesis_clearbox = 1 */; + + input [7:0] dataa; + input [7:0] datab; + output [7:0] result; + + wire [7:0] sub_wire0; + wire [7:0] result = sub_wire0[7:0]; + + add32_add_sub_nq7 add32_add_sub_nq7_component ( + .dataa (dataa), + .datab (datab), + .result (sub_wire0)); + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: nBit NUMERIC "8" +// Retrieval info: PRIVATE: Function NUMERIC "0" +// Retrieval info: PRIVATE: WhichConstant NUMERIC "0" +// Retrieval info: PRIVATE: ConstantA NUMERIC "0" +// Retrieval info: PRIVATE: ConstantB NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtA NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtB NUMERIC "0" +// Retrieval info: PRIVATE: CarryIn NUMERIC "0" +// Retrieval info: PRIVATE: CarryOut NUMERIC "0" +// Retrieval info: PRIVATE: Overflow NUMERIC "0" +// Retrieval info: PRIVATE: Latency NUMERIC "0" +// Retrieval info: PRIVATE: aclr NUMERIC "0" +// Retrieval info: PRIVATE: clken NUMERIC "0" +// Retrieval info: PRIVATE: LPM_PIPELINE NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8" +// Retrieval info: CONSTANT: LPM_DIRECTION STRING "ADD" +// Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_ADD_SUB" +// Retrieval info: CONSTANT: LPM_HINT STRING "ONE_INPUT_IS_CONSTANT=NO" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: result 0 0 8 0 OUTPUT NODEFVAL result[7..0] +// Retrieval info: USED_PORT: dataa 0 0 8 0 INPUT NODEFVAL dataa[7..0] +// Retrieval info: USED_PORT: datab 0 0 8 0 INPUT NODEFVAL datab[7..0] +// Retrieval info: CONNECT: result 0 0 8 0 @result 0 0 8 0 +// Retrieval info: CONNECT: @dataa 0 0 8 0 dataa 0 0 8 0 +// Retrieval info: CONNECT: @datab 0 0 8 0 datab 0 0 8 0 +// Retrieval info: LIBRARY: lpm lpm.lpm_components.all diff --git a/usrp/fpga/megacells/add32_bb.v b/usrp/fpga/megacells/add32_bb.v new file mode 100755 index 00000000..8d1588cc --- /dev/null +++ b/usrp/fpga/megacells/add32_bb.v @@ -0,0 +1,31 @@ +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module add32 ( + dataa, + datab, + result)/* synthesis synthesis_clearbox = 1 */; + + input [7:0] dataa; + input [7:0] datab; + output [7:0] result; + +endmodule + diff --git a/usrp/fpga/megacells/add32_inst.v b/usrp/fpga/megacells/add32_inst.v new file mode 100755 index 00000000..bc7e6d44 --- /dev/null +++ b/usrp/fpga/megacells/add32_inst.v @@ -0,0 +1,5 @@ +add32 add32_inst ( + .dataa ( dataa_sig ), + .datab ( datab_sig ), + .result ( result_sig ) + ); diff --git a/usrp/fpga/megacells/addsub16.bsf b/usrp/fpga/megacells/addsub16.bsf new file mode 100755 index 00000000..9ed6b72a --- /dev/null +++ b/usrp/fpga/megacells/addsub16.bsf @@ -0,0 +1,96 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2003 Altera Corporation +Any megafunction design, and related netlist (encrypted or decrypted), +support information, device programming or simulation file, and any other +associated documentation or information provided by Altera or a partner +under Altera's Megafunction Partnership Program may be used only +to program PLD devices (but not masked PLD devices) from Altera. Any +other use of such megafunction design, netlist, support information, +device programming or simulation file, or any other related documentation +or information is prohibited for any other purpose, including, but not +limited to modification, reverse engineering, de-compiling, or use with +any other silicon devices, unless such use is explicitly licensed under +a separate agreement with Altera or a megafunction partner. Title to the +intellectual property, including patents, copyrights, trademarks, trade +secrets, or maskworks, embodied in any such megafunction design, netlist, +support information, device programming or simulation file, or any other +related documentation or information provided by Altera or a megafunction +partner, remains with Altera, the megafunction partner, or their respective +licensors. No other licenses, including any licenses needed under any third +party's intellectual property, are provided herein. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 160 144) + (text "addsub16" (rect 45 2 128 21)(font "Arial" (font_size 10))) + (text "inst" (rect 8 125 31 140)(font "Arial" )) + (port + (pt 0 56) + (input) + (text "dataa[15..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "dataa[15..0]" (rect 4 40 73 56)(font "Arial" (font_size 8))) + (line (pt 0 56)(pt 64 56)(line_width 3)) + ) + (port + (pt 0 88) + (input) + (text "datab[15..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "datab[15..0]" (rect 4 72 73 88)(font "Arial" (font_size 8))) + (line (pt 0 88)(pt 64 88)(line_width 3)) + ) + (port + (pt 0 72) + (input) + (text "clock" (rect 0 0 36 16)(font "Arial" (font_size 8))) + (text "clock" (rect 4 56 35 72)(font "Arial" (font_size 8))) + (line (pt 0 72)(pt 64 72)(line_width 1)) + ) + (port + (pt 0 32) + (input) + (text "add_sub" (rect 0 0 57 16)(font "Arial" (font_size 8))) + (text "add_sub" (rect 4 16 53 32)(font "Arial" (font_size 8))) + (line (pt 0 32)(pt 80 32)(line_width 1)) + ) + (port + (pt 0 112) + (input) + (text "clken" (rect 0 0 36 16)(font "Arial" (font_size 8))) + (text "clken" (rect 4 96 35 112)(font "Arial" (font_size 8))) + (line (pt 0 112)(pt 74 112)(line_width 1)) + ) + (port + (pt 0 128) + (input) + (text "aclr" (rect 0 0 24 16)(font "Arial" (font_size 8))) + (text "aclr" (rect 4 112 25 128)(font "Arial" (font_size 8))) + (line (pt 0 128)(pt 85 128)(line_width 1)) + ) + (port + (pt 160 72) + (output) + (text "result[15..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "result[15..0]" (rect 88 56 157 72)(font "Arial" (font_size 8))) + (line (pt 160 72)(pt 96 72)(line_width 3)) + ) + (drawing + (text "A" (rect 66 48 75 64)(font "Arial" (font_size 8))) + (text "B" (rect 66 80 75 96)(font "Arial" (font_size 8))) + (text "A+B/A-B" (rect 82 37 134 53)(font "Arial" (font_size 8))) + (line (pt 64 48)(pt 96 56)(line_width 1)) + (line (pt 96 56)(pt 96 88)(line_width 1)) + (line (pt 96 88)(pt 64 96)(line_width 1)) + (line (pt 64 96)(pt 64 48)(line_width 1)) + (line (pt 80 32)(pt 80 52)(line_width 1)) + (line (pt 106 40)(pt 125 40)(line_width 1)) + (line (pt 74 112)(pt 74 93)(line_width 1)) + (line (pt 85 128)(pt 85 90)(line_width 1)) + (line (pt 64 66)(pt 70 72)(line_width 1)) + (line (pt 70 72)(pt 64 78)(line_width 1)) + ) +) diff --git a/usrp/fpga/megacells/addsub16.cmp b/usrp/fpga/megacells/addsub16.cmp new file mode 100755 index 00000000..e32e01b3 --- /dev/null +++ b/usrp/fpga/megacells/addsub16.cmp @@ -0,0 +1,33 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +component addsub16 + PORT + ( + add_sub : IN STD_LOGIC ; + dataa : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + datab : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + clock : IN STD_LOGIC ; + aclr : IN STD_LOGIC ; + clken : IN STD_LOGIC ; + result : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) + ); +end component; diff --git a/usrp/fpga/megacells/addsub16.inc b/usrp/fpga/megacells/addsub16.inc new file mode 100755 index 00000000..846f301d --- /dev/null +++ b/usrp/fpga/megacells/addsub16.inc @@ -0,0 +1,34 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +FUNCTION addsub16 +( + add_sub, + dataa[15..0], + datab[15..0], + clock, + aclr, + clken +) + +RETURNS ( + result[15..0] +); diff --git a/usrp/fpga/megacells/addsub16.v b/usrp/fpga/megacells/addsub16.v new file mode 100755 index 00000000..431af3e4 --- /dev/null +++ b/usrp/fpga/megacells/addsub16.v @@ -0,0 +1,438 @@ +// megafunction wizard: %LPM_ADD_SUB%CBX% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: lpm_add_sub + +// ============================================================ +// File Name: addsub16.v +// Megafunction Name(s): +// lpm_add_sub +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +//lpm_add_sub DEVICE_FAMILY=Cyclone LPM_PIPELINE=1 LPM_WIDTH=16 aclr add_sub clken clock dataa datab result +//VERSION_BEGIN 3.0 cbx_lpm_add_sub 2003:04:10:18:28:42:SJ cbx_mgl 2003:06:11:11:00:44:SJ cbx_stratix 2003:05:16:10:26:50:SJ VERSION_END + +//synthesis_resources = lut 17 +module addsub16_add_sub_gp9 + ( + aclr, + add_sub, + clken, + clock, + dataa, + datab, + result) /* synthesis synthesis_clearbox=1 */; + input aclr; + input add_sub; + input clken; + input clock; + input [15:0] dataa; + input [15:0] datab; + output [15:0] result; + + wire [0:0] wire_add_sub_cella_0cout; + wire [0:0] wire_add_sub_cella_1cout; + wire [0:0] wire_add_sub_cella_2cout; + wire [0:0] wire_add_sub_cella_3cout; + wire [0:0] wire_add_sub_cella_4cout; + wire [0:0] wire_add_sub_cella_5cout; + wire [0:0] wire_add_sub_cella_6cout; + wire [0:0] wire_add_sub_cella_7cout; + wire [0:0] wire_add_sub_cella_8cout; + wire [0:0] wire_add_sub_cella_9cout; + wire [0:0] wire_add_sub_cella_10cout; + wire [0:0] wire_add_sub_cella_11cout; + wire [0:0] wire_add_sub_cella_12cout; + wire [0:0] wire_add_sub_cella_13cout; + wire [0:0] wire_add_sub_cella_14cout; + wire [15:0] wire_add_sub_cella_dataa; + wire [15:0] wire_add_sub_cella_datab; + wire [15:0] wire_add_sub_cella_regout; + wire wire_strx_lcell1_cout; + + stratix_lcell add_sub_cella_0 + ( + .aclr(aclr), + .cin(wire_strx_lcell1_cout), + .clk(clock), + .cout(wire_add_sub_cella_0cout[0:0]), + .dataa(wire_add_sub_cella_dataa[0:0]), + .datab(wire_add_sub_cella_datab[0:0]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[0:0])); + defparam + add_sub_cella_0.cin_used = "true", + add_sub_cella_0.lut_mask = "96e8", + add_sub_cella_0.operation_mode = "arithmetic", + add_sub_cella_0.sum_lutc_input = "cin", + add_sub_cella_0.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_1 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_0cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_1cout[0:0]), + .dataa(wire_add_sub_cella_dataa[1:1]), + .datab(wire_add_sub_cella_datab[1:1]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[1:1])); + defparam + add_sub_cella_1.cin_used = "true", + add_sub_cella_1.lut_mask = "96e8", + add_sub_cella_1.operation_mode = "arithmetic", + add_sub_cella_1.sum_lutc_input = "cin", + add_sub_cella_1.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_2 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_1cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_2cout[0:0]), + .dataa(wire_add_sub_cella_dataa[2:2]), + .datab(wire_add_sub_cella_datab[2:2]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[2:2])); + defparam + add_sub_cella_2.cin_used = "true", + add_sub_cella_2.lut_mask = "96e8", + add_sub_cella_2.operation_mode = "arithmetic", + add_sub_cella_2.sum_lutc_input = "cin", + add_sub_cella_2.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_3 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_2cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_3cout[0:0]), + .dataa(wire_add_sub_cella_dataa[3:3]), + .datab(wire_add_sub_cella_datab[3:3]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[3:3])); + defparam + add_sub_cella_3.cin_used = "true", + add_sub_cella_3.lut_mask = "96e8", + add_sub_cella_3.operation_mode = "arithmetic", + add_sub_cella_3.sum_lutc_input = "cin", + add_sub_cella_3.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_4 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_3cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_4cout[0:0]), + .dataa(wire_add_sub_cella_dataa[4:4]), + .datab(wire_add_sub_cella_datab[4:4]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[4:4])); + defparam + add_sub_cella_4.cin_used = "true", + add_sub_cella_4.lut_mask = "96e8", + add_sub_cella_4.operation_mode = "arithmetic", + add_sub_cella_4.sum_lutc_input = "cin", + add_sub_cella_4.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_5 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_4cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_5cout[0:0]), + .dataa(wire_add_sub_cella_dataa[5:5]), + .datab(wire_add_sub_cella_datab[5:5]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[5:5])); + defparam + add_sub_cella_5.cin_used = "true", + add_sub_cella_5.lut_mask = "96e8", + add_sub_cella_5.operation_mode = "arithmetic", + add_sub_cella_5.sum_lutc_input = "cin", + add_sub_cella_5.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_6 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_5cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_6cout[0:0]), + .dataa(wire_add_sub_cella_dataa[6:6]), + .datab(wire_add_sub_cella_datab[6:6]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[6:6])); + defparam + add_sub_cella_6.cin_used = "true", + add_sub_cella_6.lut_mask = "96e8", + add_sub_cella_6.operation_mode = "arithmetic", + add_sub_cella_6.sum_lutc_input = "cin", + add_sub_cella_6.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_7 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_6cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_7cout[0:0]), + .dataa(wire_add_sub_cella_dataa[7:7]), + .datab(wire_add_sub_cella_datab[7:7]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[7:7])); + defparam + add_sub_cella_7.cin_used = "true", + add_sub_cella_7.lut_mask = "96e8", + add_sub_cella_7.operation_mode = "arithmetic", + add_sub_cella_7.sum_lutc_input = "cin", + add_sub_cella_7.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_8 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_7cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_8cout[0:0]), + .dataa(wire_add_sub_cella_dataa[8:8]), + .datab(wire_add_sub_cella_datab[8:8]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[8:8])); + defparam + add_sub_cella_8.cin_used = "true", + add_sub_cella_8.lut_mask = "96e8", + add_sub_cella_8.operation_mode = "arithmetic", + add_sub_cella_8.sum_lutc_input = "cin", + add_sub_cella_8.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_9 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_8cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_9cout[0:0]), + .dataa(wire_add_sub_cella_dataa[9:9]), + .datab(wire_add_sub_cella_datab[9:9]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[9:9])); + defparam + add_sub_cella_9.cin_used = "true", + add_sub_cella_9.lut_mask = "96e8", + add_sub_cella_9.operation_mode = "arithmetic", + add_sub_cella_9.sum_lutc_input = "cin", + add_sub_cella_9.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_10 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_9cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_10cout[0:0]), + .dataa(wire_add_sub_cella_dataa[10:10]), + .datab(wire_add_sub_cella_datab[10:10]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[10:10])); + defparam + add_sub_cella_10.cin_used = "true", + add_sub_cella_10.lut_mask = "96e8", + add_sub_cella_10.operation_mode = "arithmetic", + add_sub_cella_10.sum_lutc_input = "cin", + add_sub_cella_10.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_11 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_10cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_11cout[0:0]), + .dataa(wire_add_sub_cella_dataa[11:11]), + .datab(wire_add_sub_cella_datab[11:11]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[11:11])); + defparam + add_sub_cella_11.cin_used = "true", + add_sub_cella_11.lut_mask = "96e8", + add_sub_cella_11.operation_mode = "arithmetic", + add_sub_cella_11.sum_lutc_input = "cin", + add_sub_cella_11.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_12 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_11cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_12cout[0:0]), + .dataa(wire_add_sub_cella_dataa[12:12]), + .datab(wire_add_sub_cella_datab[12:12]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[12:12])); + defparam + add_sub_cella_12.cin_used = "true", + add_sub_cella_12.lut_mask = "96e8", + add_sub_cella_12.operation_mode = "arithmetic", + add_sub_cella_12.sum_lutc_input = "cin", + add_sub_cella_12.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_13 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_12cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_13cout[0:0]), + .dataa(wire_add_sub_cella_dataa[13:13]), + .datab(wire_add_sub_cella_datab[13:13]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[13:13])); + defparam + add_sub_cella_13.cin_used = "true", + add_sub_cella_13.lut_mask = "96e8", + add_sub_cella_13.operation_mode = "arithmetic", + add_sub_cella_13.sum_lutc_input = "cin", + add_sub_cella_13.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_14 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_13cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_14cout[0:0]), + .dataa(wire_add_sub_cella_dataa[14:14]), + .datab(wire_add_sub_cella_datab[14:14]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[14:14])); + defparam + add_sub_cella_14.cin_used = "true", + add_sub_cella_14.lut_mask = "96e8", + add_sub_cella_14.operation_mode = "arithmetic", + add_sub_cella_14.sum_lutc_input = "cin", + add_sub_cella_14.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_15 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_14cout[0:0]), + .clk(clock), + .dataa(wire_add_sub_cella_dataa[15:15]), + .datab(wire_add_sub_cella_datab[15:15]), + .ena(clken), + .inverta((~ add_sub)), + .regout(wire_add_sub_cella_regout[15:15])); + defparam + add_sub_cella_15.cin_used = "true", + add_sub_cella_15.lut_mask = "9696", + add_sub_cella_15.operation_mode = "normal", + add_sub_cella_15.sum_lutc_input = "cin", + add_sub_cella_15.lpm_type = "stratix_lcell"; + assign + wire_add_sub_cella_dataa = datab, + wire_add_sub_cella_datab = dataa; + stratix_lcell strx_lcell1 + ( + .cout(wire_strx_lcell1_cout), + .dataa(1'b0), + .datab((~ add_sub)), + .inverta((~ add_sub))); + defparam + strx_lcell1.cin_used = "false", + strx_lcell1.lut_mask = "00cc", + strx_lcell1.operation_mode = "arithmetic", + strx_lcell1.lpm_type = "stratix_lcell"; + assign + result = wire_add_sub_cella_regout; +endmodule //addsub16_add_sub_gp9 +//VALID FILE + + +module addsub16 ( + add_sub, + dataa, + datab, + clock, + aclr, + clken, + result)/* synthesis synthesis_clearbox = 1 */; + + input add_sub; + input [15:0] dataa; + input [15:0] datab; + input clock; + input aclr; + input clken; + output [15:0] result; + + wire [15:0] sub_wire0; + wire [15:0] result = sub_wire0[15:0]; + + addsub16_add_sub_gp9 addsub16_add_sub_gp9_component ( + .dataa (dataa), + .add_sub (add_sub), + .datab (datab), + .clken (clken), + .aclr (aclr), + .clock (clock), + .result (sub_wire0)); + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: nBit NUMERIC "16" +// Retrieval info: PRIVATE: Function NUMERIC "2" +// Retrieval info: PRIVATE: WhichConstant NUMERIC "0" +// Retrieval info: PRIVATE: ConstantA NUMERIC "0" +// Retrieval info: PRIVATE: ConstantB NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtA NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtB NUMERIC "0" +// Retrieval info: PRIVATE: CarryIn NUMERIC "0" +// Retrieval info: PRIVATE: CarryOut NUMERIC "0" +// Retrieval info: PRIVATE: Overflow NUMERIC "0" +// Retrieval info: PRIVATE: Latency NUMERIC "1" +// Retrieval info: PRIVATE: aclr NUMERIC "1" +// Retrieval info: PRIVATE: clken NUMERIC "1" +// Retrieval info: PRIVATE: LPM_PIPELINE NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_DIRECTION STRING "UNUSED" +// Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_ADD_SUB" +// Retrieval info: CONSTANT: LPM_HINT STRING "ONE_INPUT_IS_CONSTANT=NO" +// Retrieval info: CONSTANT: LPM_PIPELINE NUMERIC "1" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: add_sub 0 0 0 0 INPUT NODEFVAL add_sub +// Retrieval info: USED_PORT: result 0 0 16 0 OUTPUT NODEFVAL result[15..0] +// Retrieval info: USED_PORT: dataa 0 0 16 0 INPUT NODEFVAL dataa[15..0] +// Retrieval info: USED_PORT: datab 0 0 16 0 INPUT NODEFVAL datab[15..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr +// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT NODEFVAL clken +// Retrieval info: CONNECT: @add_sub 0 0 0 0 add_sub 0 0 0 0 +// Retrieval info: CONNECT: result 0 0 16 0 @result 0 0 16 0 +// Retrieval info: CONNECT: @dataa 0 0 16 0 dataa 0 0 16 0 +// Retrieval info: CONNECT: @datab 0 0 16 0 datab 0 0 16 0 +// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: CONNECT: @clken 0 0 0 0 clken 0 0 0 0 +// Retrieval info: LIBRARY: lpm lpm.lpm_components.all diff --git a/usrp/fpga/megacells/addsub16_bb.v b/usrp/fpga/megacells/addsub16_bb.v new file mode 100755 index 00000000..8e1e7c69 --- /dev/null +++ b/usrp/fpga/megacells/addsub16_bb.v @@ -0,0 +1,39 @@ +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module addsub16 ( + add_sub, + dataa, + datab, + clock, + aclr, + clken, + result)/* synthesis synthesis_clearbox = 1 */; + + input add_sub; + input [15:0] dataa; + input [15:0] datab; + input clock; + input aclr; + input clken; + output [15:0] result; + +endmodule + diff --git a/usrp/fpga/megacells/addsub16_inst.v b/usrp/fpga/megacells/addsub16_inst.v new file mode 100755 index 00000000..4a81ff2e --- /dev/null +++ b/usrp/fpga/megacells/addsub16_inst.v @@ -0,0 +1,9 @@ +addsub16 addsub16_inst ( + .add_sub ( add_sub_sig ), + .dataa ( dataa_sig ), + .datab ( datab_sig ), + .clock ( clock_sig ), + .aclr ( aclr_sig ), + .clken ( clken_sig ), + .result ( result_sig ) + ); diff --git a/usrp/fpga/megacells/bustri.bsf b/usrp/fpga/megacells/bustri.bsf new file mode 100755 index 00000000..f1bc3ca7 --- /dev/null +++ b/usrp/fpga/megacells/bustri.bsf @@ -0,0 +1,62 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2003 Altera Corporation +Any megafunction design, and related netlist (encrypted or decrypted), +support information, device programming or simulation file, and any other +associated documentation or information provided by Altera or a partner +under Altera's Megafunction Partnership Program may be used only +to program PLD devices (but not masked PLD devices) from Altera. Any +other use of such megafunction design, netlist, support information, +device programming or simulation file, or any other related documentation +or information is prohibited for any other purpose, including, but not +limited to modification, reverse engineering, de-compiling, or use with +any other silicon devices, unless such use is explicitly licensed under +a separate agreement with Altera or a megafunction partner. Title to the +intellectual property, including patents, copyrights, trademarks, trade +secrets, or maskworks, embodied in any such megafunction design, netlist, +support information, device programming or simulation file, or any other +related documentation or information provided by Altera or a megafunction +partner, remains with Altera, the megafunction partner, or their respective +licensors. No other licenses, including any licenses needed under any third +party's intellectual property, are provided herein. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 80 40) + (text "bustri" (rect 24 1 61 17)(font "Arial" (font_size 10))) + (text "inst" (rect 8 24 25 36)(font "Arial" )) + (port + (pt 40 40) + (input) + (text "enabledt" (rect 0 0 48 14)(font "Arial" (font_size 8))) + (text "enabledt" (rect 40 -6 53 36)(font "Arial" (font_size 8))(invisible)) + (line (pt 40 40)(pt 40 28)(line_width 1)) + ) + (port + (pt 0 24) + (input) + (text "data[15..0]" (rect 0 0 60 14)(font "Arial" (font_size 8))) + (text "data[15..0]" (rect -3 -27 10 24)(font "Arial" (font_size 8))(invisible)) + (line (pt 0 24)(pt 32 24)(line_width 3)) + ) + (port + (pt 80 24) + (bidir) + (text "tridata[15..0]" (rect 0 0 70 14)(font "Arial" (font_size 8))) + (text "tridata[15..0]" (rect 84 -36 97 24)(font "Arial" (font_size 8))(invisible)) + (line (pt 80 24)(pt 48 24)(line_width 3)) + ) + (drawing + (text "16" (rect 61 25 71 37)(font "Arial" )) + (text "16" (rect 13 25 23 37)(font "Arial" )) + (line (pt 32 16)(pt 48 24)(line_width 1)) + (line (pt 48 24)(pt 32 32)(line_width 1)) + (line (pt 32 32)(pt 32 16)(line_width 1)) + (line (pt 56 28)(pt 64 20)(line_width 1)) + (line (pt 8 28)(pt 16 20)(line_width 1)) + ) +) diff --git a/usrp/fpga/megacells/bustri.cmp b/usrp/fpga/megacells/bustri.cmp new file mode 100755 index 00000000..87599ca6 --- /dev/null +++ b/usrp/fpga/megacells/bustri.cmp @@ -0,0 +1,29 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +component bustri + PORT + ( + data : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + enabledt : IN STD_LOGIC ; + tridata : INOUT STD_LOGIC_VECTOR (15 DOWNTO 0) + ); +end component; diff --git a/usrp/fpga/megacells/bustri.inc b/usrp/fpga/megacells/bustri.inc new file mode 100755 index 00000000..39995038 --- /dev/null +++ b/usrp/fpga/megacells/bustri.inc @@ -0,0 +1,30 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +FUNCTION bustri +( + data[15..0], + enabledt +) + +RETURNS ( + tridata[15..0] +); diff --git a/usrp/fpga/megacells/bustri.v b/usrp/fpga/megacells/bustri.v new file mode 100755 index 00000000..e40c6947 --- /dev/null +++ b/usrp/fpga/megacells/bustri.v @@ -0,0 +1,71 @@ +// megafunction wizard: %LPM_BUSTRI% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: lpm_bustri + +// ============================================================ +// File Name: bustri.v +// Megafunction Name(s): +// lpm_bustri +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +module bustri ( + data, + enabledt, + tridata); + + input [15:0] data; + input enabledt; + inout [15:0] tridata; + + + lpm_bustri lpm_bustri_component ( + .tridata (tridata), + .enabledt (enabledt), + .data (data)); + defparam + lpm_bustri_component.lpm_width = 16, + lpm_bustri_component.lpm_type = "LPM_BUSTRI"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: nBit NUMERIC "16" +// Retrieval info: PRIVATE: BiDir NUMERIC "0" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_BUSTRI" +// Retrieval info: USED_PORT: tridata 0 0 16 0 BIDIR NODEFVAL tridata[15..0] +// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0] +// Retrieval info: USED_PORT: enabledt 0 0 0 0 INPUT NODEFVAL enabledt +// Retrieval info: CONNECT: tridata 0 0 16 0 @tridata 0 0 16 0 +// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: @enabledt 0 0 0 0 enabledt 0 0 0 0 +// Retrieval info: LIBRARY: lpm lpm.lpm_components.all diff --git a/usrp/fpga/megacells/bustri_bb.v b/usrp/fpga/megacells/bustri_bb.v new file mode 100755 index 00000000..4cbc1609 --- /dev/null +++ b/usrp/fpga/megacells/bustri_bb.v @@ -0,0 +1,31 @@ +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module bustri ( + data, + enabledt, + tridata); + + input [15:0] data; + input enabledt; + inout [15:0] tridata; + +endmodule + diff --git a/usrp/fpga/megacells/bustri_inst.v b/usrp/fpga/megacells/bustri_inst.v new file mode 100755 index 00000000..2b4e4963 --- /dev/null +++ b/usrp/fpga/megacells/bustri_inst.v @@ -0,0 +1,5 @@ +bustri bustri_inst ( + .data ( data_sig ), + .enabledt ( enabledt_sig ), + .tridata ( tridata_sig ) + ); diff --git a/usrp/fpga/megacells/clk_doubler.v b/usrp/fpga/megacells/clk_doubler.v new file mode 100644 index 00000000..b3762a96 --- /dev/null +++ b/usrp/fpga/megacells/clk_doubler.v @@ -0,0 +1,198 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: clk_doubler.v +// Megafunction Name(s): +// altpll +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 4.2 Build 156 11/29/2004 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module clk_doubler ( + inclk0, + c0); + + input inclk0; + output c0; + + wire [5:0] sub_wire0; + wire [0:0] sub_wire4 = 1'h0; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire sub_wire2 = inclk0; + wire [1:0] sub_wire3 = {sub_wire4, sub_wire2}; + + altpll altpll_component ( + .inclk (sub_wire3), + .clk (sub_wire0) + // synopsys translate_off + , + .activeclock (), + .areset (), + .clkbad (), + .clkena (), + .clkloss (), + .clkswitch (), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena (), + .fbin (), + .locked (), + .pfdena (), + .pllena (), + .scanaclr (), + .scanclk (), + .scandata (), + .scandataout (), + .scandone (), + .scanread (), + .scanwrite (), + .sclkout0 (), + .sclkout1 () + // synopsys translate_on + ); + defparam + altpll_component.clk0_duty_cycle = 50, + altpll_component.lpm_type = "altpll", + altpll_component.clk0_multiply_by = 2, + altpll_component.inclk0_input_frequency = 15625, + altpll_component.clk0_divide_by = 1, + altpll_component.pll_type = "AUTO", + altpll_component.intended_device_family = "Cyclone", + altpll_component.operation_mode = "NORMAL", + altpll_component.compensate_clock = "CLK0", + altpll_component.clk0_phase_shift = "0"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "512.000" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "64.000" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.000" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: DEV_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: LOCK_LOSS_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: DEVICE_FAMILY NUMERIC "11" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "15625" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT VCC "c0" +// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT VCC "@clk[5..0]" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT GND "inclk0" +// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT VCC "@extclk[3..0]" +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.inc FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.cmp FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.bsf FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler_inst.v FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler_bb.v TRUE FALSE diff --git a/usrp/fpga/megacells/clk_doubler_bb.v b/usrp/fpga/megacells/clk_doubler_bb.v new file mode 100644 index 00000000..48c52e79 --- /dev/null +++ b/usrp/fpga/megacells/clk_doubler_bb.v @@ -0,0 +1,143 @@ +// megafunction wizard: %ALTPLL%VBB% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: clk_doubler.v +// Megafunction Name(s): +// altpll +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 4.2 Build 156 11/29/2004 SJ Web Edition +// ************************************************************ + +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module clk_doubler ( + inclk0, + c0); + + input inclk0; + output c0; + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "512.000" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "64.000" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.000" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: DEV_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: LOCK_LOSS_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: DEVICE_FAMILY NUMERIC "11" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "15625" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT VCC "c0" +// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT VCC "@clk[5..0]" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT GND "inclk0" +// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT VCC "@extclk[3..0]" +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.inc FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.cmp FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler.bsf FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler_inst.v FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL clk_doubler_bb.v TRUE FALSE diff --git a/usrp/fpga/megacells/dspclkpll.v b/usrp/fpga/megacells/dspclkpll.v new file mode 100644 index 00000000..81e62213 --- /dev/null +++ b/usrp/fpga/megacells/dspclkpll.v @@ -0,0 +1,237 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: dspclkpll.v +// Megafunction Name(s): +// altpll +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 4.0 Build 214 3/25/2004 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module dspclkpll ( + inclk0, + c0, + c1); + + input inclk0; + output c0; + output c1; + + wire [5:0] sub_wire0; + wire [0:0] sub_wire5 = 1'h0; + wire [1:1] sub_wire2 = sub_wire0[1:1]; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire c1 = sub_wire2; + wire sub_wire3 = inclk0; + wire [1:0] sub_wire4 = {sub_wire5, sub_wire3}; + + altpll altpll_component ( + .inclk (sub_wire4), + .clk (sub_wire0) + // synopsys translate_off +, + .fbin (), + .pllena (), + .clkswitch (), + .areset (), + .pfdena (), + .clkena (), + .extclkena (), + .scanclk (), + .scanaclr (), + .scandata (), + .scanread (), + .scanwrite (), + .extclk (), + .clkbad (), + .activeclock (), + .locked (), + .clkloss (), + .scandataout (), + .scandone (), + .sclkout1 (), + .sclkout0 (), + .enable0 (), + .enable1 () + // synopsys translate_on + +); + defparam + altpll_component.clk1_divide_by = 1, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk0_duty_cycle = 50, + altpll_component.lpm_type = "altpll", + altpll_component.clk0_multiply_by = 1, + altpll_component.inclk0_input_frequency = 15625, + altpll_component.clk0_divide_by = 1, + altpll_component.clk1_duty_cycle = 50, + altpll_component.pll_type = "AUTO", + altpll_component.clk1_multiply_by = 2, + altpll_component.clk0_time_delay = "0", + altpll_component.intended_device_family = "Cyclone", + altpll_component.operation_mode = "NORMAL", + altpll_component.compensate_clock = "CLK0", + altpll_component.clk1_time_delay = "0", + altpll_component.clk0_phase_shift = "0"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "2" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: TIME_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: TIME_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_0 STRING "inclk;fbin;pllena;clkswitch;areset" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_1 STRING "pfdena;clkena;extclkena;scanclk;scanaclr" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_2 STRING "scandata;scanread;scanwrite;clk;extclk" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "512.000" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_3 STRING "clkbad;activeclock;locked;clkloss;scandataout" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "64.000" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_4 STRING "scandone;sclkout1;sclkout0;enable0;enable1" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.000" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: DEV_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.000" +// Retrieval info: PRIVATE: LOCK_LOSS_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: DEVICE_FAMILY NUMERIC "11" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "1" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "15625" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2" +// Retrieval info: CONSTANT: CLK0_TIME_DELAY STRING "0" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: CLK1_TIME_DELAY STRING "0" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT VCC "c0" +// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT VCC "@clk[5..0]" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT GND "inclk0" +// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT VCC "@extclk[3..0]" +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL dspclkpll.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dspclkpll.inc FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dspclkpll.cmp FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dspclkpll.bsf FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dspclkpll_inst.v FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL dspclkpll_bb.v TRUE FALSE diff --git a/usrp/fpga/megacells/dspclkpll_bb.v b/usrp/fpga/megacells/dspclkpll_bb.v new file mode 100644 index 00000000..489be7bd --- /dev/null +++ b/usrp/fpga/megacells/dspclkpll_bb.v @@ -0,0 +1,31 @@ +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module dspclkpll ( + inclk0, + c0, + c1); + + input inclk0; + output c0; + output c1; + +endmodule + diff --git a/usrp/fpga/megacells/fifo_2k.v b/usrp/fpga/megacells/fifo_2k.v new file mode 100644 index 00000000..5e2a3852 --- /dev/null +++ b/usrp/fpga/megacells/fifo_2k.v @@ -0,0 +1,3343 @@ +// megafunction wizard: %FIFO%CBX% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: dcfifo + +// ============================================================ +// File Name: fifo_2k.v +// Megafunction Name(s): +// dcfifo +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 5.0 Build 168 06/22/2005 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2005 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +//dcfifo ADD_RAM_OUTPUT_REGISTER="OFF" CLOCKS_ARE_SYNCHRONIZED="FALSE" DEVICE_FAMILY="Cyclone" LPM_NUMWORDS=2048 LPM_SHOWAHEAD="ON" LPM_WIDTH=16 LPM_WIDTHU=11 OVERFLOW_CHECKING="OFF" UNDERFLOW_CHECKING="OFF" USE_EAB="ON" aclr data q rdclk rdempty rdreq rdusedw wrclk wrfull wrreq wrusedw +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_altdpram 2004:11:30:11:29:56:SJ cbx_altsyncram 2005:03:24:13:58:56:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_dcfifo 2005:03:07:17:11:14:SJ cbx_fifo_common 2004:12:13:14:26:24:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_lpm_counter 2005:02:02:04:37:10:SJ cbx_lpm_decode 2004:12:13:14:19:12:SJ cbx_lpm_mux 2004:12:13:14:16:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_scfifo 2005:03:10:10:52:20:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + + +//a_gray2bin device_family="Cyclone" WIDTH=11 bin gray +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_mgl 2005:05:19:13:51:58:SJ VERSION_END + +//synthesis_resources = +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_a_gray2bin_8m4 + ( + bin, + gray) /* synthesis synthesis_clearbox=1 */; + output [10:0] bin; + input [10:0] gray; + + wire xor0; + wire xor1; + wire xor2; + wire xor3; + wire xor4; + wire xor5; + wire xor6; + wire xor7; + wire xor8; + wire xor9; + + assign + bin = {gray[10], xor9, xor8, xor7, xor6, xor5, xor4, xor3, xor2, xor1, xor0}, + xor0 = (gray[0] ^ xor1), + xor1 = (gray[1] ^ xor2), + xor2 = (gray[2] ^ xor3), + xor3 = (gray[3] ^ xor4), + xor4 = (gray[4] ^ xor5), + xor5 = (gray[5] ^ xor6), + xor6 = (gray[6] ^ xor7), + xor7 = (gray[7] ^ xor8), + xor8 = (gray[8] ^ xor9), + xor9 = (gray[10] ^ gray[9]); +endmodule //fifo_2k_a_gray2bin_8m4 + + +//a_graycounter DEVICE_FAMILY="Cyclone" WIDTH=11 aclr clock cnt_en q +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 12 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_a_graycounter_726 + ( + aclr, + clock, + cnt_en, + q) /* synthesis synthesis_clearbox=1 */; + input aclr; + input clock; + input cnt_en; + output [10:0] q; + + wire [0:0] wire_countera_0cout; + wire [0:0] wire_countera_1cout; + wire [0:0] wire_countera_2cout; + wire [0:0] wire_countera_3cout; + wire [0:0] wire_countera_4cout; + wire [0:0] wire_countera_5cout; + wire [0:0] wire_countera_6cout; + wire [0:0] wire_countera_7cout; + wire [0:0] wire_countera_8cout; + wire [0:0] wire_countera_9cout; + wire [10:0] wire_countera_regout; + wire wire_parity_cout; + wire wire_parity_regout; + wire [10:0] power_modified_counter_values; + wire sclr; + wire updown; + + cyclone_lcell countera_0 + ( + .aclr(aclr), + .cin(wire_parity_cout), + .clk(clock), + .combout(), + .cout(wire_countera_0cout[0:0]), + .dataa(cnt_en), + .datab(wire_countera_regout[0:0]), + .ena(1'b1), + .regout(wire_countera_regout[0:0]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_0.cin_used = "true", + countera_0.lut_mask = "c6a0", + countera_0.operation_mode = "arithmetic", + countera_0.sum_lutc_input = "cin", + countera_0.synch_mode = "on", + countera_0.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_1 + ( + .aclr(aclr), + .cin(wire_countera_0cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_1cout[0:0]), + .dataa(power_modified_counter_values[0]), + .datab(power_modified_counter_values[1]), + .ena(1'b1), + .regout(wire_countera_regout[1:1]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_1.cin_used = "true", + countera_1.lut_mask = "6c50", + countera_1.operation_mode = "arithmetic", + countera_1.sum_lutc_input = "cin", + countera_1.synch_mode = "on", + countera_1.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_2 + ( + .aclr(aclr), + .cin(wire_countera_1cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_2cout[0:0]), + .dataa(power_modified_counter_values[1]), + .datab(power_modified_counter_values[2]), + .ena(1'b1), + .regout(wire_countera_regout[2:2]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_2.cin_used = "true", + countera_2.lut_mask = "6c50", + countera_2.operation_mode = "arithmetic", + countera_2.sum_lutc_input = "cin", + countera_2.synch_mode = "on", + countera_2.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_3 + ( + .aclr(aclr), + .cin(wire_countera_2cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_3cout[0:0]), + .dataa(power_modified_counter_values[2]), + .datab(power_modified_counter_values[3]), + .ena(1'b1), + .regout(wire_countera_regout[3:3]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_3.cin_used = "true", + countera_3.lut_mask = "6c50", + countera_3.operation_mode = "arithmetic", + countera_3.sum_lutc_input = "cin", + countera_3.synch_mode = "on", + countera_3.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_4 + ( + .aclr(aclr), + .cin(wire_countera_3cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_4cout[0:0]), + .dataa(power_modified_counter_values[3]), + .datab(power_modified_counter_values[4]), + .ena(1'b1), + .regout(wire_countera_regout[4:4]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_4.cin_used = "true", + countera_4.lut_mask = "6c50", + countera_4.operation_mode = "arithmetic", + countera_4.sum_lutc_input = "cin", + countera_4.synch_mode = "on", + countera_4.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_5 + ( + .aclr(aclr), + .cin(wire_countera_4cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_5cout[0:0]), + .dataa(power_modified_counter_values[4]), + .datab(power_modified_counter_values[5]), + .ena(1'b1), + .regout(wire_countera_regout[5:5]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_5.cin_used = "true", + countera_5.lut_mask = "6c50", + countera_5.operation_mode = "arithmetic", + countera_5.sum_lutc_input = "cin", + countera_5.synch_mode = "on", + countera_5.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_6 + ( + .aclr(aclr), + .cin(wire_countera_5cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_6cout[0:0]), + .dataa(power_modified_counter_values[5]), + .datab(power_modified_counter_values[6]), + .ena(1'b1), + .regout(wire_countera_regout[6:6]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_6.cin_used = "true", + countera_6.lut_mask = "6c50", + countera_6.operation_mode = "arithmetic", + countera_6.sum_lutc_input = "cin", + countera_6.synch_mode = "on", + countera_6.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_7 + ( + .aclr(aclr), + .cin(wire_countera_6cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_7cout[0:0]), + .dataa(power_modified_counter_values[6]), + .datab(power_modified_counter_values[7]), + .ena(1'b1), + .regout(wire_countera_regout[7:7]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_7.cin_used = "true", + countera_7.lut_mask = "6c50", + countera_7.operation_mode = "arithmetic", + countera_7.sum_lutc_input = "cin", + countera_7.synch_mode = "on", + countera_7.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_8 + ( + .aclr(aclr), + .cin(wire_countera_7cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_8cout[0:0]), + .dataa(power_modified_counter_values[7]), + .datab(power_modified_counter_values[8]), + .ena(1'b1), + .regout(wire_countera_regout[8:8]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_8.cin_used = "true", + countera_8.lut_mask = "6c50", + countera_8.operation_mode = "arithmetic", + countera_8.sum_lutc_input = "cin", + countera_8.synch_mode = "on", + countera_8.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_9 + ( + .aclr(aclr), + .cin(wire_countera_8cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_9cout[0:0]), + .dataa(power_modified_counter_values[8]), + .datab(power_modified_counter_values[9]), + .ena(1'b1), + .regout(wire_countera_regout[9:9]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_9.cin_used = "true", + countera_9.lut_mask = "6c50", + countera_9.operation_mode = "arithmetic", + countera_9.sum_lutc_input = "cin", + countera_9.synch_mode = "on", + countera_9.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_10 + ( + .aclr(aclr), + .cin(wire_countera_9cout[0:0]), + .clk(clock), + .combout(), + .cout(), + .dataa(power_modified_counter_values[10]), + .ena(1'b1), + .regout(wire_countera_regout[10:10]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datab(1'b1), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_10.cin_used = "true", + countera_10.lut_mask = "5a5a", + countera_10.operation_mode = "normal", + countera_10.sum_lutc_input = "cin", + countera_10.synch_mode = "on", + countera_10.lpm_type = "cyclone_lcell"; + cyclone_lcell parity + ( + .aclr(aclr), + .cin(updown), + .clk(clock), + .combout(), + .cout(wire_parity_cout), + .dataa(cnt_en), + .datab(wire_parity_regout), + .ena(1'b1), + .regout(wire_parity_regout), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + parity.cin_used = "true", + parity.lut_mask = "6682", + parity.operation_mode = "arithmetic", + parity.synch_mode = "on", + parity.lpm_type = "cyclone_lcell"; + assign + power_modified_counter_values = {wire_countera_regout[10:0]}, + q = power_modified_counter_values, + sclr = 1'b0, + updown = 1'b1; +endmodule //fifo_2k_a_graycounter_726 + + +//a_graycounter DEVICE_FAMILY="Cyclone" PVALUE=1 WIDTH=11 aclr clock cnt_en q +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 12 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_a_graycounter_2r6 + ( + aclr, + clock, + cnt_en, + q) /* synthesis synthesis_clearbox=1 */; + input aclr; + input clock; + input cnt_en; + output [10:0] q; + + wire [0:0] wire_countera_0cout; + wire [0:0] wire_countera_1cout; + wire [0:0] wire_countera_2cout; + wire [0:0] wire_countera_3cout; + wire [0:0] wire_countera_4cout; + wire [0:0] wire_countera_5cout; + wire [0:0] wire_countera_6cout; + wire [0:0] wire_countera_7cout; + wire [0:0] wire_countera_8cout; + wire [0:0] wire_countera_9cout; + wire [10:0] wire_countera_regout; + wire wire_parity_cout; + wire wire_parity_regout; + wire [10:0] power_modified_counter_values; + wire sclr; + wire updown; + + cyclone_lcell countera_0 + ( + .aclr(aclr), + .cin(wire_parity_cout), + .clk(clock), + .combout(), + .cout(wire_countera_0cout[0:0]), + .dataa(cnt_en), + .datab(wire_countera_regout[0:0]), + .ena(1'b1), + .regout(wire_countera_regout[0:0]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_0.cin_used = "true", + countera_0.lut_mask = "c6a0", + countera_0.operation_mode = "arithmetic", + countera_0.sum_lutc_input = "cin", + countera_0.synch_mode = "on", + countera_0.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_1 + ( + .aclr(aclr), + .cin(wire_countera_0cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_1cout[0:0]), + .dataa(power_modified_counter_values[0]), + .datab(power_modified_counter_values[1]), + .ena(1'b1), + .regout(wire_countera_regout[1:1]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_1.cin_used = "true", + countera_1.lut_mask = "6c50", + countera_1.operation_mode = "arithmetic", + countera_1.sum_lutc_input = "cin", + countera_1.synch_mode = "on", + countera_1.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_2 + ( + .aclr(aclr), + .cin(wire_countera_1cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_2cout[0:0]), + .dataa(power_modified_counter_values[1]), + .datab(power_modified_counter_values[2]), + .ena(1'b1), + .regout(wire_countera_regout[2:2]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_2.cin_used = "true", + countera_2.lut_mask = "6c50", + countera_2.operation_mode = "arithmetic", + countera_2.sum_lutc_input = "cin", + countera_2.synch_mode = "on", + countera_2.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_3 + ( + .aclr(aclr), + .cin(wire_countera_2cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_3cout[0:0]), + .dataa(power_modified_counter_values[2]), + .datab(power_modified_counter_values[3]), + .ena(1'b1), + .regout(wire_countera_regout[3:3]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_3.cin_used = "true", + countera_3.lut_mask = "6c50", + countera_3.operation_mode = "arithmetic", + countera_3.sum_lutc_input = "cin", + countera_3.synch_mode = "on", + countera_3.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_4 + ( + .aclr(aclr), + .cin(wire_countera_3cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_4cout[0:0]), + .dataa(power_modified_counter_values[3]), + .datab(power_modified_counter_values[4]), + .ena(1'b1), + .regout(wire_countera_regout[4:4]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_4.cin_used = "true", + countera_4.lut_mask = "6c50", + countera_4.operation_mode = "arithmetic", + countera_4.sum_lutc_input = "cin", + countera_4.synch_mode = "on", + countera_4.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_5 + ( + .aclr(aclr), + .cin(wire_countera_4cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_5cout[0:0]), + .dataa(power_modified_counter_values[4]), + .datab(power_modified_counter_values[5]), + .ena(1'b1), + .regout(wire_countera_regout[5:5]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_5.cin_used = "true", + countera_5.lut_mask = "6c50", + countera_5.operation_mode = "arithmetic", + countera_5.sum_lutc_input = "cin", + countera_5.synch_mode = "on", + countera_5.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_6 + ( + .aclr(aclr), + .cin(wire_countera_5cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_6cout[0:0]), + .dataa(power_modified_counter_values[5]), + .datab(power_modified_counter_values[6]), + .ena(1'b1), + .regout(wire_countera_regout[6:6]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_6.cin_used = "true", + countera_6.lut_mask = "6c50", + countera_6.operation_mode = "arithmetic", + countera_6.sum_lutc_input = "cin", + countera_6.synch_mode = "on", + countera_6.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_7 + ( + .aclr(aclr), + .cin(wire_countera_6cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_7cout[0:0]), + .dataa(power_modified_counter_values[6]), + .datab(power_modified_counter_values[7]), + .ena(1'b1), + .regout(wire_countera_regout[7:7]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_7.cin_used = "true", + countera_7.lut_mask = "6c50", + countera_7.operation_mode = "arithmetic", + countera_7.sum_lutc_input = "cin", + countera_7.synch_mode = "on", + countera_7.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_8 + ( + .aclr(aclr), + .cin(wire_countera_7cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_8cout[0:0]), + .dataa(power_modified_counter_values[7]), + .datab(power_modified_counter_values[8]), + .ena(1'b1), + .regout(wire_countera_regout[8:8]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_8.cin_used = "true", + countera_8.lut_mask = "6c50", + countera_8.operation_mode = "arithmetic", + countera_8.sum_lutc_input = "cin", + countera_8.synch_mode = "on", + countera_8.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_9 + ( + .aclr(aclr), + .cin(wire_countera_8cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_9cout[0:0]), + .dataa(power_modified_counter_values[8]), + .datab(power_modified_counter_values[9]), + .ena(1'b1), + .regout(wire_countera_regout[9:9]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_9.cin_used = "true", + countera_9.lut_mask = "6c50", + countera_9.operation_mode = "arithmetic", + countera_9.sum_lutc_input = "cin", + countera_9.synch_mode = "on", + countera_9.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_10 + ( + .aclr(aclr), + .cin(wire_countera_9cout[0:0]), + .clk(clock), + .combout(), + .cout(), + .dataa(power_modified_counter_values[10]), + .ena(1'b1), + .regout(wire_countera_regout[10:10]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datab(1'b1), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_10.cin_used = "true", + countera_10.lut_mask = "5a5a", + countera_10.operation_mode = "normal", + countera_10.sum_lutc_input = "cin", + countera_10.synch_mode = "on", + countera_10.lpm_type = "cyclone_lcell"; + cyclone_lcell parity + ( + .aclr(aclr), + .cin(updown), + .clk(clock), + .combout(), + .cout(wire_parity_cout), + .dataa(cnt_en), + .datab((~ wire_parity_regout)), + .ena(1'b1), + .regout(wire_parity_regout), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + parity.cin_used = "true", + parity.lut_mask = "9982", + parity.operation_mode = "arithmetic", + parity.synch_mode = "on", + parity.lpm_type = "cyclone_lcell"; + assign + power_modified_counter_values = {wire_countera_regout[10:1], (~ wire_countera_regout[0])}, + q = power_modified_counter_values, + sclr = 1'b0, + updown = 1'b1; +endmodule //fifo_2k_a_graycounter_2r6 + + +//altsyncram ADDRESS_REG_B="CLOCK1" DEVICE_FAMILY="Cyclone" OPERATION_MODE="DUAL_PORT" OUTDATA_REG_B="UNREGISTERED" WIDTH_A=16 WIDTH_B=16 WIDTH_BYTEENA_A=1 WIDTHAD_A=11 WIDTHAD_B=11 address_a address_b clock0 clock1 clocken1 data_a q_b wren_a +//VERSION_BEGIN 5.0 cbx_altsyncram 2005:03:24:13:58:56:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_lpm_decode 2004:12:13:14:19:12:SJ cbx_lpm_mux 2004:12:13:14:16:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + +//synthesis_resources = M4K 8 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_altsyncram_6pl + ( + address_a, + address_b, + clock0, + clock1, + clocken1, + data_a, + q_b, + wren_a) /* synthesis synthesis_clearbox=1 */; + input [10:0] address_a; + input [10:0] address_b; + input clock0; + input clock1; + input clocken1; + input [15:0] data_a; + output [15:0] q_b; + input wren_a; + + wire [0:0] wire_ram_block3a_0portbdataout; + wire [0:0] wire_ram_block3a_1portbdataout; + wire [0:0] wire_ram_block3a_2portbdataout; + wire [0:0] wire_ram_block3a_3portbdataout; + wire [0:0] wire_ram_block3a_4portbdataout; + wire [0:0] wire_ram_block3a_5portbdataout; + wire [0:0] wire_ram_block3a_6portbdataout; + wire [0:0] wire_ram_block3a_7portbdataout; + wire [0:0] wire_ram_block3a_8portbdataout; + wire [0:0] wire_ram_block3a_9portbdataout; + wire [0:0] wire_ram_block3a_10portbdataout; + wire [0:0] wire_ram_block3a_11portbdataout; + wire [0:0] wire_ram_block3a_12portbdataout; + wire [0:0] wire_ram_block3a_13portbdataout; + wire [0:0] wire_ram_block3a_14portbdataout; + wire [0:0] wire_ram_block3a_15portbdataout; + wire [10:0] address_a_wire; + wire [10:0] address_b_wire; + + cyclone_ram_block ram_block3a_0 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[0]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_0portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_0.connectivity_checking = "OFF", + ram_block3a_0.logical_ram_name = "ALTSYNCRAM", + ram_block3a_0.mixed_port_feed_through_mode = "dont_care", + ram_block3a_0.operation_mode = "dual_port", + ram_block3a_0.port_a_address_width = 11, + ram_block3a_0.port_a_data_width = 1, + ram_block3a_0.port_a_first_address = 0, + ram_block3a_0.port_a_first_bit_number = 0, + ram_block3a_0.port_a_last_address = 2047, + ram_block3a_0.port_a_logical_ram_depth = 2048, + ram_block3a_0.port_a_logical_ram_width = 16, + ram_block3a_0.port_b_address_clear = "none", + ram_block3a_0.port_b_address_clock = "clock1", + ram_block3a_0.port_b_address_width = 11, + ram_block3a_0.port_b_data_out_clear = "none", + ram_block3a_0.port_b_data_out_clock = "none", + ram_block3a_0.port_b_data_width = 1, + ram_block3a_0.port_b_first_address = 0, + ram_block3a_0.port_b_first_bit_number = 0, + ram_block3a_0.port_b_last_address = 2047, + ram_block3a_0.port_b_logical_ram_depth = 2048, + ram_block3a_0.port_b_logical_ram_width = 16, + ram_block3a_0.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_0.ram_block_type = "auto", + ram_block3a_0.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_1 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[1]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_1portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_1.connectivity_checking = "OFF", + ram_block3a_1.logical_ram_name = "ALTSYNCRAM", + ram_block3a_1.mixed_port_feed_through_mode = "dont_care", + ram_block3a_1.operation_mode = "dual_port", + ram_block3a_1.port_a_address_width = 11, + ram_block3a_1.port_a_data_width = 1, + ram_block3a_1.port_a_first_address = 0, + ram_block3a_1.port_a_first_bit_number = 1, + ram_block3a_1.port_a_last_address = 2047, + ram_block3a_1.port_a_logical_ram_depth = 2048, + ram_block3a_1.port_a_logical_ram_width = 16, + ram_block3a_1.port_b_address_clear = "none", + ram_block3a_1.port_b_address_clock = "clock1", + ram_block3a_1.port_b_address_width = 11, + ram_block3a_1.port_b_data_out_clear = "none", + ram_block3a_1.port_b_data_out_clock = "none", + ram_block3a_1.port_b_data_width = 1, + ram_block3a_1.port_b_first_address = 0, + ram_block3a_1.port_b_first_bit_number = 1, + ram_block3a_1.port_b_last_address = 2047, + ram_block3a_1.port_b_logical_ram_depth = 2048, + ram_block3a_1.port_b_logical_ram_width = 16, + ram_block3a_1.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_1.ram_block_type = "auto", + ram_block3a_1.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_2 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[2]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_2portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_2.connectivity_checking = "OFF", + ram_block3a_2.logical_ram_name = "ALTSYNCRAM", + ram_block3a_2.mixed_port_feed_through_mode = "dont_care", + ram_block3a_2.operation_mode = "dual_port", + ram_block3a_2.port_a_address_width = 11, + ram_block3a_2.port_a_data_width = 1, + ram_block3a_2.port_a_first_address = 0, + ram_block3a_2.port_a_first_bit_number = 2, + ram_block3a_2.port_a_last_address = 2047, + ram_block3a_2.port_a_logical_ram_depth = 2048, + ram_block3a_2.port_a_logical_ram_width = 16, + ram_block3a_2.port_b_address_clear = "none", + ram_block3a_2.port_b_address_clock = "clock1", + ram_block3a_2.port_b_address_width = 11, + ram_block3a_2.port_b_data_out_clear = "none", + ram_block3a_2.port_b_data_out_clock = "none", + ram_block3a_2.port_b_data_width = 1, + ram_block3a_2.port_b_first_address = 0, + ram_block3a_2.port_b_first_bit_number = 2, + ram_block3a_2.port_b_last_address = 2047, + ram_block3a_2.port_b_logical_ram_depth = 2048, + ram_block3a_2.port_b_logical_ram_width = 16, + ram_block3a_2.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_2.ram_block_type = "auto", + ram_block3a_2.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_3 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[3]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_3portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_3.connectivity_checking = "OFF", + ram_block3a_3.logical_ram_name = "ALTSYNCRAM", + ram_block3a_3.mixed_port_feed_through_mode = "dont_care", + ram_block3a_3.operation_mode = "dual_port", + ram_block3a_3.port_a_address_width = 11, + ram_block3a_3.port_a_data_width = 1, + ram_block3a_3.port_a_first_address = 0, + ram_block3a_3.port_a_first_bit_number = 3, + ram_block3a_3.port_a_last_address = 2047, + ram_block3a_3.port_a_logical_ram_depth = 2048, + ram_block3a_3.port_a_logical_ram_width = 16, + ram_block3a_3.port_b_address_clear = "none", + ram_block3a_3.port_b_address_clock = "clock1", + ram_block3a_3.port_b_address_width = 11, + ram_block3a_3.port_b_data_out_clear = "none", + ram_block3a_3.port_b_data_out_clock = "none", + ram_block3a_3.port_b_data_width = 1, + ram_block3a_3.port_b_first_address = 0, + ram_block3a_3.port_b_first_bit_number = 3, + ram_block3a_3.port_b_last_address = 2047, + ram_block3a_3.port_b_logical_ram_depth = 2048, + ram_block3a_3.port_b_logical_ram_width = 16, + ram_block3a_3.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_3.ram_block_type = "auto", + ram_block3a_3.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_4 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[4]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_4portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_4.connectivity_checking = "OFF", + ram_block3a_4.logical_ram_name = "ALTSYNCRAM", + ram_block3a_4.mixed_port_feed_through_mode = "dont_care", + ram_block3a_4.operation_mode = "dual_port", + ram_block3a_4.port_a_address_width = 11, + ram_block3a_4.port_a_data_width = 1, + ram_block3a_4.port_a_first_address = 0, + ram_block3a_4.port_a_first_bit_number = 4, + ram_block3a_4.port_a_last_address = 2047, + ram_block3a_4.port_a_logical_ram_depth = 2048, + ram_block3a_4.port_a_logical_ram_width = 16, + ram_block3a_4.port_b_address_clear = "none", + ram_block3a_4.port_b_address_clock = "clock1", + ram_block3a_4.port_b_address_width = 11, + ram_block3a_4.port_b_data_out_clear = "none", + ram_block3a_4.port_b_data_out_clock = "none", + ram_block3a_4.port_b_data_width = 1, + ram_block3a_4.port_b_first_address = 0, + ram_block3a_4.port_b_first_bit_number = 4, + ram_block3a_4.port_b_last_address = 2047, + ram_block3a_4.port_b_logical_ram_depth = 2048, + ram_block3a_4.port_b_logical_ram_width = 16, + ram_block3a_4.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_4.ram_block_type = "auto", + ram_block3a_4.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_5 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[5]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_5portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_5.connectivity_checking = "OFF", + ram_block3a_5.logical_ram_name = "ALTSYNCRAM", + ram_block3a_5.mixed_port_feed_through_mode = "dont_care", + ram_block3a_5.operation_mode = "dual_port", + ram_block3a_5.port_a_address_width = 11, + ram_block3a_5.port_a_data_width = 1, + ram_block3a_5.port_a_first_address = 0, + ram_block3a_5.port_a_first_bit_number = 5, + ram_block3a_5.port_a_last_address = 2047, + ram_block3a_5.port_a_logical_ram_depth = 2048, + ram_block3a_5.port_a_logical_ram_width = 16, + ram_block3a_5.port_b_address_clear = "none", + ram_block3a_5.port_b_address_clock = "clock1", + ram_block3a_5.port_b_address_width = 11, + ram_block3a_5.port_b_data_out_clear = "none", + ram_block3a_5.port_b_data_out_clock = "none", + ram_block3a_5.port_b_data_width = 1, + ram_block3a_5.port_b_first_address = 0, + ram_block3a_5.port_b_first_bit_number = 5, + ram_block3a_5.port_b_last_address = 2047, + ram_block3a_5.port_b_logical_ram_depth = 2048, + ram_block3a_5.port_b_logical_ram_width = 16, + ram_block3a_5.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_5.ram_block_type = "auto", + ram_block3a_5.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_6 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[6]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_6portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_6.connectivity_checking = "OFF", + ram_block3a_6.logical_ram_name = "ALTSYNCRAM", + ram_block3a_6.mixed_port_feed_through_mode = "dont_care", + ram_block3a_6.operation_mode = "dual_port", + ram_block3a_6.port_a_address_width = 11, + ram_block3a_6.port_a_data_width = 1, + ram_block3a_6.port_a_first_address = 0, + ram_block3a_6.port_a_first_bit_number = 6, + ram_block3a_6.port_a_last_address = 2047, + ram_block3a_6.port_a_logical_ram_depth = 2048, + ram_block3a_6.port_a_logical_ram_width = 16, + ram_block3a_6.port_b_address_clear = "none", + ram_block3a_6.port_b_address_clock = "clock1", + ram_block3a_6.port_b_address_width = 11, + ram_block3a_6.port_b_data_out_clear = "none", + ram_block3a_6.port_b_data_out_clock = "none", + ram_block3a_6.port_b_data_width = 1, + ram_block3a_6.port_b_first_address = 0, + ram_block3a_6.port_b_first_bit_number = 6, + ram_block3a_6.port_b_last_address = 2047, + ram_block3a_6.port_b_logical_ram_depth = 2048, + ram_block3a_6.port_b_logical_ram_width = 16, + ram_block3a_6.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_6.ram_block_type = "auto", + ram_block3a_6.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_7 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[7]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_7portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_7.connectivity_checking = "OFF", + ram_block3a_7.logical_ram_name = "ALTSYNCRAM", + ram_block3a_7.mixed_port_feed_through_mode = "dont_care", + ram_block3a_7.operation_mode = "dual_port", + ram_block3a_7.port_a_address_width = 11, + ram_block3a_7.port_a_data_width = 1, + ram_block3a_7.port_a_first_address = 0, + ram_block3a_7.port_a_first_bit_number = 7, + ram_block3a_7.port_a_last_address = 2047, + ram_block3a_7.port_a_logical_ram_depth = 2048, + ram_block3a_7.port_a_logical_ram_width = 16, + ram_block3a_7.port_b_address_clear = "none", + ram_block3a_7.port_b_address_clock = "clock1", + ram_block3a_7.port_b_address_width = 11, + ram_block3a_7.port_b_data_out_clear = "none", + ram_block3a_7.port_b_data_out_clock = "none", + ram_block3a_7.port_b_data_width = 1, + ram_block3a_7.port_b_first_address = 0, + ram_block3a_7.port_b_first_bit_number = 7, + ram_block3a_7.port_b_last_address = 2047, + ram_block3a_7.port_b_logical_ram_depth = 2048, + ram_block3a_7.port_b_logical_ram_width = 16, + ram_block3a_7.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_7.ram_block_type = "auto", + ram_block3a_7.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_8 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[8]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_8portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_8.connectivity_checking = "OFF", + ram_block3a_8.logical_ram_name = "ALTSYNCRAM", + ram_block3a_8.mixed_port_feed_through_mode = "dont_care", + ram_block3a_8.operation_mode = "dual_port", + ram_block3a_8.port_a_address_width = 11, + ram_block3a_8.port_a_data_width = 1, + ram_block3a_8.port_a_first_address = 0, + ram_block3a_8.port_a_first_bit_number = 8, + ram_block3a_8.port_a_last_address = 2047, + ram_block3a_8.port_a_logical_ram_depth = 2048, + ram_block3a_8.port_a_logical_ram_width = 16, + ram_block3a_8.port_b_address_clear = "none", + ram_block3a_8.port_b_address_clock = "clock1", + ram_block3a_8.port_b_address_width = 11, + ram_block3a_8.port_b_data_out_clear = "none", + ram_block3a_8.port_b_data_out_clock = "none", + ram_block3a_8.port_b_data_width = 1, + ram_block3a_8.port_b_first_address = 0, + ram_block3a_8.port_b_first_bit_number = 8, + ram_block3a_8.port_b_last_address = 2047, + ram_block3a_8.port_b_logical_ram_depth = 2048, + ram_block3a_8.port_b_logical_ram_width = 16, + ram_block3a_8.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_8.ram_block_type = "auto", + ram_block3a_8.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_9 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[9]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_9portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_9.connectivity_checking = "OFF", + ram_block3a_9.logical_ram_name = "ALTSYNCRAM", + ram_block3a_9.mixed_port_feed_through_mode = "dont_care", + ram_block3a_9.operation_mode = "dual_port", + ram_block3a_9.port_a_address_width = 11, + ram_block3a_9.port_a_data_width = 1, + ram_block3a_9.port_a_first_address = 0, + ram_block3a_9.port_a_first_bit_number = 9, + ram_block3a_9.port_a_last_address = 2047, + ram_block3a_9.port_a_logical_ram_depth = 2048, + ram_block3a_9.port_a_logical_ram_width = 16, + ram_block3a_9.port_b_address_clear = "none", + ram_block3a_9.port_b_address_clock = "clock1", + ram_block3a_9.port_b_address_width = 11, + ram_block3a_9.port_b_data_out_clear = "none", + ram_block3a_9.port_b_data_out_clock = "none", + ram_block3a_9.port_b_data_width = 1, + ram_block3a_9.port_b_first_address = 0, + ram_block3a_9.port_b_first_bit_number = 9, + ram_block3a_9.port_b_last_address = 2047, + ram_block3a_9.port_b_logical_ram_depth = 2048, + ram_block3a_9.port_b_logical_ram_width = 16, + ram_block3a_9.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_9.ram_block_type = "auto", + ram_block3a_9.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_10 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[10]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_10portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_10.connectivity_checking = "OFF", + ram_block3a_10.logical_ram_name = "ALTSYNCRAM", + ram_block3a_10.mixed_port_feed_through_mode = "dont_care", + ram_block3a_10.operation_mode = "dual_port", + ram_block3a_10.port_a_address_width = 11, + ram_block3a_10.port_a_data_width = 1, + ram_block3a_10.port_a_first_address = 0, + ram_block3a_10.port_a_first_bit_number = 10, + ram_block3a_10.port_a_last_address = 2047, + ram_block3a_10.port_a_logical_ram_depth = 2048, + ram_block3a_10.port_a_logical_ram_width = 16, + ram_block3a_10.port_b_address_clear = "none", + ram_block3a_10.port_b_address_clock = "clock1", + ram_block3a_10.port_b_address_width = 11, + ram_block3a_10.port_b_data_out_clear = "none", + ram_block3a_10.port_b_data_out_clock = "none", + ram_block3a_10.port_b_data_width = 1, + ram_block3a_10.port_b_first_address = 0, + ram_block3a_10.port_b_first_bit_number = 10, + ram_block3a_10.port_b_last_address = 2047, + ram_block3a_10.port_b_logical_ram_depth = 2048, + ram_block3a_10.port_b_logical_ram_width = 16, + ram_block3a_10.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_10.ram_block_type = "auto", + ram_block3a_10.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_11 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[11]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_11portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_11.connectivity_checking = "OFF", + ram_block3a_11.logical_ram_name = "ALTSYNCRAM", + ram_block3a_11.mixed_port_feed_through_mode = "dont_care", + ram_block3a_11.operation_mode = "dual_port", + ram_block3a_11.port_a_address_width = 11, + ram_block3a_11.port_a_data_width = 1, + ram_block3a_11.port_a_first_address = 0, + ram_block3a_11.port_a_first_bit_number = 11, + ram_block3a_11.port_a_last_address = 2047, + ram_block3a_11.port_a_logical_ram_depth = 2048, + ram_block3a_11.port_a_logical_ram_width = 16, + ram_block3a_11.port_b_address_clear = "none", + ram_block3a_11.port_b_address_clock = "clock1", + ram_block3a_11.port_b_address_width = 11, + ram_block3a_11.port_b_data_out_clear = "none", + ram_block3a_11.port_b_data_out_clock = "none", + ram_block3a_11.port_b_data_width = 1, + ram_block3a_11.port_b_first_address = 0, + ram_block3a_11.port_b_first_bit_number = 11, + ram_block3a_11.port_b_last_address = 2047, + ram_block3a_11.port_b_logical_ram_depth = 2048, + ram_block3a_11.port_b_logical_ram_width = 16, + ram_block3a_11.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_11.ram_block_type = "auto", + ram_block3a_11.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_12 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[12]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_12portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_12.connectivity_checking = "OFF", + ram_block3a_12.logical_ram_name = "ALTSYNCRAM", + ram_block3a_12.mixed_port_feed_through_mode = "dont_care", + ram_block3a_12.operation_mode = "dual_port", + ram_block3a_12.port_a_address_width = 11, + ram_block3a_12.port_a_data_width = 1, + ram_block3a_12.port_a_first_address = 0, + ram_block3a_12.port_a_first_bit_number = 12, + ram_block3a_12.port_a_last_address = 2047, + ram_block3a_12.port_a_logical_ram_depth = 2048, + ram_block3a_12.port_a_logical_ram_width = 16, + ram_block3a_12.port_b_address_clear = "none", + ram_block3a_12.port_b_address_clock = "clock1", + ram_block3a_12.port_b_address_width = 11, + ram_block3a_12.port_b_data_out_clear = "none", + ram_block3a_12.port_b_data_out_clock = "none", + ram_block3a_12.port_b_data_width = 1, + ram_block3a_12.port_b_first_address = 0, + ram_block3a_12.port_b_first_bit_number = 12, + ram_block3a_12.port_b_last_address = 2047, + ram_block3a_12.port_b_logical_ram_depth = 2048, + ram_block3a_12.port_b_logical_ram_width = 16, + ram_block3a_12.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_12.ram_block_type = "auto", + ram_block3a_12.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_13 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[13]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_13portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_13.connectivity_checking = "OFF", + ram_block3a_13.logical_ram_name = "ALTSYNCRAM", + ram_block3a_13.mixed_port_feed_through_mode = "dont_care", + ram_block3a_13.operation_mode = "dual_port", + ram_block3a_13.port_a_address_width = 11, + ram_block3a_13.port_a_data_width = 1, + ram_block3a_13.port_a_first_address = 0, + ram_block3a_13.port_a_first_bit_number = 13, + ram_block3a_13.port_a_last_address = 2047, + ram_block3a_13.port_a_logical_ram_depth = 2048, + ram_block3a_13.port_a_logical_ram_width = 16, + ram_block3a_13.port_b_address_clear = "none", + ram_block3a_13.port_b_address_clock = "clock1", + ram_block3a_13.port_b_address_width = 11, + ram_block3a_13.port_b_data_out_clear = "none", + ram_block3a_13.port_b_data_out_clock = "none", + ram_block3a_13.port_b_data_width = 1, + ram_block3a_13.port_b_first_address = 0, + ram_block3a_13.port_b_first_bit_number = 13, + ram_block3a_13.port_b_last_address = 2047, + ram_block3a_13.port_b_logical_ram_depth = 2048, + ram_block3a_13.port_b_logical_ram_width = 16, + ram_block3a_13.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_13.ram_block_type = "auto", + ram_block3a_13.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_14 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[14]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_14portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_14.connectivity_checking = "OFF", + ram_block3a_14.logical_ram_name = "ALTSYNCRAM", + ram_block3a_14.mixed_port_feed_through_mode = "dont_care", + ram_block3a_14.operation_mode = "dual_port", + ram_block3a_14.port_a_address_width = 11, + ram_block3a_14.port_a_data_width = 1, + ram_block3a_14.port_a_first_address = 0, + ram_block3a_14.port_a_first_bit_number = 14, + ram_block3a_14.port_a_last_address = 2047, + ram_block3a_14.port_a_logical_ram_depth = 2048, + ram_block3a_14.port_a_logical_ram_width = 16, + ram_block3a_14.port_b_address_clear = "none", + ram_block3a_14.port_b_address_clock = "clock1", + ram_block3a_14.port_b_address_width = 11, + ram_block3a_14.port_b_data_out_clear = "none", + ram_block3a_14.port_b_data_out_clock = "none", + ram_block3a_14.port_b_data_width = 1, + ram_block3a_14.port_b_first_address = 0, + ram_block3a_14.port_b_first_bit_number = 14, + ram_block3a_14.port_b_last_address = 2047, + ram_block3a_14.port_b_logical_ram_depth = 2048, + ram_block3a_14.port_b_logical_ram_width = 16, + ram_block3a_14.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_14.ram_block_type = "auto", + ram_block3a_14.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_15 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[10:0]}), + .portadatain({data_a[15]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[10:0]}), + .portbdataout(wire_ram_block3a_15portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_15.connectivity_checking = "OFF", + ram_block3a_15.logical_ram_name = "ALTSYNCRAM", + ram_block3a_15.mixed_port_feed_through_mode = "dont_care", + ram_block3a_15.operation_mode = "dual_port", + ram_block3a_15.port_a_address_width = 11, + ram_block3a_15.port_a_data_width = 1, + ram_block3a_15.port_a_first_address = 0, + ram_block3a_15.port_a_first_bit_number = 15, + ram_block3a_15.port_a_last_address = 2047, + ram_block3a_15.port_a_logical_ram_depth = 2048, + ram_block3a_15.port_a_logical_ram_width = 16, + ram_block3a_15.port_b_address_clear = "none", + ram_block3a_15.port_b_address_clock = "clock1", + ram_block3a_15.port_b_address_width = 11, + ram_block3a_15.port_b_data_out_clear = "none", + ram_block3a_15.port_b_data_out_clock = "none", + ram_block3a_15.port_b_data_width = 1, + ram_block3a_15.port_b_first_address = 0, + ram_block3a_15.port_b_first_bit_number = 15, + ram_block3a_15.port_b_last_address = 2047, + ram_block3a_15.port_b_logical_ram_depth = 2048, + ram_block3a_15.port_b_logical_ram_width = 16, + ram_block3a_15.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_15.ram_block_type = "auto", + ram_block3a_15.lpm_type = "cyclone_ram_block"; + assign + address_a_wire = address_a, + address_b_wire = address_b, + q_b = {wire_ram_block3a_15portbdataout[0], wire_ram_block3a_14portbdataout[0], wire_ram_block3a_13portbdataout[0], wire_ram_block3a_12portbdataout[0], wire_ram_block3a_11portbdataout[0], wire_ram_block3a_10portbdataout[0], wire_ram_block3a_9portbdataout[0], wire_ram_block3a_8portbdataout[0], wire_ram_block3a_7portbdataout[0], wire_ram_block3a_6portbdataout[0], wire_ram_block3a_5portbdataout[0], wire_ram_block3a_4portbdataout[0], wire_ram_block3a_3portbdataout[0], wire_ram_block3a_2portbdataout[0], wire_ram_block3a_1portbdataout[0], wire_ram_block3a_0portbdataout[0]}; +endmodule //fifo_2k_altsyncram_6pl + + +//dffpipe DELAY=1 WIDTH=11 clock clrn d q +//VERSION_BEGIN 5.0 cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + +//synthesis_resources = lut 11 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_dffpipe_ab3 + ( + clock, + clrn, + d, + q) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="AUTO_SHIFT_REGISTER_RECOGNITION=OFF" */; + input clock; + input clrn; + input [10:0] d; + output [10:0] q; + + wire [10:0] wire_dffe4a_D; + reg [10:0] dffe4a; + wire ena; + wire prn; + wire sclr; + + // synopsys translate_off + initial + dffe4a[0:0] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[0:0] <= 1'b1; + else if (clrn == 1'b0) dffe4a[0:0] <= 1'b0; + else if (ena == 1'b1) dffe4a[0:0] <= wire_dffe4a_D[0:0]; + // synopsys translate_off + initial + dffe4a[1:1] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[1:1] <= 1'b1; + else if (clrn == 1'b0) dffe4a[1:1] <= 1'b0; + else if (ena == 1'b1) dffe4a[1:1] <= wire_dffe4a_D[1:1]; + // synopsys translate_off + initial + dffe4a[2:2] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[2:2] <= 1'b1; + else if (clrn == 1'b0) dffe4a[2:2] <= 1'b0; + else if (ena == 1'b1) dffe4a[2:2] <= wire_dffe4a_D[2:2]; + // synopsys translate_off + initial + dffe4a[3:3] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[3:3] <= 1'b1; + else if (clrn == 1'b0) dffe4a[3:3] <= 1'b0; + else if (ena == 1'b1) dffe4a[3:3] <= wire_dffe4a_D[3:3]; + // synopsys translate_off + initial + dffe4a[4:4] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[4:4] <= 1'b1; + else if (clrn == 1'b0) dffe4a[4:4] <= 1'b0; + else if (ena == 1'b1) dffe4a[4:4] <= wire_dffe4a_D[4:4]; + // synopsys translate_off + initial + dffe4a[5:5] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[5:5] <= 1'b1; + else if (clrn == 1'b0) dffe4a[5:5] <= 1'b0; + else if (ena == 1'b1) dffe4a[5:5] <= wire_dffe4a_D[5:5]; + // synopsys translate_off + initial + dffe4a[6:6] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[6:6] <= 1'b1; + else if (clrn == 1'b0) dffe4a[6:6] <= 1'b0; + else if (ena == 1'b1) dffe4a[6:6] <= wire_dffe4a_D[6:6]; + // synopsys translate_off + initial + dffe4a[7:7] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[7:7] <= 1'b1; + else if (clrn == 1'b0) dffe4a[7:7] <= 1'b0; + else if (ena == 1'b1) dffe4a[7:7] <= wire_dffe4a_D[7:7]; + // synopsys translate_off + initial + dffe4a[8:8] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[8:8] <= 1'b1; + else if (clrn == 1'b0) dffe4a[8:8] <= 1'b0; + else if (ena == 1'b1) dffe4a[8:8] <= wire_dffe4a_D[8:8]; + // synopsys translate_off + initial + dffe4a[9:9] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[9:9] <= 1'b1; + else if (clrn == 1'b0) dffe4a[9:9] <= 1'b0; + else if (ena == 1'b1) dffe4a[9:9] <= wire_dffe4a_D[9:9]; + // synopsys translate_off + initial + dffe4a[10:10] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[10:10] <= 1'b1; + else if (clrn == 1'b0) dffe4a[10:10] <= 1'b0; + else if (ena == 1'b1) dffe4a[10:10] <= wire_dffe4a_D[10:10]; + assign + wire_dffe4a_D = (d & {11{(~ sclr)}}); + assign + ena = 1'b1, + prn = 1'b1, + q = dffe4a, + sclr = 1'b0; +endmodule //fifo_2k_dffpipe_ab3 + + +//dffpipe WIDTH=11 clock clrn d q +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_altdpram 2004:11:30:11:29:56:SJ cbx_altsyncram 2005:03:24:13:58:56:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_dcfifo 2005:03:07:17:11:14:SJ cbx_fifo_common 2004:12:13:14:26:24:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_lpm_counter 2005:02:02:04:37:10:SJ cbx_lpm_decode 2004:12:13:14:19:12:SJ cbx_lpm_mux 2004:12:13:14:16:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_scfifo 2005:03:10:10:52:20:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + + +//dffpipe WIDTH=11 clock clrn d q +//VERSION_BEGIN 5.0 cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + +//synthesis_resources = lut 11 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_dffpipe_dm2 + ( + clock, + clrn, + d, + q) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="AUTO_SHIFT_REGISTER_RECOGNITION=OFF" */; + input clock; + input clrn; + input [10:0] d; + output [10:0] q; + + wire [10:0] wire_dffe6a_D; + reg [10:0] dffe6a; + wire ena; + wire prn; + wire sclr; + + // synopsys translate_off + initial + dffe6a[0:0] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[0:0] <= 1'b1; + else if (clrn == 1'b0) dffe6a[0:0] <= 1'b0; + else if (ena == 1'b1) dffe6a[0:0] <= wire_dffe6a_D[0:0]; + // synopsys translate_off + initial + dffe6a[1:1] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[1:1] <= 1'b1; + else if (clrn == 1'b0) dffe6a[1:1] <= 1'b0; + else if (ena == 1'b1) dffe6a[1:1] <= wire_dffe6a_D[1:1]; + // synopsys translate_off + initial + dffe6a[2:2] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[2:2] <= 1'b1; + else if (clrn == 1'b0) dffe6a[2:2] <= 1'b0; + else if (ena == 1'b1) dffe6a[2:2] <= wire_dffe6a_D[2:2]; + // synopsys translate_off + initial + dffe6a[3:3] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[3:3] <= 1'b1; + else if (clrn == 1'b0) dffe6a[3:3] <= 1'b0; + else if (ena == 1'b1) dffe6a[3:3] <= wire_dffe6a_D[3:3]; + // synopsys translate_off + initial + dffe6a[4:4] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[4:4] <= 1'b1; + else if (clrn == 1'b0) dffe6a[4:4] <= 1'b0; + else if (ena == 1'b1) dffe6a[4:4] <= wire_dffe6a_D[4:4]; + // synopsys translate_off + initial + dffe6a[5:5] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[5:5] <= 1'b1; + else if (clrn == 1'b0) dffe6a[5:5] <= 1'b0; + else if (ena == 1'b1) dffe6a[5:5] <= wire_dffe6a_D[5:5]; + // synopsys translate_off + initial + dffe6a[6:6] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[6:6] <= 1'b1; + else if (clrn == 1'b0) dffe6a[6:6] <= 1'b0; + else if (ena == 1'b1) dffe6a[6:6] <= wire_dffe6a_D[6:6]; + // synopsys translate_off + initial + dffe6a[7:7] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[7:7] <= 1'b1; + else if (clrn == 1'b0) dffe6a[7:7] <= 1'b0; + else if (ena == 1'b1) dffe6a[7:7] <= wire_dffe6a_D[7:7]; + // synopsys translate_off + initial + dffe6a[8:8] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[8:8] <= 1'b1; + else if (clrn == 1'b0) dffe6a[8:8] <= 1'b0; + else if (ena == 1'b1) dffe6a[8:8] <= wire_dffe6a_D[8:8]; + // synopsys translate_off + initial + dffe6a[9:9] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[9:9] <= 1'b1; + else if (clrn == 1'b0) dffe6a[9:9] <= 1'b0; + else if (ena == 1'b1) dffe6a[9:9] <= wire_dffe6a_D[9:9]; + // synopsys translate_off + initial + dffe6a[10:10] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[10:10] <= 1'b1; + else if (clrn == 1'b0) dffe6a[10:10] <= 1'b0; + else if (ena == 1'b1) dffe6a[10:10] <= wire_dffe6a_D[10:10]; + assign + wire_dffe6a_D = (d & {11{(~ sclr)}}); + assign + ena = 1'b1, + prn = 1'b1, + q = dffe6a, + sclr = 1'b0; +endmodule //fifo_2k_dffpipe_dm2 + +//synthesis_resources = lut 11 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_alt_synch_pipe_dm2 + ( + clock, + clrn, + d, + q) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="X_ON_VIOLATION_OPTION=OFF" */; + input clock; + input clrn; + input [10:0] d; + output [10:0] q; + + wire [10:0] wire_dffpipe5_q; + + fifo_2k_dffpipe_dm2 dffpipe5 + ( + .clock(clock), + .clrn(clrn), + .d(d), + .q(wire_dffpipe5_q)); + assign + q = wire_dffpipe5_q; +endmodule //fifo_2k_alt_synch_pipe_dm2 + + +//lpm_add_sub DEVICE_FAMILY="Cyclone" LPM_DIRECTION="SUB" LPM_WIDTH=11 dataa datab result +//VERSION_BEGIN 5.0 cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 11 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_add_sub_a18 + ( + dataa, + datab, + result) /* synthesis synthesis_clearbox=1 */; + input [10:0] dataa; + input [10:0] datab; + output [10:0] result; + + wire [10:0] wire_add_sub_cella_combout; + wire [0:0] wire_add_sub_cella_0cout; + wire [0:0] wire_add_sub_cella_1cout; + wire [0:0] wire_add_sub_cella_2cout; + wire [0:0] wire_add_sub_cella_3cout; + wire [0:0] wire_add_sub_cella_4cout; + wire [0:0] wire_add_sub_cella_5cout; + wire [0:0] wire_add_sub_cella_6cout; + wire [0:0] wire_add_sub_cella_7cout; + wire [0:0] wire_add_sub_cella_8cout; + wire [0:0] wire_add_sub_cella_9cout; + wire [10:0] wire_add_sub_cella_dataa; + wire [10:0] wire_add_sub_cella_datab; + + cyclone_lcell add_sub_cella_0 + ( + .cin(1'b1), + .combout(wire_add_sub_cella_combout[0:0]), + .cout(wire_add_sub_cella_0cout[0:0]), + .dataa(wire_add_sub_cella_dataa[0:0]), + .datab(wire_add_sub_cella_datab[0:0]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_0.cin_used = "true", + add_sub_cella_0.lut_mask = "69b2", + add_sub_cella_0.operation_mode = "arithmetic", + add_sub_cella_0.sum_lutc_input = "cin", + add_sub_cella_0.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_1 + ( + .cin(wire_add_sub_cella_0cout[0:0]), + .combout(wire_add_sub_cella_combout[1:1]), + .cout(wire_add_sub_cella_1cout[0:0]), + .dataa(wire_add_sub_cella_dataa[1:1]), + .datab(wire_add_sub_cella_datab[1:1]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_1.cin_used = "true", + add_sub_cella_1.lut_mask = "69b2", + add_sub_cella_1.operation_mode = "arithmetic", + add_sub_cella_1.sum_lutc_input = "cin", + add_sub_cella_1.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_2 + ( + .cin(wire_add_sub_cella_1cout[0:0]), + .combout(wire_add_sub_cella_combout[2:2]), + .cout(wire_add_sub_cella_2cout[0:0]), + .dataa(wire_add_sub_cella_dataa[2:2]), + .datab(wire_add_sub_cella_datab[2:2]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_2.cin_used = "true", + add_sub_cella_2.lut_mask = "69b2", + add_sub_cella_2.operation_mode = "arithmetic", + add_sub_cella_2.sum_lutc_input = "cin", + add_sub_cella_2.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_3 + ( + .cin(wire_add_sub_cella_2cout[0:0]), + .combout(wire_add_sub_cella_combout[3:3]), + .cout(wire_add_sub_cella_3cout[0:0]), + .dataa(wire_add_sub_cella_dataa[3:3]), + .datab(wire_add_sub_cella_datab[3:3]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_3.cin_used = "true", + add_sub_cella_3.lut_mask = "69b2", + add_sub_cella_3.operation_mode = "arithmetic", + add_sub_cella_3.sum_lutc_input = "cin", + add_sub_cella_3.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_4 + ( + .cin(wire_add_sub_cella_3cout[0:0]), + .combout(wire_add_sub_cella_combout[4:4]), + .cout(wire_add_sub_cella_4cout[0:0]), + .dataa(wire_add_sub_cella_dataa[4:4]), + .datab(wire_add_sub_cella_datab[4:4]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_4.cin_used = "true", + add_sub_cella_4.lut_mask = "69b2", + add_sub_cella_4.operation_mode = "arithmetic", + add_sub_cella_4.sum_lutc_input = "cin", + add_sub_cella_4.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_5 + ( + .cin(wire_add_sub_cella_4cout[0:0]), + .combout(wire_add_sub_cella_combout[5:5]), + .cout(wire_add_sub_cella_5cout[0:0]), + .dataa(wire_add_sub_cella_dataa[5:5]), + .datab(wire_add_sub_cella_datab[5:5]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_5.cin_used = "true", + add_sub_cella_5.lut_mask = "69b2", + add_sub_cella_5.operation_mode = "arithmetic", + add_sub_cella_5.sum_lutc_input = "cin", + add_sub_cella_5.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_6 + ( + .cin(wire_add_sub_cella_5cout[0:0]), + .combout(wire_add_sub_cella_combout[6:6]), + .cout(wire_add_sub_cella_6cout[0:0]), + .dataa(wire_add_sub_cella_dataa[6:6]), + .datab(wire_add_sub_cella_datab[6:6]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_6.cin_used = "true", + add_sub_cella_6.lut_mask = "69b2", + add_sub_cella_6.operation_mode = "arithmetic", + add_sub_cella_6.sum_lutc_input = "cin", + add_sub_cella_6.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_7 + ( + .cin(wire_add_sub_cella_6cout[0:0]), + .combout(wire_add_sub_cella_combout[7:7]), + .cout(wire_add_sub_cella_7cout[0:0]), + .dataa(wire_add_sub_cella_dataa[7:7]), + .datab(wire_add_sub_cella_datab[7:7]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_7.cin_used = "true", + add_sub_cella_7.lut_mask = "69b2", + add_sub_cella_7.operation_mode = "arithmetic", + add_sub_cella_7.sum_lutc_input = "cin", + add_sub_cella_7.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_8 + ( + .cin(wire_add_sub_cella_7cout[0:0]), + .combout(wire_add_sub_cella_combout[8:8]), + .cout(wire_add_sub_cella_8cout[0:0]), + .dataa(wire_add_sub_cella_dataa[8:8]), + .datab(wire_add_sub_cella_datab[8:8]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_8.cin_used = "true", + add_sub_cella_8.lut_mask = "69b2", + add_sub_cella_8.operation_mode = "arithmetic", + add_sub_cella_8.sum_lutc_input = "cin", + add_sub_cella_8.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_9 + ( + .cin(wire_add_sub_cella_8cout[0:0]), + .combout(wire_add_sub_cella_combout[9:9]), + .cout(wire_add_sub_cella_9cout[0:0]), + .dataa(wire_add_sub_cella_dataa[9:9]), + .datab(wire_add_sub_cella_datab[9:9]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_9.cin_used = "true", + add_sub_cella_9.lut_mask = "69b2", + add_sub_cella_9.operation_mode = "arithmetic", + add_sub_cella_9.sum_lutc_input = "cin", + add_sub_cella_9.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_10 + ( + .cin(wire_add_sub_cella_9cout[0:0]), + .combout(wire_add_sub_cella_combout[10:10]), + .cout(), + .dataa(wire_add_sub_cella_dataa[10:10]), + .datab(wire_add_sub_cella_datab[10:10]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_10.cin_used = "true", + add_sub_cella_10.lut_mask = "6969", + add_sub_cella_10.operation_mode = "normal", + add_sub_cella_10.sum_lutc_input = "cin", + add_sub_cella_10.lpm_type = "cyclone_lcell"; + assign + wire_add_sub_cella_dataa = dataa, + wire_add_sub_cella_datab = datab; + assign + result = wire_add_sub_cella_combout; +endmodule //fifo_2k_add_sub_a18 + + +//lpm_compare DEVICE_FAMILY="Cyclone" LPM_WIDTH=11 aeb dataa datab +//VERSION_BEGIN 5.0 cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + + +//lpm_compare DEVICE_FAMILY="Cyclone" LPM_WIDTH=11 aeb dataa datab +//VERSION_BEGIN 5.0 cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 97 M4K 8 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_2k_dcfifo_0cq + ( + aclr, + data, + q, + rdclk, + rdempty, + rdreq, + rdusedw, + wrclk, + wrfull, + wrreq, + wrusedw) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="AUTO_SHIFT_REGISTER_RECOGNITION=OFF;{ -from \"rdptr_g|power_modified_counter_values\" -to \"ws_dgrp|dffpipe5|dffe6a\" }CUT=ON;{ -from \"delayed_wrptr_g\" -to \"rs_dgwp|dffpipe5|dffe6a\" }CUT=ON" */; + input aclr; + input [15:0] data; + output [15:0] q; + input rdclk; + output rdempty; + input rdreq; + output [10:0] rdusedw; + input wrclk; + output wrfull; + input wrreq; + output [10:0] wrusedw; + + wire [10:0] wire_rdptr_g_gray2bin_bin; + wire [10:0] wire_rs_dgwp_gray2bin_bin; + wire [10:0] wire_wrptr_g_gray2bin_bin; + wire [10:0] wire_ws_dgrp_gray2bin_bin; + wire [10:0] wire_rdptr_g_q; + wire [10:0] wire_rdptr_g1p_q; + wire [10:0] wire_wrptr_g1p_q; + wire [15:0] wire_fifo_ram_q_b; + reg [10:0] delayed_wrptr_g; + reg [10:0] wrptr_g; + wire [10:0] wire_rs_brp_q; + wire [10:0] wire_rs_bwp_q; + wire [10:0] wire_rs_dgwp_q; + wire [10:0] wire_ws_brp_q; + wire [10:0] wire_ws_bwp_q; + wire [10:0] wire_ws_dgrp_q; + wire [10:0] wire_rdusedw_sub_result; + wire [10:0] wire_wrusedw_sub_result; + reg wire_rdempty_eq_comp_aeb_int; + wire wire_rdempty_eq_comp_aeb; + wire [10:0] wire_rdempty_eq_comp_dataa; + wire [10:0] wire_rdempty_eq_comp_datab; + reg wire_wrfull_eq_comp_aeb_int; + wire wire_wrfull_eq_comp_aeb; + wire [10:0] wire_wrfull_eq_comp_dataa; + wire [10:0] wire_wrfull_eq_comp_datab; + wire int_rdempty; + wire int_wrfull; + wire valid_rdreq; + wire valid_wrreq; + + fifo_2k_a_gray2bin_8m4 rdptr_g_gray2bin + ( + .bin(wire_rdptr_g_gray2bin_bin), + .gray(wire_rdptr_g_q)); + fifo_2k_a_gray2bin_8m4 rs_dgwp_gray2bin + ( + .bin(wire_rs_dgwp_gray2bin_bin), + .gray(wire_rs_dgwp_q)); + fifo_2k_a_gray2bin_8m4 wrptr_g_gray2bin + ( + .bin(wire_wrptr_g_gray2bin_bin), + .gray(wrptr_g)); + fifo_2k_a_gray2bin_8m4 ws_dgrp_gray2bin + ( + .bin(wire_ws_dgrp_gray2bin_bin), + .gray(wire_ws_dgrp_q)); + fifo_2k_a_graycounter_726 rdptr_g + ( + .aclr(aclr), + .clock(rdclk), + .cnt_en(valid_rdreq), + .q(wire_rdptr_g_q)); + fifo_2k_a_graycounter_2r6 rdptr_g1p + ( + .aclr(aclr), + .clock(rdclk), + .cnt_en(valid_rdreq), + .q(wire_rdptr_g1p_q)); + fifo_2k_a_graycounter_2r6 wrptr_g1p + ( + .aclr(aclr), + .clock(wrclk), + .cnt_en(valid_wrreq), + .q(wire_wrptr_g1p_q)); + fifo_2k_altsyncram_6pl fifo_ram + ( + .address_a(wrptr_g), + .address_b(((wire_rdptr_g_q & {11{int_rdempty}}) | (wire_rdptr_g1p_q & {11{(~ int_rdempty)}}))), + .clock0(wrclk), + .clock1(rdclk), + .clocken1((valid_rdreq | int_rdempty)), + .data_a(data), + .q_b(wire_fifo_ram_q_b), + .wren_a(valid_wrreq)); + // synopsys translate_off + initial + delayed_wrptr_g = 0; + // synopsys translate_on + always @ ( posedge wrclk or posedge aclr) + if (aclr == 1'b1) delayed_wrptr_g <= 11'b0; + else delayed_wrptr_g <= wrptr_g; + // synopsys translate_off + initial + wrptr_g = 0; + // synopsys translate_on + always @ ( posedge wrclk or posedge aclr) + if (aclr == 1'b1) wrptr_g <= 11'b0; + else if (valid_wrreq == 1'b1) wrptr_g <= wire_wrptr_g1p_q; + fifo_2k_dffpipe_ab3 rs_brp + ( + .clock(rdclk), + .clrn((~ aclr)), + .d(wire_rdptr_g_gray2bin_bin), + .q(wire_rs_brp_q)); + fifo_2k_dffpipe_ab3 rs_bwp + ( + .clock(rdclk), + .clrn((~ aclr)), + .d(wire_rs_dgwp_gray2bin_bin), + .q(wire_rs_bwp_q)); + fifo_2k_alt_synch_pipe_dm2 rs_dgwp + ( + .clock(rdclk), + .clrn((~ aclr)), + .d(delayed_wrptr_g), + .q(wire_rs_dgwp_q)); + fifo_2k_dffpipe_ab3 ws_brp + ( + .clock(wrclk), + .clrn((~ aclr)), + .d(wire_ws_dgrp_gray2bin_bin), + .q(wire_ws_brp_q)); + fifo_2k_dffpipe_ab3 ws_bwp + ( + .clock(wrclk), + .clrn((~ aclr)), + .d(wire_wrptr_g_gray2bin_bin), + .q(wire_ws_bwp_q)); + fifo_2k_alt_synch_pipe_dm2 ws_dgrp + ( + .clock(wrclk), + .clrn((~ aclr)), + .d(wire_rdptr_g_q), + .q(wire_ws_dgrp_q)); + fifo_2k_add_sub_a18 rdusedw_sub + ( + .dataa(wire_rs_bwp_q), + .datab(wire_rs_brp_q), + .result(wire_rdusedw_sub_result)); + fifo_2k_add_sub_a18 wrusedw_sub + ( + .dataa(wire_ws_bwp_q), + .datab(wire_ws_brp_q), + .result(wire_wrusedw_sub_result)); + always @(wire_rdempty_eq_comp_dataa or wire_rdempty_eq_comp_datab) + if (wire_rdempty_eq_comp_dataa == wire_rdempty_eq_comp_datab) + begin + wire_rdempty_eq_comp_aeb_int = 1'b1; + end + else + begin + wire_rdempty_eq_comp_aeb_int = 1'b0; + end + assign + wire_rdempty_eq_comp_aeb = wire_rdempty_eq_comp_aeb_int; + assign + wire_rdempty_eq_comp_dataa = wire_rs_dgwp_q, + wire_rdempty_eq_comp_datab = wire_rdptr_g_q; + always @(wire_wrfull_eq_comp_dataa or wire_wrfull_eq_comp_datab) + if (wire_wrfull_eq_comp_dataa == wire_wrfull_eq_comp_datab) + begin + wire_wrfull_eq_comp_aeb_int = 1'b1; + end + else + begin + wire_wrfull_eq_comp_aeb_int = 1'b0; + end + assign + wire_wrfull_eq_comp_aeb = wire_wrfull_eq_comp_aeb_int; + assign + wire_wrfull_eq_comp_dataa = wire_ws_dgrp_q, + wire_wrfull_eq_comp_datab = wire_wrptr_g1p_q; + assign + int_rdempty = wire_rdempty_eq_comp_aeb, + int_wrfull = wire_wrfull_eq_comp_aeb, + q = wire_fifo_ram_q_b, + rdempty = int_rdempty, + rdusedw = wire_rdusedw_sub_result, + valid_rdreq = rdreq, + valid_wrreq = wrreq, + wrfull = int_wrfull, + wrusedw = wire_wrusedw_sub_result; +endmodule //fifo_2k_dcfifo_0cq +//VALID FILE + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module fifo_2k ( + data, + wrreq, + rdreq, + rdclk, + wrclk, + aclr, + q, + rdempty, + rdusedw, + wrfull, + wrusedw)/* synthesis synthesis_clearbox = 1 */; + + input [15:0] data; + input wrreq; + input rdreq; + input rdclk; + input wrclk; + input aclr; + output [15:0] q; + output rdempty; + output [10:0] rdusedw; + output wrfull; + output [10:0] wrusedw; + + wire sub_wire0; + wire [10:0] sub_wire1; + wire sub_wire2; + wire [15:0] sub_wire3; + wire [10:0] sub_wire4; + wire rdempty = sub_wire0; + wire [10:0] wrusedw = sub_wire1[10:0]; + wire wrfull = sub_wire2; + wire [15:0] q = sub_wire3[15:0]; + wire [10:0] rdusedw = sub_wire4[10:0]; + + fifo_2k_dcfifo_0cq fifo_2k_dcfifo_0cq_component ( + .wrclk (wrclk), + .rdreq (rdreq), + .aclr (aclr), + .rdclk (rdclk), + .wrreq (wrreq), + .data (data), + .rdempty (sub_wire0), + .wrusedw (sub_wire1), + .wrfull (sub_wire2), + .q (sub_wire3), + .rdusedw (sub_wire4)); + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: Width NUMERIC "16" +// Retrieval info: PRIVATE: Depth NUMERIC "2048" +// Retrieval info: PRIVATE: Clock NUMERIC "4" +// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" +// Retrieval info: PRIVATE: Full NUMERIC "1" +// Retrieval info: PRIVATE: Empty NUMERIC "1" +// Retrieval info: PRIVATE: UsedW NUMERIC "1" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" +// Retrieval info: PRIVATE: sc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: sc_sclr NUMERIC "0" +// Retrieval info: PRIVATE: rsFull NUMERIC "0" +// Retrieval info: PRIVATE: rsEmpty NUMERIC "1" +// Retrieval info: PRIVATE: rsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: wsFull NUMERIC "1" +// Retrieval info: PRIVATE: wsEmpty NUMERIC "0" +// Retrieval info: PRIVATE: wsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: dc_aclr NUMERIC "1" +// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" +// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" +// Retrieval info: PRIVATE: Optimize NUMERIC "2" +// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "2048" +// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE" +// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo" +// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" +// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0] +// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0] +// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq +// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq +// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk +// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk +// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty +// Retrieval info: USED_PORT: rdusedw 0 0 11 0 OUTPUT NODEFVAL rdusedw[10..0] +// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull +// Retrieval info: USED_PORT: wrusedw 0 0 11 0 OUTPUT NODEFVAL wrusedw[10..0] +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr +// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0 +// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 +// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 +// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0 +// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0 +// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0 +// Retrieval info: CONNECT: rdusedw 0 0 11 0 @rdusedw 0 0 11 0 +// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0 +// Retrieval info: CONNECT: wrusedw 0 0 11 0 @wrusedw 0 0 11 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_bb.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_waveforms.html TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_wave*.jpg FALSE diff --git a/usrp/fpga/megacells/fifo_2k_bb.v b/usrp/fpga/megacells/fifo_2k_bb.v new file mode 100644 index 00000000..3fcc2a49 --- /dev/null +++ b/usrp/fpga/megacells/fifo_2k_bb.v @@ -0,0 +1,131 @@ +// megafunction wizard: %FIFO%VBB% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: dcfifo + +// ============================================================ +// File Name: fifo_2k.v +// Megafunction Name(s): +// dcfifo +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 5.0 Build 168 06/22/2005 SP 1 SJ Web Edition +// ************************************************************ + +//Copyright (C) 1991-2005 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + +module fifo_2k ( + data, + wrreq, + rdreq, + rdclk, + wrclk, + aclr, + q, + rdempty, + rdusedw, + wrfull, + wrusedw)/* synthesis synthesis_clearbox = 1 */; + + input [15:0] data; + input wrreq; + input rdreq; + input rdclk; + input wrclk; + input aclr; + output [15:0] q; + output rdempty; + output [10:0] rdusedw; + output wrfull; + output [10:0] wrusedw; + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: Width NUMERIC "16" +// Retrieval info: PRIVATE: Depth NUMERIC "2048" +// Retrieval info: PRIVATE: Clock NUMERIC "4" +// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" +// Retrieval info: PRIVATE: Full NUMERIC "1" +// Retrieval info: PRIVATE: Empty NUMERIC "1" +// Retrieval info: PRIVATE: UsedW NUMERIC "1" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" +// Retrieval info: PRIVATE: sc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: sc_sclr NUMERIC "0" +// Retrieval info: PRIVATE: rsFull NUMERIC "0" +// Retrieval info: PRIVATE: rsEmpty NUMERIC "1" +// Retrieval info: PRIVATE: rsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: wsFull NUMERIC "1" +// Retrieval info: PRIVATE: wsEmpty NUMERIC "0" +// Retrieval info: PRIVATE: wsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: dc_aclr NUMERIC "1" +// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" +// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" +// Retrieval info: PRIVATE: Optimize NUMERIC "2" +// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "2048" +// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE" +// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo" +// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" +// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0] +// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0] +// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq +// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq +// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk +// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk +// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty +// Retrieval info: USED_PORT: rdusedw 0 0 11 0 OUTPUT NODEFVAL rdusedw[10..0] +// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull +// Retrieval info: USED_PORT: wrusedw 0 0 11 0 OUTPUT NODEFVAL wrusedw[10..0] +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr +// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0 +// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 +// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 +// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0 +// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0 +// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0 +// Retrieval info: CONNECT: rdusedw 0 0 11 0 @rdusedw 0 0 11 0 +// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0 +// Retrieval info: CONNECT: wrusedw 0 0 11 0 @wrusedw 0 0 11 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_bb.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_waveforms.html TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_wave*.jpg FALSE diff --git a/usrp/fpga/megacells/fifo_4k.v b/usrp/fpga/megacells/fifo_4k.v new file mode 100644 index 00000000..a5ab4667 --- /dev/null +++ b/usrp/fpga/megacells/fifo_4k.v @@ -0,0 +1,3495 @@ +// megafunction wizard: %FIFO%CBX% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: dcfifo + +// ============================================================ +// File Name: fifo_4k.v +// Megafunction Name(s): +// dcfifo +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 5.0 Build 168 06/22/2005 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2005 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +//dcfifo ADD_RAM_OUTPUT_REGISTER="OFF" CLOCKS_ARE_SYNCHRONIZED="FALSE" DEVICE_FAMILY="Cyclone" LPM_NUMWORDS=4096 LPM_SHOWAHEAD="ON" LPM_WIDTH=16 LPM_WIDTHU=12 OVERFLOW_CHECKING="OFF" UNDERFLOW_CHECKING="OFF" USE_EAB="ON" aclr data q rdclk rdempty rdreq rdusedw wrclk wrfull wrreq wrusedw +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_altdpram 2004:11:30:11:29:56:SJ cbx_altsyncram 2005:03:24:13:58:56:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_dcfifo 2005:03:07:17:11:14:SJ cbx_fifo_common 2004:12:13:14:26:24:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_lpm_counter 2005:02:02:04:37:10:SJ cbx_lpm_decode 2004:12:13:14:19:12:SJ cbx_lpm_mux 2004:12:13:14:16:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_scfifo 2005:03:10:10:52:20:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + + +//a_gray2bin device_family="Cyclone" WIDTH=12 bin gray +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_mgl 2005:05:19:13:51:58:SJ VERSION_END + +//synthesis_resources = +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_a_gray2bin_9m4 + ( + bin, + gray) /* synthesis synthesis_clearbox=1 */; + output [11:0] bin; + input [11:0] gray; + + wire xor0; + wire xor1; + wire xor10; + wire xor2; + wire xor3; + wire xor4; + wire xor5; + wire xor6; + wire xor7; + wire xor8; + wire xor9; + + assign + bin = {gray[11], xor10, xor9, xor8, xor7, xor6, xor5, xor4, xor3, xor2, xor1, xor0}, + xor0 = (gray[0] ^ xor1), + xor1 = (gray[1] ^ xor2), + xor10 = (gray[11] ^ gray[10]), + xor2 = (gray[2] ^ xor3), + xor3 = (gray[3] ^ xor4), + xor4 = (gray[4] ^ xor5), + xor5 = (gray[5] ^ xor6), + xor6 = (gray[6] ^ xor7), + xor7 = (gray[7] ^ xor8), + xor8 = (gray[8] ^ xor9), + xor9 = (gray[9] ^ xor10); +endmodule //fifo_4k_a_gray2bin_9m4 + + +//a_graycounter DEVICE_FAMILY="Cyclone" WIDTH=12 aclr clock cnt_en q +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 13 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_a_graycounter_826 + ( + aclr, + clock, + cnt_en, + q) /* synthesis synthesis_clearbox=1 */; + input aclr; + input clock; + input cnt_en; + output [11:0] q; + + wire [0:0] wire_countera_0cout; + wire [0:0] wire_countera_1cout; + wire [0:0] wire_countera_2cout; + wire [0:0] wire_countera_3cout; + wire [0:0] wire_countera_4cout; + wire [0:0] wire_countera_5cout; + wire [0:0] wire_countera_6cout; + wire [0:0] wire_countera_7cout; + wire [0:0] wire_countera_8cout; + wire [0:0] wire_countera_9cout; + wire [0:0] wire_countera_10cout; + wire [11:0] wire_countera_regout; + wire wire_parity_cout; + wire wire_parity_regout; + wire [11:0] power_modified_counter_values; + wire sclr; + wire updown; + + cyclone_lcell countera_0 + ( + .aclr(aclr), + .cin(wire_parity_cout), + .clk(clock), + .combout(), + .cout(wire_countera_0cout[0:0]), + .dataa(cnt_en), + .datab(wire_countera_regout[0:0]), + .ena(1'b1), + .regout(wire_countera_regout[0:0]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_0.cin_used = "true", + countera_0.lut_mask = "c6a0", + countera_0.operation_mode = "arithmetic", + countera_0.sum_lutc_input = "cin", + countera_0.synch_mode = "on", + countera_0.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_1 + ( + .aclr(aclr), + .cin(wire_countera_0cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_1cout[0:0]), + .dataa(power_modified_counter_values[0]), + .datab(power_modified_counter_values[1]), + .ena(1'b1), + .regout(wire_countera_regout[1:1]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_1.cin_used = "true", + countera_1.lut_mask = "6c50", + countera_1.operation_mode = "arithmetic", + countera_1.sum_lutc_input = "cin", + countera_1.synch_mode = "on", + countera_1.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_2 + ( + .aclr(aclr), + .cin(wire_countera_1cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_2cout[0:0]), + .dataa(power_modified_counter_values[1]), + .datab(power_modified_counter_values[2]), + .ena(1'b1), + .regout(wire_countera_regout[2:2]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_2.cin_used = "true", + countera_2.lut_mask = "6c50", + countera_2.operation_mode = "arithmetic", + countera_2.sum_lutc_input = "cin", + countera_2.synch_mode = "on", + countera_2.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_3 + ( + .aclr(aclr), + .cin(wire_countera_2cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_3cout[0:0]), + .dataa(power_modified_counter_values[2]), + .datab(power_modified_counter_values[3]), + .ena(1'b1), + .regout(wire_countera_regout[3:3]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_3.cin_used = "true", + countera_3.lut_mask = "6c50", + countera_3.operation_mode = "arithmetic", + countera_3.sum_lutc_input = "cin", + countera_3.synch_mode = "on", + countera_3.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_4 + ( + .aclr(aclr), + .cin(wire_countera_3cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_4cout[0:0]), + .dataa(power_modified_counter_values[3]), + .datab(power_modified_counter_values[4]), + .ena(1'b1), + .regout(wire_countera_regout[4:4]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_4.cin_used = "true", + countera_4.lut_mask = "6c50", + countera_4.operation_mode = "arithmetic", + countera_4.sum_lutc_input = "cin", + countera_4.synch_mode = "on", + countera_4.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_5 + ( + .aclr(aclr), + .cin(wire_countera_4cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_5cout[0:0]), + .dataa(power_modified_counter_values[4]), + .datab(power_modified_counter_values[5]), + .ena(1'b1), + .regout(wire_countera_regout[5:5]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_5.cin_used = "true", + countera_5.lut_mask = "6c50", + countera_5.operation_mode = "arithmetic", + countera_5.sum_lutc_input = "cin", + countera_5.synch_mode = "on", + countera_5.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_6 + ( + .aclr(aclr), + .cin(wire_countera_5cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_6cout[0:0]), + .dataa(power_modified_counter_values[5]), + .datab(power_modified_counter_values[6]), + .ena(1'b1), + .regout(wire_countera_regout[6:6]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_6.cin_used = "true", + countera_6.lut_mask = "6c50", + countera_6.operation_mode = "arithmetic", + countera_6.sum_lutc_input = "cin", + countera_6.synch_mode = "on", + countera_6.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_7 + ( + .aclr(aclr), + .cin(wire_countera_6cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_7cout[0:0]), + .dataa(power_modified_counter_values[6]), + .datab(power_modified_counter_values[7]), + .ena(1'b1), + .regout(wire_countera_regout[7:7]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_7.cin_used = "true", + countera_7.lut_mask = "6c50", + countera_7.operation_mode = "arithmetic", + countera_7.sum_lutc_input = "cin", + countera_7.synch_mode = "on", + countera_7.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_8 + ( + .aclr(aclr), + .cin(wire_countera_7cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_8cout[0:0]), + .dataa(power_modified_counter_values[7]), + .datab(power_modified_counter_values[8]), + .ena(1'b1), + .regout(wire_countera_regout[8:8]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_8.cin_used = "true", + countera_8.lut_mask = "6c50", + countera_8.operation_mode = "arithmetic", + countera_8.sum_lutc_input = "cin", + countera_8.synch_mode = "on", + countera_8.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_9 + ( + .aclr(aclr), + .cin(wire_countera_8cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_9cout[0:0]), + .dataa(power_modified_counter_values[8]), + .datab(power_modified_counter_values[9]), + .ena(1'b1), + .regout(wire_countera_regout[9:9]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_9.cin_used = "true", + countera_9.lut_mask = "6c50", + countera_9.operation_mode = "arithmetic", + countera_9.sum_lutc_input = "cin", + countera_9.synch_mode = "on", + countera_9.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_10 + ( + .aclr(aclr), + .cin(wire_countera_9cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_10cout[0:0]), + .dataa(power_modified_counter_values[9]), + .datab(power_modified_counter_values[10]), + .ena(1'b1), + .regout(wire_countera_regout[10:10]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_10.cin_used = "true", + countera_10.lut_mask = "6c50", + countera_10.operation_mode = "arithmetic", + countera_10.sum_lutc_input = "cin", + countera_10.synch_mode = "on", + countera_10.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_11 + ( + .aclr(aclr), + .cin(wire_countera_10cout[0:0]), + .clk(clock), + .combout(), + .cout(), + .dataa(power_modified_counter_values[11]), + .ena(1'b1), + .regout(wire_countera_regout[11:11]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datab(1'b1), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_11.cin_used = "true", + countera_11.lut_mask = "5a5a", + countera_11.operation_mode = "normal", + countera_11.sum_lutc_input = "cin", + countera_11.synch_mode = "on", + countera_11.lpm_type = "cyclone_lcell"; + cyclone_lcell parity + ( + .aclr(aclr), + .cin(updown), + .clk(clock), + .combout(), + .cout(wire_parity_cout), + .dataa(cnt_en), + .datab(wire_parity_regout), + .ena(1'b1), + .regout(wire_parity_regout), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + parity.cin_used = "true", + parity.lut_mask = "6682", + parity.operation_mode = "arithmetic", + parity.synch_mode = "on", + parity.lpm_type = "cyclone_lcell"; + assign + power_modified_counter_values = {wire_countera_regout[11:0]}, + q = power_modified_counter_values, + sclr = 1'b0, + updown = 1'b1; +endmodule //fifo_4k_a_graycounter_826 + + +//a_graycounter DEVICE_FAMILY="Cyclone" PVALUE=1 WIDTH=12 aclr clock cnt_en q +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 13 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_a_graycounter_3r6 + ( + aclr, + clock, + cnt_en, + q) /* synthesis synthesis_clearbox=1 */; + input aclr; + input clock; + input cnt_en; + output [11:0] q; + + wire [0:0] wire_countera_0cout; + wire [0:0] wire_countera_1cout; + wire [0:0] wire_countera_2cout; + wire [0:0] wire_countera_3cout; + wire [0:0] wire_countera_4cout; + wire [0:0] wire_countera_5cout; + wire [0:0] wire_countera_6cout; + wire [0:0] wire_countera_7cout; + wire [0:0] wire_countera_8cout; + wire [0:0] wire_countera_9cout; + wire [0:0] wire_countera_10cout; + wire [11:0] wire_countera_regout; + wire wire_parity_cout; + wire wire_parity_regout; + wire [11:0] power_modified_counter_values; + wire sclr; + wire updown; + + cyclone_lcell countera_0 + ( + .aclr(aclr), + .cin(wire_parity_cout), + .clk(clock), + .combout(), + .cout(wire_countera_0cout[0:0]), + .dataa(cnt_en), + .datab(wire_countera_regout[0:0]), + .ena(1'b1), + .regout(wire_countera_regout[0:0]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_0.cin_used = "true", + countera_0.lut_mask = "c6a0", + countera_0.operation_mode = "arithmetic", + countera_0.sum_lutc_input = "cin", + countera_0.synch_mode = "on", + countera_0.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_1 + ( + .aclr(aclr), + .cin(wire_countera_0cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_1cout[0:0]), + .dataa(power_modified_counter_values[0]), + .datab(power_modified_counter_values[1]), + .ena(1'b1), + .regout(wire_countera_regout[1:1]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_1.cin_used = "true", + countera_1.lut_mask = "6c50", + countera_1.operation_mode = "arithmetic", + countera_1.sum_lutc_input = "cin", + countera_1.synch_mode = "on", + countera_1.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_2 + ( + .aclr(aclr), + .cin(wire_countera_1cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_2cout[0:0]), + .dataa(power_modified_counter_values[1]), + .datab(power_modified_counter_values[2]), + .ena(1'b1), + .regout(wire_countera_regout[2:2]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_2.cin_used = "true", + countera_2.lut_mask = "6c50", + countera_2.operation_mode = "arithmetic", + countera_2.sum_lutc_input = "cin", + countera_2.synch_mode = "on", + countera_2.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_3 + ( + .aclr(aclr), + .cin(wire_countera_2cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_3cout[0:0]), + .dataa(power_modified_counter_values[2]), + .datab(power_modified_counter_values[3]), + .ena(1'b1), + .regout(wire_countera_regout[3:3]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_3.cin_used = "true", + countera_3.lut_mask = "6c50", + countera_3.operation_mode = "arithmetic", + countera_3.sum_lutc_input = "cin", + countera_3.synch_mode = "on", + countera_3.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_4 + ( + .aclr(aclr), + .cin(wire_countera_3cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_4cout[0:0]), + .dataa(power_modified_counter_values[3]), + .datab(power_modified_counter_values[4]), + .ena(1'b1), + .regout(wire_countera_regout[4:4]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_4.cin_used = "true", + countera_4.lut_mask = "6c50", + countera_4.operation_mode = "arithmetic", + countera_4.sum_lutc_input = "cin", + countera_4.synch_mode = "on", + countera_4.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_5 + ( + .aclr(aclr), + .cin(wire_countera_4cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_5cout[0:0]), + .dataa(power_modified_counter_values[4]), + .datab(power_modified_counter_values[5]), + .ena(1'b1), + .regout(wire_countera_regout[5:5]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_5.cin_used = "true", + countera_5.lut_mask = "6c50", + countera_5.operation_mode = "arithmetic", + countera_5.sum_lutc_input = "cin", + countera_5.synch_mode = "on", + countera_5.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_6 + ( + .aclr(aclr), + .cin(wire_countera_5cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_6cout[0:0]), + .dataa(power_modified_counter_values[5]), + .datab(power_modified_counter_values[6]), + .ena(1'b1), + .regout(wire_countera_regout[6:6]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_6.cin_used = "true", + countera_6.lut_mask = "6c50", + countera_6.operation_mode = "arithmetic", + countera_6.sum_lutc_input = "cin", + countera_6.synch_mode = "on", + countera_6.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_7 + ( + .aclr(aclr), + .cin(wire_countera_6cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_7cout[0:0]), + .dataa(power_modified_counter_values[6]), + .datab(power_modified_counter_values[7]), + .ena(1'b1), + .regout(wire_countera_regout[7:7]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_7.cin_used = "true", + countera_7.lut_mask = "6c50", + countera_7.operation_mode = "arithmetic", + countera_7.sum_lutc_input = "cin", + countera_7.synch_mode = "on", + countera_7.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_8 + ( + .aclr(aclr), + .cin(wire_countera_7cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_8cout[0:0]), + .dataa(power_modified_counter_values[7]), + .datab(power_modified_counter_values[8]), + .ena(1'b1), + .regout(wire_countera_regout[8:8]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_8.cin_used = "true", + countera_8.lut_mask = "6c50", + countera_8.operation_mode = "arithmetic", + countera_8.sum_lutc_input = "cin", + countera_8.synch_mode = "on", + countera_8.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_9 + ( + .aclr(aclr), + .cin(wire_countera_8cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_9cout[0:0]), + .dataa(power_modified_counter_values[8]), + .datab(power_modified_counter_values[9]), + .ena(1'b1), + .regout(wire_countera_regout[9:9]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_9.cin_used = "true", + countera_9.lut_mask = "6c50", + countera_9.operation_mode = "arithmetic", + countera_9.sum_lutc_input = "cin", + countera_9.synch_mode = "on", + countera_9.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_10 + ( + .aclr(aclr), + .cin(wire_countera_9cout[0:0]), + .clk(clock), + .combout(), + .cout(wire_countera_10cout[0:0]), + .dataa(power_modified_counter_values[9]), + .datab(power_modified_counter_values[10]), + .ena(1'b1), + .regout(wire_countera_regout[10:10]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_10.cin_used = "true", + countera_10.lut_mask = "6c50", + countera_10.operation_mode = "arithmetic", + countera_10.sum_lutc_input = "cin", + countera_10.synch_mode = "on", + countera_10.lpm_type = "cyclone_lcell"; + cyclone_lcell countera_11 + ( + .aclr(aclr), + .cin(wire_countera_10cout[0:0]), + .clk(clock), + .combout(), + .cout(), + .dataa(power_modified_counter_values[11]), + .ena(1'b1), + .regout(wire_countera_regout[11:11]), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datab(1'b1), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + countera_11.cin_used = "true", + countera_11.lut_mask = "5a5a", + countera_11.operation_mode = "normal", + countera_11.sum_lutc_input = "cin", + countera_11.synch_mode = "on", + countera_11.lpm_type = "cyclone_lcell"; + cyclone_lcell parity + ( + .aclr(aclr), + .cin(updown), + .clk(clock), + .combout(), + .cout(wire_parity_cout), + .dataa(cnt_en), + .datab((~ wire_parity_regout)), + .ena(1'b1), + .regout(wire_parity_regout), + .sclr(sclr) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aload(1'b0), + .datac(1'b1), + .datad(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + parity.cin_used = "true", + parity.lut_mask = "9982", + parity.operation_mode = "arithmetic", + parity.synch_mode = "on", + parity.lpm_type = "cyclone_lcell"; + assign + power_modified_counter_values = {wire_countera_regout[11:1], (~ wire_countera_regout[0])}, + q = power_modified_counter_values, + sclr = 1'b0, + updown = 1'b1; +endmodule //fifo_4k_a_graycounter_3r6 + + +//altsyncram ADDRESS_REG_B="CLOCK1" DEVICE_FAMILY="Cyclone" OPERATION_MODE="DUAL_PORT" OUTDATA_REG_B="UNREGISTERED" WIDTH_A=16 WIDTH_B=16 WIDTH_BYTEENA_A=1 WIDTHAD_A=12 WIDTHAD_B=12 address_a address_b clock0 clock1 clocken1 data_a q_b wren_a +//VERSION_BEGIN 5.0 cbx_altsyncram 2005:03:24:13:58:56:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_lpm_decode 2004:12:13:14:19:12:SJ cbx_lpm_mux 2004:12:13:14:16:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + +//synthesis_resources = M4K 16 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_altsyncram_8pl + ( + address_a, + address_b, + clock0, + clock1, + clocken1, + data_a, + q_b, + wren_a) /* synthesis synthesis_clearbox=1 */; + input [11:0] address_a; + input [11:0] address_b; + input clock0; + input clock1; + input clocken1; + input [15:0] data_a; + output [15:0] q_b; + input wren_a; + + wire [0:0] wire_ram_block3a_0portbdataout; + wire [0:0] wire_ram_block3a_1portbdataout; + wire [0:0] wire_ram_block3a_2portbdataout; + wire [0:0] wire_ram_block3a_3portbdataout; + wire [0:0] wire_ram_block3a_4portbdataout; + wire [0:0] wire_ram_block3a_5portbdataout; + wire [0:0] wire_ram_block3a_6portbdataout; + wire [0:0] wire_ram_block3a_7portbdataout; + wire [0:0] wire_ram_block3a_8portbdataout; + wire [0:0] wire_ram_block3a_9portbdataout; + wire [0:0] wire_ram_block3a_10portbdataout; + wire [0:0] wire_ram_block3a_11portbdataout; + wire [0:0] wire_ram_block3a_12portbdataout; + wire [0:0] wire_ram_block3a_13portbdataout; + wire [0:0] wire_ram_block3a_14portbdataout; + wire [0:0] wire_ram_block3a_15portbdataout; + wire [11:0] address_a_wire; + wire [11:0] address_b_wire; + + cyclone_ram_block ram_block3a_0 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[0]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_0portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_0.connectivity_checking = "OFF", + ram_block3a_0.logical_ram_name = "ALTSYNCRAM", + ram_block3a_0.mixed_port_feed_through_mode = "dont_care", + ram_block3a_0.operation_mode = "dual_port", + ram_block3a_0.port_a_address_width = 12, + ram_block3a_0.port_a_data_width = 1, + ram_block3a_0.port_a_first_address = 0, + ram_block3a_0.port_a_first_bit_number = 0, + ram_block3a_0.port_a_last_address = 4095, + ram_block3a_0.port_a_logical_ram_depth = 4096, + ram_block3a_0.port_a_logical_ram_width = 16, + ram_block3a_0.port_b_address_clear = "none", + ram_block3a_0.port_b_address_clock = "clock1", + ram_block3a_0.port_b_address_width = 12, + ram_block3a_0.port_b_data_out_clear = "none", + ram_block3a_0.port_b_data_out_clock = "none", + ram_block3a_0.port_b_data_width = 1, + ram_block3a_0.port_b_first_address = 0, + ram_block3a_0.port_b_first_bit_number = 0, + ram_block3a_0.port_b_last_address = 4095, + ram_block3a_0.port_b_logical_ram_depth = 4096, + ram_block3a_0.port_b_logical_ram_width = 16, + ram_block3a_0.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_0.ram_block_type = "auto", + ram_block3a_0.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_1 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[1]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_1portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_1.connectivity_checking = "OFF", + ram_block3a_1.logical_ram_name = "ALTSYNCRAM", + ram_block3a_1.mixed_port_feed_through_mode = "dont_care", + ram_block3a_1.operation_mode = "dual_port", + ram_block3a_1.port_a_address_width = 12, + ram_block3a_1.port_a_data_width = 1, + ram_block3a_1.port_a_first_address = 0, + ram_block3a_1.port_a_first_bit_number = 1, + ram_block3a_1.port_a_last_address = 4095, + ram_block3a_1.port_a_logical_ram_depth = 4096, + ram_block3a_1.port_a_logical_ram_width = 16, + ram_block3a_1.port_b_address_clear = "none", + ram_block3a_1.port_b_address_clock = "clock1", + ram_block3a_1.port_b_address_width = 12, + ram_block3a_1.port_b_data_out_clear = "none", + ram_block3a_1.port_b_data_out_clock = "none", + ram_block3a_1.port_b_data_width = 1, + ram_block3a_1.port_b_first_address = 0, + ram_block3a_1.port_b_first_bit_number = 1, + ram_block3a_1.port_b_last_address = 4095, + ram_block3a_1.port_b_logical_ram_depth = 4096, + ram_block3a_1.port_b_logical_ram_width = 16, + ram_block3a_1.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_1.ram_block_type = "auto", + ram_block3a_1.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_2 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[2]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_2portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_2.connectivity_checking = "OFF", + ram_block3a_2.logical_ram_name = "ALTSYNCRAM", + ram_block3a_2.mixed_port_feed_through_mode = "dont_care", + ram_block3a_2.operation_mode = "dual_port", + ram_block3a_2.port_a_address_width = 12, + ram_block3a_2.port_a_data_width = 1, + ram_block3a_2.port_a_first_address = 0, + ram_block3a_2.port_a_first_bit_number = 2, + ram_block3a_2.port_a_last_address = 4095, + ram_block3a_2.port_a_logical_ram_depth = 4096, + ram_block3a_2.port_a_logical_ram_width = 16, + ram_block3a_2.port_b_address_clear = "none", + ram_block3a_2.port_b_address_clock = "clock1", + ram_block3a_2.port_b_address_width = 12, + ram_block3a_2.port_b_data_out_clear = "none", + ram_block3a_2.port_b_data_out_clock = "none", + ram_block3a_2.port_b_data_width = 1, + ram_block3a_2.port_b_first_address = 0, + ram_block3a_2.port_b_first_bit_number = 2, + ram_block3a_2.port_b_last_address = 4095, + ram_block3a_2.port_b_logical_ram_depth = 4096, + ram_block3a_2.port_b_logical_ram_width = 16, + ram_block3a_2.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_2.ram_block_type = "auto", + ram_block3a_2.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_3 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[3]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_3portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_3.connectivity_checking = "OFF", + ram_block3a_3.logical_ram_name = "ALTSYNCRAM", + ram_block3a_3.mixed_port_feed_through_mode = "dont_care", + ram_block3a_3.operation_mode = "dual_port", + ram_block3a_3.port_a_address_width = 12, + ram_block3a_3.port_a_data_width = 1, + ram_block3a_3.port_a_first_address = 0, + ram_block3a_3.port_a_first_bit_number = 3, + ram_block3a_3.port_a_last_address = 4095, + ram_block3a_3.port_a_logical_ram_depth = 4096, + ram_block3a_3.port_a_logical_ram_width = 16, + ram_block3a_3.port_b_address_clear = "none", + ram_block3a_3.port_b_address_clock = "clock1", + ram_block3a_3.port_b_address_width = 12, + ram_block3a_3.port_b_data_out_clear = "none", + ram_block3a_3.port_b_data_out_clock = "none", + ram_block3a_3.port_b_data_width = 1, + ram_block3a_3.port_b_first_address = 0, + ram_block3a_3.port_b_first_bit_number = 3, + ram_block3a_3.port_b_last_address = 4095, + ram_block3a_3.port_b_logical_ram_depth = 4096, + ram_block3a_3.port_b_logical_ram_width = 16, + ram_block3a_3.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_3.ram_block_type = "auto", + ram_block3a_3.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_4 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[4]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_4portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_4.connectivity_checking = "OFF", + ram_block3a_4.logical_ram_name = "ALTSYNCRAM", + ram_block3a_4.mixed_port_feed_through_mode = "dont_care", + ram_block3a_4.operation_mode = "dual_port", + ram_block3a_4.port_a_address_width = 12, + ram_block3a_4.port_a_data_width = 1, + ram_block3a_4.port_a_first_address = 0, + ram_block3a_4.port_a_first_bit_number = 4, + ram_block3a_4.port_a_last_address = 4095, + ram_block3a_4.port_a_logical_ram_depth = 4096, + ram_block3a_4.port_a_logical_ram_width = 16, + ram_block3a_4.port_b_address_clear = "none", + ram_block3a_4.port_b_address_clock = "clock1", + ram_block3a_4.port_b_address_width = 12, + ram_block3a_4.port_b_data_out_clear = "none", + ram_block3a_4.port_b_data_out_clock = "none", + ram_block3a_4.port_b_data_width = 1, + ram_block3a_4.port_b_first_address = 0, + ram_block3a_4.port_b_first_bit_number = 4, + ram_block3a_4.port_b_last_address = 4095, + ram_block3a_4.port_b_logical_ram_depth = 4096, + ram_block3a_4.port_b_logical_ram_width = 16, + ram_block3a_4.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_4.ram_block_type = "auto", + ram_block3a_4.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_5 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[5]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_5portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_5.connectivity_checking = "OFF", + ram_block3a_5.logical_ram_name = "ALTSYNCRAM", + ram_block3a_5.mixed_port_feed_through_mode = "dont_care", + ram_block3a_5.operation_mode = "dual_port", + ram_block3a_5.port_a_address_width = 12, + ram_block3a_5.port_a_data_width = 1, + ram_block3a_5.port_a_first_address = 0, + ram_block3a_5.port_a_first_bit_number = 5, + ram_block3a_5.port_a_last_address = 4095, + ram_block3a_5.port_a_logical_ram_depth = 4096, + ram_block3a_5.port_a_logical_ram_width = 16, + ram_block3a_5.port_b_address_clear = "none", + ram_block3a_5.port_b_address_clock = "clock1", + ram_block3a_5.port_b_address_width = 12, + ram_block3a_5.port_b_data_out_clear = "none", + ram_block3a_5.port_b_data_out_clock = "none", + ram_block3a_5.port_b_data_width = 1, + ram_block3a_5.port_b_first_address = 0, + ram_block3a_5.port_b_first_bit_number = 5, + ram_block3a_5.port_b_last_address = 4095, + ram_block3a_5.port_b_logical_ram_depth = 4096, + ram_block3a_5.port_b_logical_ram_width = 16, + ram_block3a_5.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_5.ram_block_type = "auto", + ram_block3a_5.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_6 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[6]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_6portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_6.connectivity_checking = "OFF", + ram_block3a_6.logical_ram_name = "ALTSYNCRAM", + ram_block3a_6.mixed_port_feed_through_mode = "dont_care", + ram_block3a_6.operation_mode = "dual_port", + ram_block3a_6.port_a_address_width = 12, + ram_block3a_6.port_a_data_width = 1, + ram_block3a_6.port_a_first_address = 0, + ram_block3a_6.port_a_first_bit_number = 6, + ram_block3a_6.port_a_last_address = 4095, + ram_block3a_6.port_a_logical_ram_depth = 4096, + ram_block3a_6.port_a_logical_ram_width = 16, + ram_block3a_6.port_b_address_clear = "none", + ram_block3a_6.port_b_address_clock = "clock1", + ram_block3a_6.port_b_address_width = 12, + ram_block3a_6.port_b_data_out_clear = "none", + ram_block3a_6.port_b_data_out_clock = "none", + ram_block3a_6.port_b_data_width = 1, + ram_block3a_6.port_b_first_address = 0, + ram_block3a_6.port_b_first_bit_number = 6, + ram_block3a_6.port_b_last_address = 4095, + ram_block3a_6.port_b_logical_ram_depth = 4096, + ram_block3a_6.port_b_logical_ram_width = 16, + ram_block3a_6.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_6.ram_block_type = "auto", + ram_block3a_6.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_7 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[7]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_7portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_7.connectivity_checking = "OFF", + ram_block3a_7.logical_ram_name = "ALTSYNCRAM", + ram_block3a_7.mixed_port_feed_through_mode = "dont_care", + ram_block3a_7.operation_mode = "dual_port", + ram_block3a_7.port_a_address_width = 12, + ram_block3a_7.port_a_data_width = 1, + ram_block3a_7.port_a_first_address = 0, + ram_block3a_7.port_a_first_bit_number = 7, + ram_block3a_7.port_a_last_address = 4095, + ram_block3a_7.port_a_logical_ram_depth = 4096, + ram_block3a_7.port_a_logical_ram_width = 16, + ram_block3a_7.port_b_address_clear = "none", + ram_block3a_7.port_b_address_clock = "clock1", + ram_block3a_7.port_b_address_width = 12, + ram_block3a_7.port_b_data_out_clear = "none", + ram_block3a_7.port_b_data_out_clock = "none", + ram_block3a_7.port_b_data_width = 1, + ram_block3a_7.port_b_first_address = 0, + ram_block3a_7.port_b_first_bit_number = 7, + ram_block3a_7.port_b_last_address = 4095, + ram_block3a_7.port_b_logical_ram_depth = 4096, + ram_block3a_7.port_b_logical_ram_width = 16, + ram_block3a_7.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_7.ram_block_type = "auto", + ram_block3a_7.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_8 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[8]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_8portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_8.connectivity_checking = "OFF", + ram_block3a_8.logical_ram_name = "ALTSYNCRAM", + ram_block3a_8.mixed_port_feed_through_mode = "dont_care", + ram_block3a_8.operation_mode = "dual_port", + ram_block3a_8.port_a_address_width = 12, + ram_block3a_8.port_a_data_width = 1, + ram_block3a_8.port_a_first_address = 0, + ram_block3a_8.port_a_first_bit_number = 8, + ram_block3a_8.port_a_last_address = 4095, + ram_block3a_8.port_a_logical_ram_depth = 4096, + ram_block3a_8.port_a_logical_ram_width = 16, + ram_block3a_8.port_b_address_clear = "none", + ram_block3a_8.port_b_address_clock = "clock1", + ram_block3a_8.port_b_address_width = 12, + ram_block3a_8.port_b_data_out_clear = "none", + ram_block3a_8.port_b_data_out_clock = "none", + ram_block3a_8.port_b_data_width = 1, + ram_block3a_8.port_b_first_address = 0, + ram_block3a_8.port_b_first_bit_number = 8, + ram_block3a_8.port_b_last_address = 4095, + ram_block3a_8.port_b_logical_ram_depth = 4096, + ram_block3a_8.port_b_logical_ram_width = 16, + ram_block3a_8.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_8.ram_block_type = "auto", + ram_block3a_8.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_9 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[9]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_9portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_9.connectivity_checking = "OFF", + ram_block3a_9.logical_ram_name = "ALTSYNCRAM", + ram_block3a_9.mixed_port_feed_through_mode = "dont_care", + ram_block3a_9.operation_mode = "dual_port", + ram_block3a_9.port_a_address_width = 12, + ram_block3a_9.port_a_data_width = 1, + ram_block3a_9.port_a_first_address = 0, + ram_block3a_9.port_a_first_bit_number = 9, + ram_block3a_9.port_a_last_address = 4095, + ram_block3a_9.port_a_logical_ram_depth = 4096, + ram_block3a_9.port_a_logical_ram_width = 16, + ram_block3a_9.port_b_address_clear = "none", + ram_block3a_9.port_b_address_clock = "clock1", + ram_block3a_9.port_b_address_width = 12, + ram_block3a_9.port_b_data_out_clear = "none", + ram_block3a_9.port_b_data_out_clock = "none", + ram_block3a_9.port_b_data_width = 1, + ram_block3a_9.port_b_first_address = 0, + ram_block3a_9.port_b_first_bit_number = 9, + ram_block3a_9.port_b_last_address = 4095, + ram_block3a_9.port_b_logical_ram_depth = 4096, + ram_block3a_9.port_b_logical_ram_width = 16, + ram_block3a_9.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_9.ram_block_type = "auto", + ram_block3a_9.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_10 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[10]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_10portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_10.connectivity_checking = "OFF", + ram_block3a_10.logical_ram_name = "ALTSYNCRAM", + ram_block3a_10.mixed_port_feed_through_mode = "dont_care", + ram_block3a_10.operation_mode = "dual_port", + ram_block3a_10.port_a_address_width = 12, + ram_block3a_10.port_a_data_width = 1, + ram_block3a_10.port_a_first_address = 0, + ram_block3a_10.port_a_first_bit_number = 10, + ram_block3a_10.port_a_last_address = 4095, + ram_block3a_10.port_a_logical_ram_depth = 4096, + ram_block3a_10.port_a_logical_ram_width = 16, + ram_block3a_10.port_b_address_clear = "none", + ram_block3a_10.port_b_address_clock = "clock1", + ram_block3a_10.port_b_address_width = 12, + ram_block3a_10.port_b_data_out_clear = "none", + ram_block3a_10.port_b_data_out_clock = "none", + ram_block3a_10.port_b_data_width = 1, + ram_block3a_10.port_b_first_address = 0, + ram_block3a_10.port_b_first_bit_number = 10, + ram_block3a_10.port_b_last_address = 4095, + ram_block3a_10.port_b_logical_ram_depth = 4096, + ram_block3a_10.port_b_logical_ram_width = 16, + ram_block3a_10.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_10.ram_block_type = "auto", + ram_block3a_10.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_11 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[11]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_11portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_11.connectivity_checking = "OFF", + ram_block3a_11.logical_ram_name = "ALTSYNCRAM", + ram_block3a_11.mixed_port_feed_through_mode = "dont_care", + ram_block3a_11.operation_mode = "dual_port", + ram_block3a_11.port_a_address_width = 12, + ram_block3a_11.port_a_data_width = 1, + ram_block3a_11.port_a_first_address = 0, + ram_block3a_11.port_a_first_bit_number = 11, + ram_block3a_11.port_a_last_address = 4095, + ram_block3a_11.port_a_logical_ram_depth = 4096, + ram_block3a_11.port_a_logical_ram_width = 16, + ram_block3a_11.port_b_address_clear = "none", + ram_block3a_11.port_b_address_clock = "clock1", + ram_block3a_11.port_b_address_width = 12, + ram_block3a_11.port_b_data_out_clear = "none", + ram_block3a_11.port_b_data_out_clock = "none", + ram_block3a_11.port_b_data_width = 1, + ram_block3a_11.port_b_first_address = 0, + ram_block3a_11.port_b_first_bit_number = 11, + ram_block3a_11.port_b_last_address = 4095, + ram_block3a_11.port_b_logical_ram_depth = 4096, + ram_block3a_11.port_b_logical_ram_width = 16, + ram_block3a_11.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_11.ram_block_type = "auto", + ram_block3a_11.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_12 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[12]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_12portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_12.connectivity_checking = "OFF", + ram_block3a_12.logical_ram_name = "ALTSYNCRAM", + ram_block3a_12.mixed_port_feed_through_mode = "dont_care", + ram_block3a_12.operation_mode = "dual_port", + ram_block3a_12.port_a_address_width = 12, + ram_block3a_12.port_a_data_width = 1, + ram_block3a_12.port_a_first_address = 0, + ram_block3a_12.port_a_first_bit_number = 12, + ram_block3a_12.port_a_last_address = 4095, + ram_block3a_12.port_a_logical_ram_depth = 4096, + ram_block3a_12.port_a_logical_ram_width = 16, + ram_block3a_12.port_b_address_clear = "none", + ram_block3a_12.port_b_address_clock = "clock1", + ram_block3a_12.port_b_address_width = 12, + ram_block3a_12.port_b_data_out_clear = "none", + ram_block3a_12.port_b_data_out_clock = "none", + ram_block3a_12.port_b_data_width = 1, + ram_block3a_12.port_b_first_address = 0, + ram_block3a_12.port_b_first_bit_number = 12, + ram_block3a_12.port_b_last_address = 4095, + ram_block3a_12.port_b_logical_ram_depth = 4096, + ram_block3a_12.port_b_logical_ram_width = 16, + ram_block3a_12.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_12.ram_block_type = "auto", + ram_block3a_12.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_13 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[13]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_13portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_13.connectivity_checking = "OFF", + ram_block3a_13.logical_ram_name = "ALTSYNCRAM", + ram_block3a_13.mixed_port_feed_through_mode = "dont_care", + ram_block3a_13.operation_mode = "dual_port", + ram_block3a_13.port_a_address_width = 12, + ram_block3a_13.port_a_data_width = 1, + ram_block3a_13.port_a_first_address = 0, + ram_block3a_13.port_a_first_bit_number = 13, + ram_block3a_13.port_a_last_address = 4095, + ram_block3a_13.port_a_logical_ram_depth = 4096, + ram_block3a_13.port_a_logical_ram_width = 16, + ram_block3a_13.port_b_address_clear = "none", + ram_block3a_13.port_b_address_clock = "clock1", + ram_block3a_13.port_b_address_width = 12, + ram_block3a_13.port_b_data_out_clear = "none", + ram_block3a_13.port_b_data_out_clock = "none", + ram_block3a_13.port_b_data_width = 1, + ram_block3a_13.port_b_first_address = 0, + ram_block3a_13.port_b_first_bit_number = 13, + ram_block3a_13.port_b_last_address = 4095, + ram_block3a_13.port_b_logical_ram_depth = 4096, + ram_block3a_13.port_b_logical_ram_width = 16, + ram_block3a_13.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_13.ram_block_type = "auto", + ram_block3a_13.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_14 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[14]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_14portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_14.connectivity_checking = "OFF", + ram_block3a_14.logical_ram_name = "ALTSYNCRAM", + ram_block3a_14.mixed_port_feed_through_mode = "dont_care", + ram_block3a_14.operation_mode = "dual_port", + ram_block3a_14.port_a_address_width = 12, + ram_block3a_14.port_a_data_width = 1, + ram_block3a_14.port_a_first_address = 0, + ram_block3a_14.port_a_first_bit_number = 14, + ram_block3a_14.port_a_last_address = 4095, + ram_block3a_14.port_a_logical_ram_depth = 4096, + ram_block3a_14.port_a_logical_ram_width = 16, + ram_block3a_14.port_b_address_clear = "none", + ram_block3a_14.port_b_address_clock = "clock1", + ram_block3a_14.port_b_address_width = 12, + ram_block3a_14.port_b_data_out_clear = "none", + ram_block3a_14.port_b_data_out_clock = "none", + ram_block3a_14.port_b_data_width = 1, + ram_block3a_14.port_b_first_address = 0, + ram_block3a_14.port_b_first_bit_number = 14, + ram_block3a_14.port_b_last_address = 4095, + ram_block3a_14.port_b_logical_ram_depth = 4096, + ram_block3a_14.port_b_logical_ram_width = 16, + ram_block3a_14.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_14.ram_block_type = "auto", + ram_block3a_14.lpm_type = "cyclone_ram_block"; + cyclone_ram_block ram_block3a_15 + ( + .clk0(clock0), + .clk1(clock1), + .ena0(wren_a), + .ena1(clocken1), + .portaaddr({address_a_wire[11:0]}), + .portadatain({data_a[15]}), + .portadataout(), + .portawe(1'b1), + .portbaddr({address_b_wire[11:0]}), + .portbdataout(wire_ram_block3a_15portbdataout[0:0]), + .portbrewe(1'b1) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .clr0(1'b0), + .clr1(1'b0), + .portabyteenamasks(1'b1), + .portbbyteenamasks(1'b1), + .portbdatain(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + ram_block3a_15.connectivity_checking = "OFF", + ram_block3a_15.logical_ram_name = "ALTSYNCRAM", + ram_block3a_15.mixed_port_feed_through_mode = "dont_care", + ram_block3a_15.operation_mode = "dual_port", + ram_block3a_15.port_a_address_width = 12, + ram_block3a_15.port_a_data_width = 1, + ram_block3a_15.port_a_first_address = 0, + ram_block3a_15.port_a_first_bit_number = 15, + ram_block3a_15.port_a_last_address = 4095, + ram_block3a_15.port_a_logical_ram_depth = 4096, + ram_block3a_15.port_a_logical_ram_width = 16, + ram_block3a_15.port_b_address_clear = "none", + ram_block3a_15.port_b_address_clock = "clock1", + ram_block3a_15.port_b_address_width = 12, + ram_block3a_15.port_b_data_out_clear = "none", + ram_block3a_15.port_b_data_out_clock = "none", + ram_block3a_15.port_b_data_width = 1, + ram_block3a_15.port_b_first_address = 0, + ram_block3a_15.port_b_first_bit_number = 15, + ram_block3a_15.port_b_last_address = 4095, + ram_block3a_15.port_b_logical_ram_depth = 4096, + ram_block3a_15.port_b_logical_ram_width = 16, + ram_block3a_15.port_b_read_enable_write_enable_clock = "clock1", + ram_block3a_15.ram_block_type = "auto", + ram_block3a_15.lpm_type = "cyclone_ram_block"; + assign + address_a_wire = address_a, + address_b_wire = address_b, + q_b = {wire_ram_block3a_15portbdataout[0], wire_ram_block3a_14portbdataout[0], wire_ram_block3a_13portbdataout[0], wire_ram_block3a_12portbdataout[0], wire_ram_block3a_11portbdataout[0], wire_ram_block3a_10portbdataout[0], wire_ram_block3a_9portbdataout[0], wire_ram_block3a_8portbdataout[0], wire_ram_block3a_7portbdataout[0], wire_ram_block3a_6portbdataout[0], wire_ram_block3a_5portbdataout[0], wire_ram_block3a_4portbdataout[0], wire_ram_block3a_3portbdataout[0], wire_ram_block3a_2portbdataout[0], wire_ram_block3a_1portbdataout[0], wire_ram_block3a_0portbdataout[0]}; +endmodule //fifo_4k_altsyncram_8pl + + +//dffpipe DELAY=1 WIDTH=12 clock clrn d q +//VERSION_BEGIN 5.0 cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + +//synthesis_resources = lut 12 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_dffpipe_bb3 + ( + clock, + clrn, + d, + q) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="AUTO_SHIFT_REGISTER_RECOGNITION=OFF" */; + input clock; + input clrn; + input [11:0] d; + output [11:0] q; + + wire [11:0] wire_dffe4a_D; + reg [11:0] dffe4a; + wire ena; + wire prn; + wire sclr; + + // synopsys translate_off + initial + dffe4a[0:0] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[0:0] <= 1'b1; + else if (clrn == 1'b0) dffe4a[0:0] <= 1'b0; + else if (ena == 1'b1) dffe4a[0:0] <= wire_dffe4a_D[0:0]; + // synopsys translate_off + initial + dffe4a[1:1] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[1:1] <= 1'b1; + else if (clrn == 1'b0) dffe4a[1:1] <= 1'b0; + else if (ena == 1'b1) dffe4a[1:1] <= wire_dffe4a_D[1:1]; + // synopsys translate_off + initial + dffe4a[2:2] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[2:2] <= 1'b1; + else if (clrn == 1'b0) dffe4a[2:2] <= 1'b0; + else if (ena == 1'b1) dffe4a[2:2] <= wire_dffe4a_D[2:2]; + // synopsys translate_off + initial + dffe4a[3:3] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[3:3] <= 1'b1; + else if (clrn == 1'b0) dffe4a[3:3] <= 1'b0; + else if (ena == 1'b1) dffe4a[3:3] <= wire_dffe4a_D[3:3]; + // synopsys translate_off + initial + dffe4a[4:4] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[4:4] <= 1'b1; + else if (clrn == 1'b0) dffe4a[4:4] <= 1'b0; + else if (ena == 1'b1) dffe4a[4:4] <= wire_dffe4a_D[4:4]; + // synopsys translate_off + initial + dffe4a[5:5] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[5:5] <= 1'b1; + else if (clrn == 1'b0) dffe4a[5:5] <= 1'b0; + else if (ena == 1'b1) dffe4a[5:5] <= wire_dffe4a_D[5:5]; + // synopsys translate_off + initial + dffe4a[6:6] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[6:6] <= 1'b1; + else if (clrn == 1'b0) dffe4a[6:6] <= 1'b0; + else if (ena == 1'b1) dffe4a[6:6] <= wire_dffe4a_D[6:6]; + // synopsys translate_off + initial + dffe4a[7:7] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[7:7] <= 1'b1; + else if (clrn == 1'b0) dffe4a[7:7] <= 1'b0; + else if (ena == 1'b1) dffe4a[7:7] <= wire_dffe4a_D[7:7]; + // synopsys translate_off + initial + dffe4a[8:8] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[8:8] <= 1'b1; + else if (clrn == 1'b0) dffe4a[8:8] <= 1'b0; + else if (ena == 1'b1) dffe4a[8:8] <= wire_dffe4a_D[8:8]; + // synopsys translate_off + initial + dffe4a[9:9] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[9:9] <= 1'b1; + else if (clrn == 1'b0) dffe4a[9:9] <= 1'b0; + else if (ena == 1'b1) dffe4a[9:9] <= wire_dffe4a_D[9:9]; + // synopsys translate_off + initial + dffe4a[10:10] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[10:10] <= 1'b1; + else if (clrn == 1'b0) dffe4a[10:10] <= 1'b0; + else if (ena == 1'b1) dffe4a[10:10] <= wire_dffe4a_D[10:10]; + // synopsys translate_off + initial + dffe4a[11:11] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe4a[11:11] <= 1'b1; + else if (clrn == 1'b0) dffe4a[11:11] <= 1'b0; + else if (ena == 1'b1) dffe4a[11:11] <= wire_dffe4a_D[11:11]; + assign + wire_dffe4a_D = (d & {12{(~ sclr)}}); + assign + ena = 1'b1, + prn = 1'b1, + q = dffe4a, + sclr = 1'b0; +endmodule //fifo_4k_dffpipe_bb3 + + +//dffpipe WIDTH=12 clock clrn d q +//VERSION_BEGIN 5.0 cbx_a_gray2bin 2004:03:06:00:52:20:SJ cbx_a_graycounter 2004:10:01:12:13:16:SJ cbx_altdpram 2004:11:30:11:29:56:SJ cbx_altsyncram 2005:03:24:13:58:56:SJ cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_dcfifo 2005:03:07:17:11:14:SJ cbx_fifo_common 2004:12:13:14:26:24:SJ cbx_flex10ke 2002:10:18:16:54:38:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_lpm_counter 2005:02:02:04:37:10:SJ cbx_lpm_decode 2004:12:13:14:19:12:SJ cbx_lpm_mux 2004:12:13:14:16:38:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_scfifo 2005:03:10:10:52:20:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + + +//dffpipe WIDTH=12 clock clrn d q +//VERSION_BEGIN 5.0 cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratixii 2004:12:22:13:27:12:SJ cbx_util_mgl 2005:04:04:13:50:06:SJ VERSION_END + +//synthesis_resources = lut 12 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_dffpipe_em2 + ( + clock, + clrn, + d, + q) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="AUTO_SHIFT_REGISTER_RECOGNITION=OFF" */; + input clock; + input clrn; + input [11:0] d; + output [11:0] q; + + wire [11:0] wire_dffe6a_D; + reg [11:0] dffe6a; + wire ena; + wire prn; + wire sclr; + + // synopsys translate_off + initial + dffe6a[0:0] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[0:0] <= 1'b1; + else if (clrn == 1'b0) dffe6a[0:0] <= 1'b0; + else if (ena == 1'b1) dffe6a[0:0] <= wire_dffe6a_D[0:0]; + // synopsys translate_off + initial + dffe6a[1:1] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[1:1] <= 1'b1; + else if (clrn == 1'b0) dffe6a[1:1] <= 1'b0; + else if (ena == 1'b1) dffe6a[1:1] <= wire_dffe6a_D[1:1]; + // synopsys translate_off + initial + dffe6a[2:2] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[2:2] <= 1'b1; + else if (clrn == 1'b0) dffe6a[2:2] <= 1'b0; + else if (ena == 1'b1) dffe6a[2:2] <= wire_dffe6a_D[2:2]; + // synopsys translate_off + initial + dffe6a[3:3] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[3:3] <= 1'b1; + else if (clrn == 1'b0) dffe6a[3:3] <= 1'b0; + else if (ena == 1'b1) dffe6a[3:3] <= wire_dffe6a_D[3:3]; + // synopsys translate_off + initial + dffe6a[4:4] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[4:4] <= 1'b1; + else if (clrn == 1'b0) dffe6a[4:4] <= 1'b0; + else if (ena == 1'b1) dffe6a[4:4] <= wire_dffe6a_D[4:4]; + // synopsys translate_off + initial + dffe6a[5:5] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[5:5] <= 1'b1; + else if (clrn == 1'b0) dffe6a[5:5] <= 1'b0; + else if (ena == 1'b1) dffe6a[5:5] <= wire_dffe6a_D[5:5]; + // synopsys translate_off + initial + dffe6a[6:6] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[6:6] <= 1'b1; + else if (clrn == 1'b0) dffe6a[6:6] <= 1'b0; + else if (ena == 1'b1) dffe6a[6:6] <= wire_dffe6a_D[6:6]; + // synopsys translate_off + initial + dffe6a[7:7] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[7:7] <= 1'b1; + else if (clrn == 1'b0) dffe6a[7:7] <= 1'b0; + else if (ena == 1'b1) dffe6a[7:7] <= wire_dffe6a_D[7:7]; + // synopsys translate_off + initial + dffe6a[8:8] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[8:8] <= 1'b1; + else if (clrn == 1'b0) dffe6a[8:8] <= 1'b0; + else if (ena == 1'b1) dffe6a[8:8] <= wire_dffe6a_D[8:8]; + // synopsys translate_off + initial + dffe6a[9:9] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[9:9] <= 1'b1; + else if (clrn == 1'b0) dffe6a[9:9] <= 1'b0; + else if (ena == 1'b1) dffe6a[9:9] <= wire_dffe6a_D[9:9]; + // synopsys translate_off + initial + dffe6a[10:10] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[10:10] <= 1'b1; + else if (clrn == 1'b0) dffe6a[10:10] <= 1'b0; + else if (ena == 1'b1) dffe6a[10:10] <= wire_dffe6a_D[10:10]; + // synopsys translate_off + initial + dffe6a[11:11] = 0; + // synopsys translate_on + always @ ( posedge clock or negedge prn or negedge clrn) + if (prn == 1'b0) dffe6a[11:11] <= 1'b1; + else if (clrn == 1'b0) dffe6a[11:11] <= 1'b0; + else if (ena == 1'b1) dffe6a[11:11] <= wire_dffe6a_D[11:11]; + assign + wire_dffe6a_D = (d & {12{(~ sclr)}}); + assign + ena = 1'b1, + prn = 1'b1, + q = dffe6a, + sclr = 1'b0; +endmodule //fifo_4k_dffpipe_em2 + +//synthesis_resources = lut 12 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_alt_synch_pipe_em2 + ( + clock, + clrn, + d, + q) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="X_ON_VIOLATION_OPTION=OFF" */; + input clock; + input clrn; + input [11:0] d; + output [11:0] q; + + wire [11:0] wire_dffpipe5_q; + + fifo_4k_dffpipe_em2 dffpipe5 + ( + .clock(clock), + .clrn(clrn), + .d(d), + .q(wire_dffpipe5_q)); + assign + q = wire_dffpipe5_q; +endmodule //fifo_4k_alt_synch_pipe_em2 + + +//lpm_add_sub DEVICE_FAMILY="Cyclone" LPM_DIRECTION="SUB" LPM_WIDTH=12 dataa datab result +//VERSION_BEGIN 5.0 cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 12 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_add_sub_b18 + ( + dataa, + datab, + result) /* synthesis synthesis_clearbox=1 */; + input [11:0] dataa; + input [11:0] datab; + output [11:0] result; + + wire [11:0] wire_add_sub_cella_combout; + wire [0:0] wire_add_sub_cella_0cout; + wire [0:0] wire_add_sub_cella_1cout; + wire [0:0] wire_add_sub_cella_2cout; + wire [0:0] wire_add_sub_cella_3cout; + wire [0:0] wire_add_sub_cella_4cout; + wire [0:0] wire_add_sub_cella_5cout; + wire [0:0] wire_add_sub_cella_6cout; + wire [0:0] wire_add_sub_cella_7cout; + wire [0:0] wire_add_sub_cella_8cout; + wire [0:0] wire_add_sub_cella_9cout; + wire [0:0] wire_add_sub_cella_10cout; + wire [11:0] wire_add_sub_cella_dataa; + wire [11:0] wire_add_sub_cella_datab; + + cyclone_lcell add_sub_cella_0 + ( + .cin(1'b1), + .combout(wire_add_sub_cella_combout[0:0]), + .cout(wire_add_sub_cella_0cout[0:0]), + .dataa(wire_add_sub_cella_dataa[0:0]), + .datab(wire_add_sub_cella_datab[0:0]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_0.cin_used = "true", + add_sub_cella_0.lut_mask = "69b2", + add_sub_cella_0.operation_mode = "arithmetic", + add_sub_cella_0.sum_lutc_input = "cin", + add_sub_cella_0.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_1 + ( + .cin(wire_add_sub_cella_0cout[0:0]), + .combout(wire_add_sub_cella_combout[1:1]), + .cout(wire_add_sub_cella_1cout[0:0]), + .dataa(wire_add_sub_cella_dataa[1:1]), + .datab(wire_add_sub_cella_datab[1:1]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_1.cin_used = "true", + add_sub_cella_1.lut_mask = "69b2", + add_sub_cella_1.operation_mode = "arithmetic", + add_sub_cella_1.sum_lutc_input = "cin", + add_sub_cella_1.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_2 + ( + .cin(wire_add_sub_cella_1cout[0:0]), + .combout(wire_add_sub_cella_combout[2:2]), + .cout(wire_add_sub_cella_2cout[0:0]), + .dataa(wire_add_sub_cella_dataa[2:2]), + .datab(wire_add_sub_cella_datab[2:2]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_2.cin_used = "true", + add_sub_cella_2.lut_mask = "69b2", + add_sub_cella_2.operation_mode = "arithmetic", + add_sub_cella_2.sum_lutc_input = "cin", + add_sub_cella_2.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_3 + ( + .cin(wire_add_sub_cella_2cout[0:0]), + .combout(wire_add_sub_cella_combout[3:3]), + .cout(wire_add_sub_cella_3cout[0:0]), + .dataa(wire_add_sub_cella_dataa[3:3]), + .datab(wire_add_sub_cella_datab[3:3]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_3.cin_used = "true", + add_sub_cella_3.lut_mask = "69b2", + add_sub_cella_3.operation_mode = "arithmetic", + add_sub_cella_3.sum_lutc_input = "cin", + add_sub_cella_3.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_4 + ( + .cin(wire_add_sub_cella_3cout[0:0]), + .combout(wire_add_sub_cella_combout[4:4]), + .cout(wire_add_sub_cella_4cout[0:0]), + .dataa(wire_add_sub_cella_dataa[4:4]), + .datab(wire_add_sub_cella_datab[4:4]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_4.cin_used = "true", + add_sub_cella_4.lut_mask = "69b2", + add_sub_cella_4.operation_mode = "arithmetic", + add_sub_cella_4.sum_lutc_input = "cin", + add_sub_cella_4.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_5 + ( + .cin(wire_add_sub_cella_4cout[0:0]), + .combout(wire_add_sub_cella_combout[5:5]), + .cout(wire_add_sub_cella_5cout[0:0]), + .dataa(wire_add_sub_cella_dataa[5:5]), + .datab(wire_add_sub_cella_datab[5:5]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_5.cin_used = "true", + add_sub_cella_5.lut_mask = "69b2", + add_sub_cella_5.operation_mode = "arithmetic", + add_sub_cella_5.sum_lutc_input = "cin", + add_sub_cella_5.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_6 + ( + .cin(wire_add_sub_cella_5cout[0:0]), + .combout(wire_add_sub_cella_combout[6:6]), + .cout(wire_add_sub_cella_6cout[0:0]), + .dataa(wire_add_sub_cella_dataa[6:6]), + .datab(wire_add_sub_cella_datab[6:6]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_6.cin_used = "true", + add_sub_cella_6.lut_mask = "69b2", + add_sub_cella_6.operation_mode = "arithmetic", + add_sub_cella_6.sum_lutc_input = "cin", + add_sub_cella_6.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_7 + ( + .cin(wire_add_sub_cella_6cout[0:0]), + .combout(wire_add_sub_cella_combout[7:7]), + .cout(wire_add_sub_cella_7cout[0:0]), + .dataa(wire_add_sub_cella_dataa[7:7]), + .datab(wire_add_sub_cella_datab[7:7]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_7.cin_used = "true", + add_sub_cella_7.lut_mask = "69b2", + add_sub_cella_7.operation_mode = "arithmetic", + add_sub_cella_7.sum_lutc_input = "cin", + add_sub_cella_7.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_8 + ( + .cin(wire_add_sub_cella_7cout[0:0]), + .combout(wire_add_sub_cella_combout[8:8]), + .cout(wire_add_sub_cella_8cout[0:0]), + .dataa(wire_add_sub_cella_dataa[8:8]), + .datab(wire_add_sub_cella_datab[8:8]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_8.cin_used = "true", + add_sub_cella_8.lut_mask = "69b2", + add_sub_cella_8.operation_mode = "arithmetic", + add_sub_cella_8.sum_lutc_input = "cin", + add_sub_cella_8.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_9 + ( + .cin(wire_add_sub_cella_8cout[0:0]), + .combout(wire_add_sub_cella_combout[9:9]), + .cout(wire_add_sub_cella_9cout[0:0]), + .dataa(wire_add_sub_cella_dataa[9:9]), + .datab(wire_add_sub_cella_datab[9:9]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_9.cin_used = "true", + add_sub_cella_9.lut_mask = "69b2", + add_sub_cella_9.operation_mode = "arithmetic", + add_sub_cella_9.sum_lutc_input = "cin", + add_sub_cella_9.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_10 + ( + .cin(wire_add_sub_cella_9cout[0:0]), + .combout(wire_add_sub_cella_combout[10:10]), + .cout(wire_add_sub_cella_10cout[0:0]), + .dataa(wire_add_sub_cella_dataa[10:10]), + .datab(wire_add_sub_cella_datab[10:10]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_10.cin_used = "true", + add_sub_cella_10.lut_mask = "69b2", + add_sub_cella_10.operation_mode = "arithmetic", + add_sub_cella_10.sum_lutc_input = "cin", + add_sub_cella_10.lpm_type = "cyclone_lcell"; + cyclone_lcell add_sub_cella_11 + ( + .cin(wire_add_sub_cella_10cout[0:0]), + .combout(wire_add_sub_cella_combout[11:11]), + .cout(), + .dataa(wire_add_sub_cella_dataa[11:11]), + .datab(wire_add_sub_cella_datab[11:11]), + .regout() + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_off + `endif + , + .aclr(1'b0), + .aload(1'b0), + .clk(1'b1), + .datac(1'b1), + .datad(1'b1), + .ena(1'b1), + .inverta(1'b0), + .regcascin(1'b0), + .sclr(1'b0), + .sload(1'b0) + `ifdef FORMAL_VERIFICATION + `else + // synopsys translate_on + `endif + // synopsys translate_off + , + .cin0(), + .cin1(), + .cout0(), + .cout1(), + .devclrn(), + .devpor() + // synopsys translate_on + ); + defparam + add_sub_cella_11.cin_used = "true", + add_sub_cella_11.lut_mask = "6969", + add_sub_cella_11.operation_mode = "normal", + add_sub_cella_11.sum_lutc_input = "cin", + add_sub_cella_11.lpm_type = "cyclone_lcell"; + assign + wire_add_sub_cella_dataa = dataa, + wire_add_sub_cella_datab = datab; + assign + result = wire_add_sub_cella_combout; +endmodule //fifo_4k_add_sub_b18 + + +//lpm_compare DEVICE_FAMILY="Cyclone" LPM_WIDTH=12 aeb dataa datab +//VERSION_BEGIN 5.0 cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + + +//lpm_compare DEVICE_FAMILY="Cyclone" LPM_WIDTH=12 aeb dataa datab +//VERSION_BEGIN 5.0 cbx_cycloneii 2004:12:20:14:28:52:SJ cbx_lpm_add_sub 2005:04:12:13:30:42:SJ cbx_lpm_compare 2004:11:30:11:30:40:SJ cbx_mgl 2005:05:19:13:51:58:SJ cbx_stratix 2005:06:02:09:53:04:SJ cbx_stratixii 2004:12:22:13:27:12:SJ VERSION_END + +//synthesis_resources = lut 104 M4K 16 +//synopsys translate_off +`timescale 1 ps / 1 ps +//synopsys translate_on +module fifo_4k_dcfifo_6cq + ( + aclr, + data, + q, + rdclk, + rdempty, + rdreq, + rdusedw, + wrclk, + wrfull, + wrreq, + wrusedw) /* synthesis synthesis_clearbox=1 */ + /* synthesis ALTERA_ATTRIBUTE="AUTO_SHIFT_REGISTER_RECOGNITION=OFF;{ -from \"rdptr_g|power_modified_counter_values\" -to \"ws_dgrp|dffpipe5|dffe6a\" }CUT=ON;{ -from \"delayed_wrptr_g\" -to \"rs_dgwp|dffpipe5|dffe6a\" }CUT=ON" */; + input aclr; + input [15:0] data; + output [15:0] q; + input rdclk; + output rdempty; + input rdreq; + output [11:0] rdusedw; + input wrclk; + output wrfull; + input wrreq; + output [11:0] wrusedw; + + wire [11:0] wire_rdptr_g_gray2bin_bin; + wire [11:0] wire_rs_dgwp_gray2bin_bin; + wire [11:0] wire_wrptr_g_gray2bin_bin; + wire [11:0] wire_ws_dgrp_gray2bin_bin; + wire [11:0] wire_rdptr_g_q; + wire [11:0] wire_rdptr_g1p_q; + wire [11:0] wire_wrptr_g1p_q; + wire [15:0] wire_fifo_ram_q_b; + reg [11:0] delayed_wrptr_g; + reg [11:0] wrptr_g; + wire [11:0] wire_rs_brp_q; + wire [11:0] wire_rs_bwp_q; + wire [11:0] wire_rs_dgwp_q; + wire [11:0] wire_ws_brp_q; + wire [11:0] wire_ws_bwp_q; + wire [11:0] wire_ws_dgrp_q; + wire [11:0] wire_rdusedw_sub_result; + wire [11:0] wire_wrusedw_sub_result; + reg wire_rdempty_eq_comp_aeb_int; + wire wire_rdempty_eq_comp_aeb; + wire [11:0] wire_rdempty_eq_comp_dataa; + wire [11:0] wire_rdempty_eq_comp_datab; + reg wire_wrfull_eq_comp_aeb_int; + wire wire_wrfull_eq_comp_aeb; + wire [11:0] wire_wrfull_eq_comp_dataa; + wire [11:0] wire_wrfull_eq_comp_datab; + wire int_rdempty; + wire int_wrfull; + wire valid_rdreq; + wire valid_wrreq; + + fifo_4k_a_gray2bin_9m4 rdptr_g_gray2bin + ( + .bin(wire_rdptr_g_gray2bin_bin), + .gray(wire_rdptr_g_q)); + fifo_4k_a_gray2bin_9m4 rs_dgwp_gray2bin + ( + .bin(wire_rs_dgwp_gray2bin_bin), + .gray(wire_rs_dgwp_q)); + fifo_4k_a_gray2bin_9m4 wrptr_g_gray2bin + ( + .bin(wire_wrptr_g_gray2bin_bin), + .gray(wrptr_g)); + fifo_4k_a_gray2bin_9m4 ws_dgrp_gray2bin + ( + .bin(wire_ws_dgrp_gray2bin_bin), + .gray(wire_ws_dgrp_q)); + fifo_4k_a_graycounter_826 rdptr_g + ( + .aclr(aclr), + .clock(rdclk), + .cnt_en(valid_rdreq), + .q(wire_rdptr_g_q)); + fifo_4k_a_graycounter_3r6 rdptr_g1p + ( + .aclr(aclr), + .clock(rdclk), + .cnt_en(valid_rdreq), + .q(wire_rdptr_g1p_q)); + fifo_4k_a_graycounter_3r6 wrptr_g1p + ( + .aclr(aclr), + .clock(wrclk), + .cnt_en(valid_wrreq), + .q(wire_wrptr_g1p_q)); + fifo_4k_altsyncram_8pl fifo_ram + ( + .address_a(wrptr_g), + .address_b(((wire_rdptr_g_q & {12{int_rdempty}}) | (wire_rdptr_g1p_q & {12{(~ int_rdempty)}}))), + .clock0(wrclk), + .clock1(rdclk), + .clocken1((valid_rdreq | int_rdempty)), + .data_a(data), + .q_b(wire_fifo_ram_q_b), + .wren_a(valid_wrreq)); + // synopsys translate_off + initial + delayed_wrptr_g = 0; + // synopsys translate_on + always @ ( posedge wrclk or posedge aclr) + if (aclr == 1'b1) delayed_wrptr_g <= 12'b0; + else delayed_wrptr_g <= wrptr_g; + // synopsys translate_off + initial + wrptr_g = 0; + // synopsys translate_on + always @ ( posedge wrclk or posedge aclr) + if (aclr == 1'b1) wrptr_g <= 12'b0; + else if (valid_wrreq == 1'b1) wrptr_g <= wire_wrptr_g1p_q; + fifo_4k_dffpipe_bb3 rs_brp + ( + .clock(rdclk), + .clrn((~ aclr)), + .d(wire_rdptr_g_gray2bin_bin), + .q(wire_rs_brp_q)); + fifo_4k_dffpipe_bb3 rs_bwp + ( + .clock(rdclk), + .clrn((~ aclr)), + .d(wire_rs_dgwp_gray2bin_bin), + .q(wire_rs_bwp_q)); + fifo_4k_alt_synch_pipe_em2 rs_dgwp + ( + .clock(rdclk), + .clrn((~ aclr)), + .d(delayed_wrptr_g), + .q(wire_rs_dgwp_q)); + fifo_4k_dffpipe_bb3 ws_brp + ( + .clock(wrclk), + .clrn((~ aclr)), + .d(wire_ws_dgrp_gray2bin_bin), + .q(wire_ws_brp_q)); + fifo_4k_dffpipe_bb3 ws_bwp + ( + .clock(wrclk), + .clrn((~ aclr)), + .d(wire_wrptr_g_gray2bin_bin), + .q(wire_ws_bwp_q)); + fifo_4k_alt_synch_pipe_em2 ws_dgrp + ( + .clock(wrclk), + .clrn((~ aclr)), + .d(wire_rdptr_g_q), + .q(wire_ws_dgrp_q)); + fifo_4k_add_sub_b18 rdusedw_sub + ( + .dataa(wire_rs_bwp_q), + .datab(wire_rs_brp_q), + .result(wire_rdusedw_sub_result)); + fifo_4k_add_sub_b18 wrusedw_sub + ( + .dataa(wire_ws_bwp_q), + .datab(wire_ws_brp_q), + .result(wire_wrusedw_sub_result)); + always @(wire_rdempty_eq_comp_dataa or wire_rdempty_eq_comp_datab) + if (wire_rdempty_eq_comp_dataa == wire_rdempty_eq_comp_datab) + begin + wire_rdempty_eq_comp_aeb_int = 1'b1; + end + else + begin + wire_rdempty_eq_comp_aeb_int = 1'b0; + end + assign + wire_rdempty_eq_comp_aeb = wire_rdempty_eq_comp_aeb_int; + assign + wire_rdempty_eq_comp_dataa = wire_rs_dgwp_q, + wire_rdempty_eq_comp_datab = wire_rdptr_g_q; + always @(wire_wrfull_eq_comp_dataa or wire_wrfull_eq_comp_datab) + if (wire_wrfull_eq_comp_dataa == wire_wrfull_eq_comp_datab) + begin + wire_wrfull_eq_comp_aeb_int = 1'b1; + end + else + begin + wire_wrfull_eq_comp_aeb_int = 1'b0; + end + assign + wire_wrfull_eq_comp_aeb = wire_wrfull_eq_comp_aeb_int; + assign + wire_wrfull_eq_comp_dataa = wire_ws_dgrp_q, + wire_wrfull_eq_comp_datab = wire_wrptr_g1p_q; + assign + int_rdempty = wire_rdempty_eq_comp_aeb, + int_wrfull = wire_wrfull_eq_comp_aeb, + q = wire_fifo_ram_q_b, + rdempty = int_rdempty, + rdusedw = wire_rdusedw_sub_result, + valid_rdreq = rdreq, + valid_wrreq = wrreq, + wrfull = int_wrfull, + wrusedw = wire_wrusedw_sub_result; +endmodule //fifo_4k_dcfifo_6cq +//VALID FILE + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module fifo_4k ( + data, + wrreq, + rdreq, + rdclk, + wrclk, + aclr, + q, + rdempty, + rdusedw, + wrfull, + wrusedw)/* synthesis synthesis_clearbox = 1 */; + + input [15:0] data; + input wrreq; + input rdreq; + input rdclk; + input wrclk; + input aclr; + output [15:0] q; + output rdempty; + output [11:0] rdusedw; + output wrfull; + output [11:0] wrusedw; + + wire sub_wire0; + wire [11:0] sub_wire1; + wire sub_wire2; + wire [15:0] sub_wire3; + wire [11:0] sub_wire4; + wire rdempty = sub_wire0; + wire [11:0] wrusedw = sub_wire1[11:0]; + wire wrfull = sub_wire2; + wire [15:0] q = sub_wire3[15:0]; + wire [11:0] rdusedw = sub_wire4[11:0]; + + fifo_4k_dcfifo_6cq fifo_4k_dcfifo_6cq_component ( + .wrclk (wrclk), + .rdreq (rdreq), + .aclr (aclr), + .rdclk (rdclk), + .wrreq (wrreq), + .data (data), + .rdempty (sub_wire0), + .wrusedw (sub_wire1), + .wrfull (sub_wire2), + .q (sub_wire3), + .rdusedw (sub_wire4)); + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: Width NUMERIC "16" +// Retrieval info: PRIVATE: Depth NUMERIC "4096" +// Retrieval info: PRIVATE: Clock NUMERIC "4" +// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" +// Retrieval info: PRIVATE: Full NUMERIC "1" +// Retrieval info: PRIVATE: Empty NUMERIC "1" +// Retrieval info: PRIVATE: UsedW NUMERIC "1" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" +// Retrieval info: PRIVATE: sc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: sc_sclr NUMERIC "0" +// Retrieval info: PRIVATE: rsFull NUMERIC "0" +// Retrieval info: PRIVATE: rsEmpty NUMERIC "1" +// Retrieval info: PRIVATE: rsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: wsFull NUMERIC "1" +// Retrieval info: PRIVATE: wsEmpty NUMERIC "0" +// Retrieval info: PRIVATE: wsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: dc_aclr NUMERIC "1" +// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" +// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" +// Retrieval info: PRIVATE: Optimize NUMERIC "2" +// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096" +// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE" +// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo" +// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" +// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0] +// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0] +// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq +// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq +// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk +// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk +// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty +// Retrieval info: USED_PORT: rdusedw 0 0 12 0 OUTPUT NODEFVAL rdusedw[11..0] +// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull +// Retrieval info: USED_PORT: wrusedw 0 0 12 0 OUTPUT NODEFVAL wrusedw[11..0] +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr +// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0 +// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 +// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 +// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0 +// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0 +// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0 +// Retrieval info: CONNECT: rdusedw 0 0 12 0 @rdusedw 0 0 12 0 +// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0 +// Retrieval info: CONNECT: wrusedw 0 0 12 0 @wrusedw 0 0 12 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_bb.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_waveforms.html TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_wave*.jpg FALSE diff --git a/usrp/fpga/megacells/fifo_4k_bb.v b/usrp/fpga/megacells/fifo_4k_bb.v new file mode 100644 index 00000000..fc4ca979 --- /dev/null +++ b/usrp/fpga/megacells/fifo_4k_bb.v @@ -0,0 +1,131 @@ +// megafunction wizard: %FIFO%VBB% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: dcfifo + +// ============================================================ +// File Name: fifo_4k.v +// Megafunction Name(s): +// dcfifo +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 5.0 Build 168 06/22/2005 SP 1 SJ Web Edition +// ************************************************************ + +//Copyright (C) 1991-2005 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + +module fifo_4k ( + data, + wrreq, + rdreq, + rdclk, + wrclk, + aclr, + q, + rdempty, + rdusedw, + wrfull, + wrusedw)/* synthesis synthesis_clearbox = 1 */; + + input [15:0] data; + input wrreq; + input rdreq; + input rdclk; + input wrclk; + input aclr; + output [15:0] q; + output rdempty; + output [11:0] rdusedw; + output wrfull; + output [11:0] wrusedw; + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: Width NUMERIC "16" +// Retrieval info: PRIVATE: Depth NUMERIC "4096" +// Retrieval info: PRIVATE: Clock NUMERIC "4" +// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" +// Retrieval info: PRIVATE: Full NUMERIC "1" +// Retrieval info: PRIVATE: Empty NUMERIC "1" +// Retrieval info: PRIVATE: UsedW NUMERIC "1" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" +// Retrieval info: PRIVATE: sc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: sc_sclr NUMERIC "0" +// Retrieval info: PRIVATE: rsFull NUMERIC "0" +// Retrieval info: PRIVATE: rsEmpty NUMERIC "1" +// Retrieval info: PRIVATE: rsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: wsFull NUMERIC "1" +// Retrieval info: PRIVATE: wsEmpty NUMERIC "0" +// Retrieval info: PRIVATE: wsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: dc_aclr NUMERIC "1" +// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" +// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" +// Retrieval info: PRIVATE: Optimize NUMERIC "2" +// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096" +// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE" +// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo" +// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" +// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "OFF" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0] +// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0] +// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq +// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq +// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk +// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk +// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty +// Retrieval info: USED_PORT: rdusedw 0 0 12 0 OUTPUT NODEFVAL rdusedw[11..0] +// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull +// Retrieval info: USED_PORT: wrusedw 0 0 12 0 OUTPUT NODEFVAL wrusedw[11..0] +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr +// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0 +// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 +// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 +// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0 +// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0 +// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0 +// Retrieval info: CONNECT: rdusedw 0 0 12 0 @rdusedw 0 0 12 0 +// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0 +// Retrieval info: CONNECT: wrusedw 0 0 12 0 @wrusedw 0 0 12 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_bb.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_waveforms.html TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4k_wave*.jpg FALSE diff --git a/usrp/fpga/megacells/mylpm_addsub.bsf b/usrp/fpga/megacells/mylpm_addsub.bsf new file mode 100755 index 00000000..e5c1ded7 --- /dev/null +++ b/usrp/fpga/megacells/mylpm_addsub.bsf @@ -0,0 +1,80 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2003 Altera Corporation +Any megafunction design, and related netlist (encrypted or decrypted), +support information, device programming or simulation file, and any other +associated documentation or information provided by Altera or a partner +under Altera's Megafunction Partnership Program may be used only +to program PLD devices (but not masked PLD devices) from Altera. Any +other use of such megafunction design, netlist, support information, +device programming or simulation file, or any other related documentation +or information is prohibited for any other purpose, including, but not +limited to modification, reverse engineering, de-compiling, or use with +any other silicon devices, unless such use is explicitly licensed under +a separate agreement with Altera or a megafunction partner. Title to the +intellectual property, including patents, copyrights, trademarks, trade +secrets, or maskworks, embodied in any such megafunction design, netlist, +support information, device programming or simulation file, or any other +related documentation or information provided by Altera or a megafunction +partner, remains with Altera, the megafunction partner, or their respective +licensors. No other licenses, including any licenses needed under any third +party's intellectual property, are provided herein. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 160 112) + (text "mylpm_addsub" (rect 26 2 145 21)(font "Arial" (font_size 10))) + (text "inst" (rect 8 93 30 108)(font "Arial" )) + (port + (pt 0 56) + (input) + (text "dataa[15..0]" (rect 0 0 75 16)(font "Arial" (font_size 8))) + (text "dataa[15..0]" (rect 4 40 73 56)(font "Arial" (font_size 8))) + (line (pt 0 56)(pt 64 56)(line_width 3)) + ) + (port + (pt 0 88) + (input) + (text "datab[15..0]" (rect 0 0 75 16)(font "Arial" (font_size 8))) + (text "datab[15..0]" (rect 4 72 73 88)(font "Arial" (font_size 8))) + (line (pt 0 88)(pt 64 88)(line_width 3)) + ) + (port + (pt 0 72) + (input) + (text "clock" (rect 0 0 34 16)(font "Arial" (font_size 8))) + (text "clock" (rect 4 56 35 72)(font "Arial" (font_size 8))) + (line (pt 0 72)(pt 64 72)(line_width 1)) + ) + (port + (pt 0 32) + (input) + (text "add_sub" (rect 0 0 53 16)(font "Arial" (font_size 8))) + (text "add_sub" (rect 4 16 53 32)(font "Arial" (font_size 8))) + (line (pt 0 32)(pt 80 32)(line_width 1)) + ) + (port + (pt 160 72) + (output) + (text "result[15..0]" (rect 0 0 75 16)(font "Arial" (font_size 8))) + (text "result[15..0]" (rect 88 56 157 72)(font "Arial" (font_size 8))) + (line (pt 160 72)(pt 96 72)(line_width 3)) + ) + (drawing + (text "A" (rect 66 48 75 64)(font "Arial" (font_size 8))) + (text "B" (rect 66 80 75 96)(font "Arial" (font_size 8))) + (text "A+B/A-B" (rect 82 37 134 53)(font "Arial" (font_size 8))) + (line (pt 64 48)(pt 96 56)(line_width 1)) + (line (pt 96 56)(pt 96 88)(line_width 1)) + (line (pt 96 88)(pt 64 96)(line_width 1)) + (line (pt 64 96)(pt 64 48)(line_width 1)) + (line (pt 80 32)(pt 80 52)(line_width 1)) + (line (pt 106 40)(pt 125 40)(line_width 1)) + (line (pt 64 66)(pt 70 72)(line_width 1)) + (line (pt 70 72)(pt 64 78)(line_width 1)) + ) +) diff --git a/usrp/fpga/megacells/mylpm_addsub.cmp b/usrp/fpga/megacells/mylpm_addsub.cmp new file mode 100755 index 00000000..311c54a5 --- /dev/null +++ b/usrp/fpga/megacells/mylpm_addsub.cmp @@ -0,0 +1,31 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +component mylpm_addsub + PORT + ( + add_sub : IN STD_LOGIC ; + dataa : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + datab : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + clock : IN STD_LOGIC ; + result : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) + ); +end component; diff --git a/usrp/fpga/megacells/mylpm_addsub.inc b/usrp/fpga/megacells/mylpm_addsub.inc new file mode 100755 index 00000000..d8b283f4 --- /dev/null +++ b/usrp/fpga/megacells/mylpm_addsub.inc @@ -0,0 +1,32 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +FUNCTION mylpm_addsub +( + add_sub, + dataa[15..0], + datab[15..0], + clock +) + +RETURNS ( + result[15..0] +); diff --git a/usrp/fpga/megacells/mylpm_addsub.v b/usrp/fpga/megacells/mylpm_addsub.v new file mode 100755 index 00000000..0566f7e5 --- /dev/null +++ b/usrp/fpga/megacells/mylpm_addsub.v @@ -0,0 +1,102 @@ +// megafunction wizard: %LPM_ADD_SUB% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: lpm_add_sub + +// ============================================================ +// File Name: mylpm_addsub.v +// Megafunction Name(s): +// lpm_add_sub +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +module mylpm_addsub ( + add_sub, + dataa, + datab, + clock, + result); + + input add_sub; + input [15:0] dataa; + input [15:0] datab; + input clock; + output [15:0] result; + + wire [15:0] sub_wire0; + wire [15:0] result = sub_wire0[15:0]; + + lpm_add_sub lpm_add_sub_component ( + .dataa (dataa), + .add_sub (add_sub), + .datab (datab), + .clock (clock), + .result (sub_wire0)); + defparam + lpm_add_sub_component.lpm_width = 16, + lpm_add_sub_component.lpm_direction = "UNUSED", + lpm_add_sub_component.lpm_type = "LPM_ADD_SUB", + lpm_add_sub_component.lpm_hint = "ONE_INPUT_IS_CONSTANT=NO", + lpm_add_sub_component.lpm_pipeline = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: nBit NUMERIC "16" +// Retrieval info: PRIVATE: Function NUMERIC "2" +// Retrieval info: PRIVATE: WhichConstant NUMERIC "0" +// Retrieval info: PRIVATE: ConstantA NUMERIC "0" +// Retrieval info: PRIVATE: ConstantB NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtA NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtB NUMERIC "0" +// Retrieval info: PRIVATE: CarryIn NUMERIC "0" +// Retrieval info: PRIVATE: CarryOut NUMERIC "0" +// Retrieval info: PRIVATE: Overflow NUMERIC "0" +// Retrieval info: PRIVATE: Latency NUMERIC "1" +// Retrieval info: PRIVATE: aclr NUMERIC "0" +// Retrieval info: PRIVATE: clken NUMERIC "0" +// Retrieval info: PRIVATE: LPM_PIPELINE NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: LPM_DIRECTION STRING "UNUSED" +// Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_ADD_SUB" +// Retrieval info: CONSTANT: LPM_HINT STRING "ONE_INPUT_IS_CONSTANT=NO" +// Retrieval info: CONSTANT: LPM_PIPELINE NUMERIC "1" +// Retrieval info: USED_PORT: add_sub 0 0 0 0 INPUT NODEFVAL add_sub +// Retrieval info: USED_PORT: result 0 0 16 0 OUTPUT NODEFVAL result[15..0] +// Retrieval info: USED_PORT: dataa 0 0 16 0 INPUT NODEFVAL dataa[15..0] +// Retrieval info: USED_PORT: datab 0 0 16 0 INPUT NODEFVAL datab[15..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: CONNECT: @add_sub 0 0 0 0 add_sub 0 0 0 0 +// Retrieval info: CONNECT: result 0 0 16 0 @result 0 0 16 0 +// Retrieval info: CONNECT: @dataa 0 0 16 0 dataa 0 0 16 0 +// Retrieval info: CONNECT: @datab 0 0 16 0 datab 0 0 16 0 +// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0 +// Retrieval info: LIBRARY: lpm lpm.lpm_components.all diff --git a/usrp/fpga/megacells/mylpm_addsub_bb.v b/usrp/fpga/megacells/mylpm_addsub_bb.v new file mode 100755 index 00000000..598d3da5 --- /dev/null +++ b/usrp/fpga/megacells/mylpm_addsub_bb.v @@ -0,0 +1,35 @@ +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module mylpm_addsub ( + add_sub, + dataa, + datab, + clock, + result); + + input add_sub; + input [15:0] dataa; + input [15:0] datab; + input clock; + output [15:0] result; + +endmodule + diff --git a/usrp/fpga/megacells/mylpm_addsub_inst.v b/usrp/fpga/megacells/mylpm_addsub_inst.v new file mode 100755 index 00000000..dd732bd6 --- /dev/null +++ b/usrp/fpga/megacells/mylpm_addsub_inst.v @@ -0,0 +1,7 @@ +mylpm_addsub mylpm_addsub_inst ( + .add_sub ( add_sub_sig ), + .dataa ( dataa_sig ), + .datab ( datab_sig ), + .clock ( clock_sig ), + .result ( result_sig ) + ); diff --git a/usrp/fpga/megacells/pll.v b/usrp/fpga/megacells/pll.v new file mode 100644 index 00000000..dacd11f2 --- /dev/null +++ b/usrp/fpga/megacells/pll.v @@ -0,0 +1,207 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 4.0 Build 214 3/25/2004 SP 1 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0); + + input inclk0; + output c0; + + wire [5:0] sub_wire0; + wire [0:0] sub_wire4 = 1'h0; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire sub_wire2 = inclk0; + wire [1:0] sub_wire3 = {sub_wire4, sub_wire2}; + + altpll altpll_component ( + .inclk (sub_wire3), + .clk (sub_wire0) + // synopsys translate_off +, + .fbin (), + .pllena (), + .clkswitch (), + .areset (), + .pfdena (), + .clkena (), + .extclkena (), + .scanclk (), + .scanaclr (), + .scandata (), + .scanread (), + .scanwrite (), + .extclk (), + .clkbad (), + .activeclock (), + .locked (), + .clkloss (), + .scandataout (), + .scandone (), + .sclkout1 (), + .sclkout0 (), + .enable0 (), + .enable1 () + // synopsys translate_on + +); + defparam + altpll_component.clk0_duty_cycle = 50, + altpll_component.lpm_type = "altpll", + altpll_component.clk0_multiply_by = 1, + altpll_component.inclk0_input_frequency = 20833, + altpll_component.clk0_divide_by = 1, + altpll_component.pll_type = "AUTO", + altpll_component.clk0_time_delay = "0", + altpll_component.intended_device_family = "Cyclone", + altpll_component.operation_mode = "NORMAL", + altpll_component.compensate_clock = "CLK0", + altpll_component.clk0_phase_shift = "-3000"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "ns" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "-3.00000000" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: TIME_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_0 STRING "inclk;fbin;pllena;clkswitch;areset" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_1 STRING "pfdena;clkena;extclkena;scanclk;scanaclr" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_2 STRING "scandata;scanread;scanwrite;clk;extclk" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "528.000" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_3 STRING "clkbad;activeclock;locked;clkloss;scandataout" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "48.000" +// Retrieval info: PRIVATE: MEGAFN_PORT_INFO_4 STRING "scandone;sclkout1;sclkout0;enable0;enable1" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.000" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: DEV_FAMILY STRING "Cyclone" +// Retrieval info: PRIVATE: LOCK_LOSS_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: DEVICE_FAMILY NUMERIC "11" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "1" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20833" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_TIME_DELAY STRING "0" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "-3000" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT VCC "c0" +// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT VCC "@clk[5..0]" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT GND "inclk0" +// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT VCC "@extclk[3..0]" +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v TRUE FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v TRUE FALSE diff --git a/usrp/fpga/megacells/pll_bb.v b/usrp/fpga/megacells/pll_bb.v new file mode 100644 index 00000000..debadaa2 --- /dev/null +++ b/usrp/fpga/megacells/pll_bb.v @@ -0,0 +1,29 @@ +//Copyright (C) 1991-2004 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module pll ( + inclk0, + c0); + + input inclk0; + output c0; + +endmodule + diff --git a/usrp/fpga/megacells/pll_inst.v b/usrp/fpga/megacells/pll_inst.v new file mode 100644 index 00000000..97db58ba --- /dev/null +++ b/usrp/fpga/megacells/pll_inst.v @@ -0,0 +1,4 @@ +pll pll_inst ( + .inclk0 ( inclk0_sig ), + .c0 ( c0_sig ) + ); diff --git a/usrp/fpga/megacells/sub32.bsf b/usrp/fpga/megacells/sub32.bsf new file mode 100755 index 00000000..753fdc73 --- /dev/null +++ b/usrp/fpga/megacells/sub32.bsf @@ -0,0 +1,87 @@ +/* +WARNING: Do NOT edit the input and output ports in this file in a text +editor if you plan to continue editing the block that represents it in +the Block Editor! File corruption is VERY likely to occur. +*/ +/* +Copyright (C) 1991-2003 Altera Corporation +Any megafunction design, and related netlist (encrypted or decrypted), +support information, device programming or simulation file, and any other +associated documentation or information provided by Altera or a partner +under Altera's Megafunction Partnership Program may be used only +to program PLD devices (but not masked PLD devices) from Altera. Any +other use of such megafunction design, netlist, support information, +device programming or simulation file, or any other related documentation +or information is prohibited for any other purpose, including, but not +limited to modification, reverse engineering, de-compiling, or use with +any other silicon devices, unless such use is explicitly licensed under +a separate agreement with Altera or a megafunction partner. Title to the +intellectual property, including patents, copyrights, trademarks, trade +secrets, or maskworks, embodied in any such megafunction design, netlist, +support information, device programming or simulation file, or any other +related documentation or information provided by Altera or a megafunction +partner, remains with Altera, the megafunction partner, or their respective +licensors. No other licenses, including any licenses needed under any third +party's intellectual property, are provided herein. +*/ +(header "symbol" (version "1.1")) +(symbol + (rect 0 0 160 128) + (text "sub32" (rect 58 2 109 21)(font "Arial" (font_size 10))) + (text "inst" (rect 8 109 31 124)(font "Arial" )) + (port + (pt 0 40) + (input) + (text "dataa[31..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "dataa[31..0]" (rect 4 24 73 40)(font "Arial" (font_size 8))) + (line (pt 0 40)(pt 64 40)(line_width 3)) + ) + (port + (pt 0 72) + (input) + (text "datab[31..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "datab[31..0]" (rect 4 56 73 72)(font "Arial" (font_size 8))) + (line (pt 0 72)(pt 64 72)(line_width 3)) + ) + (port + (pt 0 56) + (input) + (text "clock" (rect 0 0 36 16)(font "Arial" (font_size 8))) + (text "clock" (rect 4 40 35 56)(font "Arial" (font_size 8))) + (line (pt 0 56)(pt 64 56)(line_width 1)) + ) + (port + (pt 0 96) + (input) + (text "clken" (rect 0 0 36 16)(font "Arial" (font_size 8))) + (text "clken" (rect 4 80 35 96)(font "Arial" (font_size 8))) + (line (pt 0 96)(pt 74 96)(line_width 1)) + ) + (port + (pt 0 112) + (input) + (text "aclr" (rect 0 0 24 16)(font "Arial" (font_size 8))) + (text "aclr" (rect 4 96 25 112)(font "Arial" (font_size 8))) + (line (pt 0 112)(pt 85 112)(line_width 1)) + ) + (port + (pt 160 56) + (output) + (text "result[31..0]" (rect 0 0 81 16)(font "Arial" (font_size 8))) + (text "result[31..0]" (rect 88 40 157 56)(font "Arial" (font_size 8))) + (line (pt 160 56)(pt 96 56)(line_width 3)) + ) + (drawing + (text "A" (rect 66 32 75 48)(font "Arial" (font_size 8))) + (text "B" (rect 66 64 75 80)(font "Arial" (font_size 8))) + (text "A-B" (rect 72 48 94 64)(font "Arial" (font_size 8))) + (line (pt 64 32)(pt 96 40)(line_width 1)) + (line (pt 96 40)(pt 96 72)(line_width 1)) + (line (pt 96 72)(pt 64 80)(line_width 1)) + (line (pt 64 80)(pt 64 32)(line_width 1)) + (line (pt 74 96)(pt 74 77)(line_width 1)) + (line (pt 85 112)(pt 85 74)(line_width 1)) + (line (pt 64 50)(pt 70 56)(line_width 1)) + (line (pt 70 56)(pt 64 62)(line_width 1)) + ) +) diff --git a/usrp/fpga/megacells/sub32.cmp b/usrp/fpga/megacells/sub32.cmp new file mode 100755 index 00000000..0d5b62ef --- /dev/null +++ b/usrp/fpga/megacells/sub32.cmp @@ -0,0 +1,32 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +component sub32 + PORT + ( + dataa : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + datab : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + clock : IN STD_LOGIC ; + aclr : IN STD_LOGIC ; + clken : IN STD_LOGIC ; + result : OUT STD_LOGIC_VECTOR (31 DOWNTO 0) + ); +end component; diff --git a/usrp/fpga/megacells/sub32.inc b/usrp/fpga/megacells/sub32.inc new file mode 100755 index 00000000..3c64e21c --- /dev/null +++ b/usrp/fpga/megacells/sub32.inc @@ -0,0 +1,33 @@ +--Copyright (C) 1991-2003 Altera Corporation +--Any megafunction design, and related netlist (encrypted or decrypted), +--support information, device programming or simulation file, and any other +--associated documentation or information provided by Altera or a partner +--under Altera's Megafunction Partnership Program may be used only +--to program PLD devices (but not masked PLD devices) from Altera. Any +--other use of such megafunction design, netlist, support information, +--device programming or simulation file, or any other related documentation +--or information is prohibited for any other purpose, including, but not +--limited to modification, reverse engineering, de-compiling, or use with +--any other silicon devices, unless such use is explicitly licensed under +--a separate agreement with Altera or a megafunction partner. Title to the +--intellectual property, including patents, copyrights, trademarks, trade +--secrets, or maskworks, embodied in any such megafunction design, netlist, +--support information, device programming or simulation file, or any other +--related documentation or information provided by Altera or a megafunction +--partner, remains with Altera, the megafunction partner, or their respective +--licensors. No other licenses, including any licenses needed under any third +--party's intellectual property, are provided herein. + + +FUNCTION sub32 +( + dataa[31..0], + datab[31..0], + clock, + aclr, + clken +) + +RETURNS ( + result[31..0] +); diff --git a/usrp/fpga/megacells/sub32.v b/usrp/fpga/megacells/sub32.v new file mode 100755 index 00000000..dd825d91 --- /dev/null +++ b/usrp/fpga/megacells/sub32.v @@ -0,0 +1,675 @@ +// megafunction wizard: %LPM_ADD_SUB%CBX% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: lpm_add_sub + +// ============================================================ +// File Name: sub32.v +// Megafunction Name(s): +// lpm_add_sub +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// ************************************************************ + + +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + + +//lpm_add_sub DEVICE_FAMILY=Cyclone LPM_DIRECTION=SUB LPM_PIPELINE=1 LPM_WIDTH=32 aclr clken clock dataa datab result +//VERSION_BEGIN 3.0 cbx_lpm_add_sub 2003:04:10:18:28:42:SJ cbx_mgl 2003:06:11:11:00:44:SJ cbx_stratix 2003:05:16:10:26:50:SJ VERSION_END + +//synthesis_resources = lut 32 +module sub32_add_sub_cqa + ( + aclr, + clken, + clock, + dataa, + datab, + result) /* synthesis synthesis_clearbox=1 */; + input aclr; + input clken; + input clock; + input [31:0] dataa; + input [31:0] datab; + output [31:0] result; + + wire [0:0] wire_add_sub_cella_0cout; + wire [0:0] wire_add_sub_cella_1cout; + wire [0:0] wire_add_sub_cella_2cout; + wire [0:0] wire_add_sub_cella_3cout; + wire [0:0] wire_add_sub_cella_4cout; + wire [0:0] wire_add_sub_cella_5cout; + wire [0:0] wire_add_sub_cella_6cout; + wire [0:0] wire_add_sub_cella_7cout; + wire [0:0] wire_add_sub_cella_8cout; + wire [0:0] wire_add_sub_cella_9cout; + wire [0:0] wire_add_sub_cella_10cout; + wire [0:0] wire_add_sub_cella_11cout; + wire [0:0] wire_add_sub_cella_12cout; + wire [0:0] wire_add_sub_cella_13cout; + wire [0:0] wire_add_sub_cella_14cout; + wire [0:0] wire_add_sub_cella_15cout; + wire [0:0] wire_add_sub_cella_16cout; + wire [0:0] wire_add_sub_cella_17cout; + wire [0:0] wire_add_sub_cella_18cout; + wire [0:0] wire_add_sub_cella_19cout; + wire [0:0] wire_add_sub_cella_20cout; + wire [0:0] wire_add_sub_cella_21cout; + wire [0:0] wire_add_sub_cella_22cout; + wire [0:0] wire_add_sub_cella_23cout; + wire [0:0] wire_add_sub_cella_24cout; + wire [0:0] wire_add_sub_cella_25cout; + wire [0:0] wire_add_sub_cella_26cout; + wire [0:0] wire_add_sub_cella_27cout; + wire [0:0] wire_add_sub_cella_28cout; + wire [0:0] wire_add_sub_cella_29cout; + wire [0:0] wire_add_sub_cella_30cout; + wire [31:0] wire_add_sub_cella_dataa; + wire [31:0] wire_add_sub_cella_datab; + wire [31:0] wire_add_sub_cella_regout; + + stratix_lcell add_sub_cella_0 + ( + .aclr(aclr), + .cin(1'b1), + .clk(clock), + .cout(wire_add_sub_cella_0cout[0:0]), + .dataa(wire_add_sub_cella_dataa[0:0]), + .datab(wire_add_sub_cella_datab[0:0]), + .ena(clken), + .regout(wire_add_sub_cella_regout[0:0])); + defparam + add_sub_cella_0.cin_used = "true", + add_sub_cella_0.lut_mask = "69b2", + add_sub_cella_0.operation_mode = "arithmetic", + add_sub_cella_0.sum_lutc_input = "cin", + add_sub_cella_0.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_1 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_0cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_1cout[0:0]), + .dataa(wire_add_sub_cella_dataa[1:1]), + .datab(wire_add_sub_cella_datab[1:1]), + .ena(clken), + .regout(wire_add_sub_cella_regout[1:1])); + defparam + add_sub_cella_1.cin_used = "true", + add_sub_cella_1.lut_mask = "69b2", + add_sub_cella_1.operation_mode = "arithmetic", + add_sub_cella_1.sum_lutc_input = "cin", + add_sub_cella_1.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_2 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_1cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_2cout[0:0]), + .dataa(wire_add_sub_cella_dataa[2:2]), + .datab(wire_add_sub_cella_datab[2:2]), + .ena(clken), + .regout(wire_add_sub_cella_regout[2:2])); + defparam + add_sub_cella_2.cin_used = "true", + add_sub_cella_2.lut_mask = "69b2", + add_sub_cella_2.operation_mode = "arithmetic", + add_sub_cella_2.sum_lutc_input = "cin", + add_sub_cella_2.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_3 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_2cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_3cout[0:0]), + .dataa(wire_add_sub_cella_dataa[3:3]), + .datab(wire_add_sub_cella_datab[3:3]), + .ena(clken), + .regout(wire_add_sub_cella_regout[3:3])); + defparam + add_sub_cella_3.cin_used = "true", + add_sub_cella_3.lut_mask = "69b2", + add_sub_cella_3.operation_mode = "arithmetic", + add_sub_cella_3.sum_lutc_input = "cin", + add_sub_cella_3.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_4 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_3cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_4cout[0:0]), + .dataa(wire_add_sub_cella_dataa[4:4]), + .datab(wire_add_sub_cella_datab[4:4]), + .ena(clken), + .regout(wire_add_sub_cella_regout[4:4])); + defparam + add_sub_cella_4.cin_used = "true", + add_sub_cella_4.lut_mask = "69b2", + add_sub_cella_4.operation_mode = "arithmetic", + add_sub_cella_4.sum_lutc_input = "cin", + add_sub_cella_4.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_5 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_4cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_5cout[0:0]), + .dataa(wire_add_sub_cella_dataa[5:5]), + .datab(wire_add_sub_cella_datab[5:5]), + .ena(clken), + .regout(wire_add_sub_cella_regout[5:5])); + defparam + add_sub_cella_5.cin_used = "true", + add_sub_cella_5.lut_mask = "69b2", + add_sub_cella_5.operation_mode = "arithmetic", + add_sub_cella_5.sum_lutc_input = "cin", + add_sub_cella_5.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_6 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_5cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_6cout[0:0]), + .dataa(wire_add_sub_cella_dataa[6:6]), + .datab(wire_add_sub_cella_datab[6:6]), + .ena(clken), + .regout(wire_add_sub_cella_regout[6:6])); + defparam + add_sub_cella_6.cin_used = "true", + add_sub_cella_6.lut_mask = "69b2", + add_sub_cella_6.operation_mode = "arithmetic", + add_sub_cella_6.sum_lutc_input = "cin", + add_sub_cella_6.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_7 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_6cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_7cout[0:0]), + .dataa(wire_add_sub_cella_dataa[7:7]), + .datab(wire_add_sub_cella_datab[7:7]), + .ena(clken), + .regout(wire_add_sub_cella_regout[7:7])); + defparam + add_sub_cella_7.cin_used = "true", + add_sub_cella_7.lut_mask = "69b2", + add_sub_cella_7.operation_mode = "arithmetic", + add_sub_cella_7.sum_lutc_input = "cin", + add_sub_cella_7.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_8 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_7cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_8cout[0:0]), + .dataa(wire_add_sub_cella_dataa[8:8]), + .datab(wire_add_sub_cella_datab[8:8]), + .ena(clken), + .regout(wire_add_sub_cella_regout[8:8])); + defparam + add_sub_cella_8.cin_used = "true", + add_sub_cella_8.lut_mask = "69b2", + add_sub_cella_8.operation_mode = "arithmetic", + add_sub_cella_8.sum_lutc_input = "cin", + add_sub_cella_8.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_9 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_8cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_9cout[0:0]), + .dataa(wire_add_sub_cella_dataa[9:9]), + .datab(wire_add_sub_cella_datab[9:9]), + .ena(clken), + .regout(wire_add_sub_cella_regout[9:9])); + defparam + add_sub_cella_9.cin_used = "true", + add_sub_cella_9.lut_mask = "69b2", + add_sub_cella_9.operation_mode = "arithmetic", + add_sub_cella_9.sum_lutc_input = "cin", + add_sub_cella_9.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_10 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_9cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_10cout[0:0]), + .dataa(wire_add_sub_cella_dataa[10:10]), + .datab(wire_add_sub_cella_datab[10:10]), + .ena(clken), + .regout(wire_add_sub_cella_regout[10:10])); + defparam + add_sub_cella_10.cin_used = "true", + add_sub_cella_10.lut_mask = "69b2", + add_sub_cella_10.operation_mode = "arithmetic", + add_sub_cella_10.sum_lutc_input = "cin", + add_sub_cella_10.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_11 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_10cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_11cout[0:0]), + .dataa(wire_add_sub_cella_dataa[11:11]), + .datab(wire_add_sub_cella_datab[11:11]), + .ena(clken), + .regout(wire_add_sub_cella_regout[11:11])); + defparam + add_sub_cella_11.cin_used = "true", + add_sub_cella_11.lut_mask = "69b2", + add_sub_cella_11.operation_mode = "arithmetic", + add_sub_cella_11.sum_lutc_input = "cin", + add_sub_cella_11.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_12 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_11cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_12cout[0:0]), + .dataa(wire_add_sub_cella_dataa[12:12]), + .datab(wire_add_sub_cella_datab[12:12]), + .ena(clken), + .regout(wire_add_sub_cella_regout[12:12])); + defparam + add_sub_cella_12.cin_used = "true", + add_sub_cella_12.lut_mask = "69b2", + add_sub_cella_12.operation_mode = "arithmetic", + add_sub_cella_12.sum_lutc_input = "cin", + add_sub_cella_12.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_13 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_12cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_13cout[0:0]), + .dataa(wire_add_sub_cella_dataa[13:13]), + .datab(wire_add_sub_cella_datab[13:13]), + .ena(clken), + .regout(wire_add_sub_cella_regout[13:13])); + defparam + add_sub_cella_13.cin_used = "true", + add_sub_cella_13.lut_mask = "69b2", + add_sub_cella_13.operation_mode = "arithmetic", + add_sub_cella_13.sum_lutc_input = "cin", + add_sub_cella_13.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_14 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_13cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_14cout[0:0]), + .dataa(wire_add_sub_cella_dataa[14:14]), + .datab(wire_add_sub_cella_datab[14:14]), + .ena(clken), + .regout(wire_add_sub_cella_regout[14:14])); + defparam + add_sub_cella_14.cin_used = "true", + add_sub_cella_14.lut_mask = "69b2", + add_sub_cella_14.operation_mode = "arithmetic", + add_sub_cella_14.sum_lutc_input = "cin", + add_sub_cella_14.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_15 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_14cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_15cout[0:0]), + .dataa(wire_add_sub_cella_dataa[15:15]), + .datab(wire_add_sub_cella_datab[15:15]), + .ena(clken), + .regout(wire_add_sub_cella_regout[15:15])); + defparam + add_sub_cella_15.cin_used = "true", + add_sub_cella_15.lut_mask = "69b2", + add_sub_cella_15.operation_mode = "arithmetic", + add_sub_cella_15.sum_lutc_input = "cin", + add_sub_cella_15.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_16 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_15cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_16cout[0:0]), + .dataa(wire_add_sub_cella_dataa[16:16]), + .datab(wire_add_sub_cella_datab[16:16]), + .ena(clken), + .regout(wire_add_sub_cella_regout[16:16])); + defparam + add_sub_cella_16.cin_used = "true", + add_sub_cella_16.lut_mask = "69b2", + add_sub_cella_16.operation_mode = "arithmetic", + add_sub_cella_16.sum_lutc_input = "cin", + add_sub_cella_16.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_17 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_16cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_17cout[0:0]), + .dataa(wire_add_sub_cella_dataa[17:17]), + .datab(wire_add_sub_cella_datab[17:17]), + .ena(clken), + .regout(wire_add_sub_cella_regout[17:17])); + defparam + add_sub_cella_17.cin_used = "true", + add_sub_cella_17.lut_mask = "69b2", + add_sub_cella_17.operation_mode = "arithmetic", + add_sub_cella_17.sum_lutc_input = "cin", + add_sub_cella_17.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_18 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_17cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_18cout[0:0]), + .dataa(wire_add_sub_cella_dataa[18:18]), + .datab(wire_add_sub_cella_datab[18:18]), + .ena(clken), + .regout(wire_add_sub_cella_regout[18:18])); + defparam + add_sub_cella_18.cin_used = "true", + add_sub_cella_18.lut_mask = "69b2", + add_sub_cella_18.operation_mode = "arithmetic", + add_sub_cella_18.sum_lutc_input = "cin", + add_sub_cella_18.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_19 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_18cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_19cout[0:0]), + .dataa(wire_add_sub_cella_dataa[19:19]), + .datab(wire_add_sub_cella_datab[19:19]), + .ena(clken), + .regout(wire_add_sub_cella_regout[19:19])); + defparam + add_sub_cella_19.cin_used = "true", + add_sub_cella_19.lut_mask = "69b2", + add_sub_cella_19.operation_mode = "arithmetic", + add_sub_cella_19.sum_lutc_input = "cin", + add_sub_cella_19.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_20 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_19cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_20cout[0:0]), + .dataa(wire_add_sub_cella_dataa[20:20]), + .datab(wire_add_sub_cella_datab[20:20]), + .ena(clken), + .regout(wire_add_sub_cella_regout[20:20])); + defparam + add_sub_cella_20.cin_used = "true", + add_sub_cella_20.lut_mask = "69b2", + add_sub_cella_20.operation_mode = "arithmetic", + add_sub_cella_20.sum_lutc_input = "cin", + add_sub_cella_20.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_21 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_20cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_21cout[0:0]), + .dataa(wire_add_sub_cella_dataa[21:21]), + .datab(wire_add_sub_cella_datab[21:21]), + .ena(clken), + .regout(wire_add_sub_cella_regout[21:21])); + defparam + add_sub_cella_21.cin_used = "true", + add_sub_cella_21.lut_mask = "69b2", + add_sub_cella_21.operation_mode = "arithmetic", + add_sub_cella_21.sum_lutc_input = "cin", + add_sub_cella_21.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_22 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_21cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_22cout[0:0]), + .dataa(wire_add_sub_cella_dataa[22:22]), + .datab(wire_add_sub_cella_datab[22:22]), + .ena(clken), + .regout(wire_add_sub_cella_regout[22:22])); + defparam + add_sub_cella_22.cin_used = "true", + add_sub_cella_22.lut_mask = "69b2", + add_sub_cella_22.operation_mode = "arithmetic", + add_sub_cella_22.sum_lutc_input = "cin", + add_sub_cella_22.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_23 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_22cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_23cout[0:0]), + .dataa(wire_add_sub_cella_dataa[23:23]), + .datab(wire_add_sub_cella_datab[23:23]), + .ena(clken), + .regout(wire_add_sub_cella_regout[23:23])); + defparam + add_sub_cella_23.cin_used = "true", + add_sub_cella_23.lut_mask = "69b2", + add_sub_cella_23.operation_mode = "arithmetic", + add_sub_cella_23.sum_lutc_input = "cin", + add_sub_cella_23.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_24 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_23cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_24cout[0:0]), + .dataa(wire_add_sub_cella_dataa[24:24]), + .datab(wire_add_sub_cella_datab[24:24]), + .ena(clken), + .regout(wire_add_sub_cella_regout[24:24])); + defparam + add_sub_cella_24.cin_used = "true", + add_sub_cella_24.lut_mask = "69b2", + add_sub_cella_24.operation_mode = "arithmetic", + add_sub_cella_24.sum_lutc_input = "cin", + add_sub_cella_24.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_25 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_24cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_25cout[0:0]), + .dataa(wire_add_sub_cella_dataa[25:25]), + .datab(wire_add_sub_cella_datab[25:25]), + .ena(clken), + .regout(wire_add_sub_cella_regout[25:25])); + defparam + add_sub_cella_25.cin_used = "true", + add_sub_cella_25.lut_mask = "69b2", + add_sub_cella_25.operation_mode = "arithmetic", + add_sub_cella_25.sum_lutc_input = "cin", + add_sub_cella_25.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_26 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_25cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_26cout[0:0]), + .dataa(wire_add_sub_cella_dataa[26:26]), + .datab(wire_add_sub_cella_datab[26:26]), + .ena(clken), + .regout(wire_add_sub_cella_regout[26:26])); + defparam + add_sub_cella_26.cin_used = "true", + add_sub_cella_26.lut_mask = "69b2", + add_sub_cella_26.operation_mode = "arithmetic", + add_sub_cella_26.sum_lutc_input = "cin", + add_sub_cella_26.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_27 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_26cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_27cout[0:0]), + .dataa(wire_add_sub_cella_dataa[27:27]), + .datab(wire_add_sub_cella_datab[27:27]), + .ena(clken), + .regout(wire_add_sub_cella_regout[27:27])); + defparam + add_sub_cella_27.cin_used = "true", + add_sub_cella_27.lut_mask = "69b2", + add_sub_cella_27.operation_mode = "arithmetic", + add_sub_cella_27.sum_lutc_input = "cin", + add_sub_cella_27.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_28 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_27cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_28cout[0:0]), + .dataa(wire_add_sub_cella_dataa[28:28]), + .datab(wire_add_sub_cella_datab[28:28]), + .ena(clken), + .regout(wire_add_sub_cella_regout[28:28])); + defparam + add_sub_cella_28.cin_used = "true", + add_sub_cella_28.lut_mask = "69b2", + add_sub_cella_28.operation_mode = "arithmetic", + add_sub_cella_28.sum_lutc_input = "cin", + add_sub_cella_28.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_29 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_28cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_29cout[0:0]), + .dataa(wire_add_sub_cella_dataa[29:29]), + .datab(wire_add_sub_cella_datab[29:29]), + .ena(clken), + .regout(wire_add_sub_cella_regout[29:29])); + defparam + add_sub_cella_29.cin_used = "true", + add_sub_cella_29.lut_mask = "69b2", + add_sub_cella_29.operation_mode = "arithmetic", + add_sub_cella_29.sum_lutc_input = "cin", + add_sub_cella_29.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_30 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_29cout[0:0]), + .clk(clock), + .cout(wire_add_sub_cella_30cout[0:0]), + .dataa(wire_add_sub_cella_dataa[30:30]), + .datab(wire_add_sub_cella_datab[30:30]), + .ena(clken), + .regout(wire_add_sub_cella_regout[30:30])); + defparam + add_sub_cella_30.cin_used = "true", + add_sub_cella_30.lut_mask = "69b2", + add_sub_cella_30.operation_mode = "arithmetic", + add_sub_cella_30.sum_lutc_input = "cin", + add_sub_cella_30.lpm_type = "stratix_lcell"; + stratix_lcell add_sub_cella_31 + ( + .aclr(aclr), + .cin(wire_add_sub_cella_30cout[0:0]), + .clk(clock), + .dataa(wire_add_sub_cella_dataa[31:31]), + .datab(wire_add_sub_cella_datab[31:31]), + .ena(clken), + .regout(wire_add_sub_cella_regout[31:31])); + defparam + add_sub_cella_31.cin_used = "true", + add_sub_cella_31.lut_mask = "6969", + add_sub_cella_31.operation_mode = "normal", + add_sub_cella_31.sum_lutc_input = "cin", + add_sub_cella_31.lpm_type = "stratix_lcell"; + assign + wire_add_sub_cella_dataa = dataa, + wire_add_sub_cella_datab = datab; + assign + result = wire_add_sub_cella_regout; +endmodule //sub32_add_sub_cqa +//VALID FILE + + +module sub32 ( + dataa, + datab, + clock, + aclr, + clken, + result)/* synthesis synthesis_clearbox = 1 */; + + input [31:0] dataa; + input [31:0] datab; + input clock; + input aclr; + input clken; + output [31:0] result; + + wire [31:0] sub_wire0; + wire [31:0] result = sub_wire0[31:0]; + + sub32_add_sub_cqa sub32_add_sub_cqa_component ( + .dataa (dataa), + .datab (datab), + .clken (clken), + .aclr (aclr), + .clock (clock), + .result (sub_wire0)); + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: nBit NUMERIC "32" +// Retrieval info: PRIVATE: Function NUMERIC "1" +// Retrieval info: PRIVATE: WhichConstant NUMERIC "0" +// Retrieval info: PRIVATE: ConstantA NUMERIC "0" +// Retrieval info: PRIVATE: ConstantB NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtA NUMERIC "0" +// Retrieval info: PRIVATE: ValidCtB NUMERIC "0" +// Retrieval info: PRIVATE: CarryIn NUMERIC "0" +// Retrieval info: PRIVATE: CarryOut NUMERIC "0" +// Retrieval info: PRIVATE: Overflow NUMERIC "0" +// Retrieval info: PRIVATE: Latency NUMERIC "1" +// Retrieval info: PRIVATE: aclr NUMERIC "1" +// Retrieval info: PRIVATE: clken NUMERIC "1" +// Retrieval info: PRIVATE: LPM_PIPELINE NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32" +// Retrieval info: CONSTANT: LPM_DIRECTION STRING "SUB" +// Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_ADD_SUB" +// Retrieval info: CONSTANT: LPM_HINT STRING "ONE_INPUT_IS_CONSTANT=NO" +// Retrieval info: CONSTANT: LPM_PIPELINE NUMERIC "1" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone" +// Retrieval info: USED_PORT: result 0 0 32 0 OUTPUT NODEFVAL result[31..0] +// Retrieval info: USED_PORT: dataa 0 0 32 0 INPUT NODEFVAL dataa[31..0] +// Retrieval info: USED_PORT: datab 0 0 32 0 INPUT NODEFVAL datab[31..0] +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr +// Retrieval info: USED_PORT: clken 0 0 0 0 INPUT NODEFVAL clken +// Retrieval info: CONNECT: result 0 0 32 0 @result 0 0 32 0 +// Retrieval info: CONNECT: @dataa 0 0 32 0 dataa 0 0 32 0 +// Retrieval info: CONNECT: @datab 0 0 32 0 datab 0 0 32 0 +// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 +// Retrieval info: CONNECT: @clken 0 0 0 0 clken 0 0 0 0 +// Retrieval info: LIBRARY: lpm lpm.lpm_components.all diff --git a/usrp/fpga/megacells/sub32_bb.v b/usrp/fpga/megacells/sub32_bb.v new file mode 100755 index 00000000..488ab51c --- /dev/null +++ b/usrp/fpga/megacells/sub32_bb.v @@ -0,0 +1,37 @@ +//Copyright (C) 1991-2003 Altera Corporation +//Any megafunction design, and related netlist (encrypted or decrypted), +//support information, device programming or simulation file, and any other +//associated documentation or information provided by Altera or a partner +//under Altera's Megafunction Partnership Program may be used only +//to program PLD devices (but not masked PLD devices) from Altera. Any +//other use of such megafunction design, netlist, support information, +//device programming or simulation file, or any other related documentation +//or information is prohibited for any other purpose, including, but not +//limited to modification, reverse engineering, de-compiling, or use with +//any other silicon devices, unless such use is explicitly licensed under +//a separate agreement with Altera or a megafunction partner. Title to the +//intellectual property, including patents, copyrights, trademarks, trade +//secrets, or maskworks, embodied in any such megafunction design, netlist, +//support information, device programming or simulation file, or any other +//related documentation or information provided by Altera or a megafunction +//partner, remains with Altera, the megafunction partner, or their respective +//licensors. No other licenses, including any licenses needed under any third +//party's intellectual property, are provided herein. + +module sub32 ( + dataa, + datab, + clock, + aclr, + clken, + result)/* synthesis synthesis_clearbox = 1 */; + + input [31:0] dataa; + input [31:0] datab; + input clock; + input aclr; + input clken; + output [31:0] result; + +endmodule + diff --git a/usrp/fpga/megacells/sub32_inst.v b/usrp/fpga/megacells/sub32_inst.v new file mode 100755 index 00000000..1916fc52 --- /dev/null +++ b/usrp/fpga/megacells/sub32_inst.v @@ -0,0 +1,8 @@ +sub32 sub32_inst ( + .dataa ( dataa_sig ), + .datab ( datab_sig ), + .clock ( clock_sig ), + .aclr ( aclr_sig ), + .clken ( clken_sig ), + .result ( result_sig ) + ); diff --git a/usrp/fpga/models/bustri.v b/usrp/fpga/models/bustri.v new file mode 100644 index 00000000..6e5a0f74 --- /dev/null +++ b/usrp/fpga/models/bustri.v @@ -0,0 +1,17 @@ + +// Model for tristate bus on altera +// FIXME do we really need to use a megacell for this? + +module bustri (data, + enabledt, + tridata); + + input [15:0] data; + input enabledt; + inout [15:0] tridata; + + assign tridata = enabledt ? data :16'bz; + +endmodule // bustri + + diff --git a/usrp/fpga/models/fifo.v b/usrp/fpga/models/fifo.v new file mode 100644 index 00000000..a04e7da6 --- /dev/null +++ b/usrp/fpga/models/fifo.v @@ -0,0 +1,81 @@ +// Model of FIFO in Altera + +module fifo( data, wrreq, rdreq, rdclk, wrclk, aclr, q, + rdfull, rdempty, rdusedw, wrfull, wrempty, wrusedw); + + parameter width = 16; + parameter depth = 1024; + parameter addr_bits = 10; + + //`define rd_req 0; // Set this to 0 for rd_ack, 1 for rd_req + + input [width-1:0] data; + input wrreq; + input rdreq; + input rdclk; + input wrclk; + input aclr; + output [width-1:0] q; + output rdfull; + output rdempty; + output reg [addr_bits-1:0] rdusedw; + output wrfull; + output wrempty; + output reg [addr_bits-1:0] wrusedw; + + reg [width-1:0] mem [0:depth-1]; + reg [addr_bits-1:0] rdptr; + reg [addr_bits-1:0] wrptr; + +`ifdef rd_req + reg [width-1:0] q; +`else + wire [width-1:0] q; +`endif + + integer i; + + always @( aclr) + begin + wrptr <= #1 0; + rdptr <= #1 0; + for(i=0;i DAC) + always @(posedge usbclk, posedge reset) + begin + if(reset) + begin + fifo_in <= #1 0; + write_count <= #1 0; + end + else + if(WR & ~write_count[8]) + begin + case(write_count[0]) + 1'b0 : fifo_in[31:16] <= #1 usbdata_in; // I + 1'b1 : fifo_in[15:0] <= #1 usbdata_in; // Q + endcase + write_count <= #1 write_count + 9'd1; + end + else + write_count <= #1 WR ? write_count : 9'b0; + end + + always @(posedge usbclk) + if(reset) + commit <= #1 1'b0; + else + if(write_count[0] && ~write_count[8] && WR) + commit <= #1 1'b1; + else + commit <= #1 1'b0; + + assign rdreq = txstrobe & !tx_empty; + assign txdata = tx_empty ? 32'b0 : txd; + + always @(posedge txclk) + if(reset) + tx_underrun <= 1'b0; + else if(txstrobe & tx_empty) + tx_underrun <= 1'b1; + else if(clear_status) + tx_underrun <= 1'b0; + + fifo_1c_2k txfifo (.data ( fifo_in ), + .wrreq ( commit ), + .wrclk ( usbclk ), + + .q ( txd ), + .rdreq ( rdreq), + .rdclk ( txclk ), + + .aclr ( reset ), + + .rdempty ( tx_empty ), + .rdusedw ( ), + .wrfull ( tx_full ), + .wrusedw ( txfifolevel ) + ); + + assign have_space = (txfifolevel <= (2048-128)); + + ////////////////////////////// + // Receive FIFO (ADC --> USB) + + always @(posedge rxclk) + if(reset) + rx_overrun <= 1'b0; + else if(rxstrobe & rx_full) + rx_overrun <= 1'b1; + else if(clear_status) + rx_overrun <= 1'b0; + + always @(select_out, fifo_out) + case(select_out) + 0 : usbdata_out = fifo_out[31:16]; // I + 1 : usbdata_out = fifo_out[15:0]; // Q + endcase + +/* + always @(posedge usbclk, posedge reset) + if(reset) + usbdata_out <= #1 16'b0; + else + if(select_out) + usbdata_out = fifo_out[31:16]; + else + usbdata_out = fifo_out[15:0]; + */ + + always @(negedge usbclk, posedge reset) + if(reset) + select_out <= #1 1'b0; + else if(~RD) + select_out <= #1 1'b0; + else + select_out <= #1 ~select_out; + + fifo_1c_2k rxfifo (.data ( rxdata ), // counter ), + .wrreq (rxstrobe & ~rx_full ), + .wrclk ( rxclk ), + + .q ( fifo_out ), + .rdreq ( select_out ),// & RD ), // FIXME + .rdclk ( usbclk ), + + .aclr ( reset ), + + .rdempty ( rx_empty ), + .rdusedw ( rxfifolevel ), + .wrfull ( rx_full ), + .wrusedw ( ) + ); + + assign have_pkt_rdy = (rxfifolevel >= 128); + + // Debugging Aids + assign debugbus[0] = tx_underrun; + assign debugbus[1] = rx_overrun; + assign debugbus[2] = tx_empty; + assign debugbus[3] = tx_full; + assign debugbus[4] = rx_empty; + assign debugbus[5] = rx_full; + assign debugbus[6] = txstrobe; + assign debugbus[7] = rxstrobe; + assign debugbus[8] = select_out; + assign debugbus[9] = rxstrobe & ~rx_full; + assign debugbus[10] = have_space; + assign debugbus[11] = have_pkt_rdy; + +endmodule // bus_interface + diff --git a/usrp/fpga/sdr_lib/cic_decim.v b/usrp/fpga/sdr_lib/cic_decim.v new file mode 100755 index 00000000..45b863f1 --- /dev/null +++ b/usrp/fpga/sdr_lib/cic_decim.v @@ -0,0 +1,106 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +module cic_decim + ( clock,reset,enable,rate,strobe_in,strobe_out,signal_in,signal_out); + parameter bw = 16; + parameter N = 4; + parameter log2_of_max_rate = 8; + parameter maxbitgain = N * log2_of_max_rate; + + input clock; + input reset; + input enable; + input [7:0] rate; + input strobe_in,strobe_out; + input [bw-1:0] signal_in; + output [bw-1:0] signal_out; + reg [bw-1:0] signal_out; + + wire [bw+maxbitgain-1:0] signal_in_ext; + reg [bw+maxbitgain-1:0] integrator [0:N-1]; + reg [bw+maxbitgain-1:0] differentiator [0:N-1]; + reg [bw+maxbitgain-1:0] pipeline [0:N-1]; + reg [bw+maxbitgain-1:0] sampler; + + integer i; + + sign_extend #(bw,bw+maxbitgain) + ext_input (.in(signal_in),.out(signal_in_ext)); + + always @(posedge clock) + if(reset) + for(i=0;i=0;i=i-1) + bin_val[i] = bin_val[i+1] ^ gray_val[i]; + end +endmodule // gray2bin diff --git a/usrp/fpga/sdr_lib/gen_cordic_consts.py b/usrp/fpga/sdr_lib/gen_cordic_consts.py new file mode 100755 index 00000000..ab66cfe0 --- /dev/null +++ b/usrp/fpga/sdr_lib/gen_cordic_consts.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +import math + +zwidth = 16 + +for i in range(17): + c = math.atan (1.0/(2**i)) / (2 * math.pi) * (1 << zwidth) + print "`define c%02d %d'd%d" % (i, zwidth, round (c)) + diff --git a/usrp/fpga/sdr_lib/gen_sync.v b/usrp/fpga/sdr_lib/gen_sync.v new file mode 100644 index 00000000..d72b39d5 --- /dev/null +++ b/usrp/fpga/sdr_lib/gen_sync.v @@ -0,0 +1,43 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +module gen_sync + ( input clock, + input reset, + input enable, + input [7:0] rate, + output wire sync ); + +// parameter width = 8; + + reg [7:0] counter; + assign sync = |(((rate+1)>>1)& counter); + + always @(posedge clock) + if(reset || ~enable) + counter <= #1 0; + else if(counter == rate) + counter <= #1 0; + else + counter <= #1 counter + 8'd1; + +endmodule // gen_sync + diff --git a/usrp/fpga/sdr_lib/hb/acc.v b/usrp/fpga/sdr_lib/hb/acc.v new file mode 100644 index 00000000..195d5ea9 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/acc.v @@ -0,0 +1,22 @@ + + +module acc (input clock, input reset, input clear, input enable_in, output reg enable_out, + input signed [30:0] addend, output reg signed [33:0] sum ); + + always @(posedge clock) + if(reset) + sum <= #1 34'd0; + //else if(clear & enable_in) + // sum <= #1 addend; + //else if(clear) + // sum <= #1 34'd0; + else if(clear) + sum <= #1 addend; + else if(enable_in) + sum <= #1 sum + addend; + + always @(posedge clock) + enable_out <= #1 enable_in; + +endmodule // acc + diff --git a/usrp/fpga/sdr_lib/hb/coeff_ram.v b/usrp/fpga/sdr_lib/hb/coeff_ram.v new file mode 100644 index 00000000..65460822 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/coeff_ram.v @@ -0,0 +1,26 @@ + + +module coeff_ram (input clock, input [3:0] rd_addr, output reg [15:0] rd_data); + + always @(posedge clock) + case (rd_addr) + 4'd0 : rd_data <= #1 -16'd16; + 4'd1 : rd_data <= #1 16'd74; + 4'd2 : rd_data <= #1 -16'd254; + 4'd3 : rd_data <= #1 16'd669; + 4'd4 : rd_data <= #1 -16'd1468; + 4'd5 : rd_data <= #1 16'd2950; + 4'd6 : rd_data <= #1 -16'd6158; + 4'd7 : rd_data <= #1 16'd20585; + 4'd8 : rd_data <= #1 16'd20585; + 4'd9 : rd_data <= #1 -16'd6158; + 4'd10 : rd_data <= #1 16'd2950; + 4'd11 : rd_data <= #1 -16'd1468; + 4'd12 : rd_data <= #1 16'd669; + 4'd13 : rd_data <= #1 -16'd254; + 4'd14 : rd_data <= #1 16'd74; + 4'd15 : rd_data <= #1 -16'd16; + default : rd_data <= #1 16'd0; + endcase // case(rd_addr) + +endmodule // ram diff --git a/usrp/fpga/sdr_lib/hb/coeff_rom.v b/usrp/fpga/sdr_lib/hb/coeff_rom.v new file mode 100644 index 00000000..c287eaaa --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/coeff_rom.v @@ -0,0 +1,19 @@ + + +module coeff_rom (input clock, input [2:0] addr, output reg [15:0] data); + + always @(posedge clock) + case (addr) + 3'd0 : data <= #1 -16'd16; + 3'd1 : data <= #1 16'd74; + 3'd2 : data <= #1 -16'd254; + 3'd3 : data <= #1 16'd669; + 3'd4 : data <= #1 -16'd1468; + 3'd5 : data <= #1 16'd2950; + 3'd6 : data <= #1 -16'd6158; + 3'd7 : data <= #1 16'd20585; + endcase // case(addr) + +endmodule // coeff_rom + + diff --git a/usrp/fpga/sdr_lib/hb/halfband_decim.v b/usrp/fpga/sdr_lib/hb/halfband_decim.v new file mode 100644 index 00000000..2a05ce52 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/halfband_decim.v @@ -0,0 +1,163 @@ +/* -*- verilog -*- + * + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2005 Matt Ettus + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This implements a 31-tap halfband filter that decimates by two. + * The coefficients are symmetric, and with the exception of the middle tap, + * every other coefficient is zero. The middle section of taps looks like this: + * + * ..., -1468, 0, 2950, 0, -6158, 0, 20585, 32768, 20585, 0, -6158, 0, 2950, 0, -1468, ... + * | + * middle tap -------+ + * + * See coeff_rom.v for the full set. The taps are scaled relative to 32768, + * thus the middle tap equals 1.0. Not counting the middle tap, there are 8 + * non-zero taps on each side, and they are symmetric. A naive implementation + * requires a mulitply for each non-zero tap. Because of symmetry, we can + * replace 2 multiplies with 1 add and 1 multiply. Thus, to compute each output + * sample, we need to perform 8 multiplications. Since the middle tap is 1.0, + * we just add the corresponding delay line value. + * + * About timing: We implement this with a single multiplier, so it takes + * 8 cycles to compute a single output. However, since we're decimating by two + * we can accept a new input value every 4 cycles. strobe_in is asserted when + * there's a new input sample available. Depending on the overall decimation + * rate, strobe_in may be asserted less frequently than once every 4 clocks. + * On the output side, we assert strobe_out when output contains a new sample. + * + * Implementation: Every time strobe_in is asserted we store the new data into + * the delay line. We split the delay line into two components, one for the + * even samples, and one for the odd samples. ram16_odd is the delay line for + * the odd samples. This ram is written on each odd assertion of strobe_in, and + * is read on each clock when we're computing the dot product. ram16_even is + * similar, although because it holds the even samples we must be able to read + * two samples from different addresses at the same time, while writing the incoming + * even samples. Thus it's "triple-ported". + */ + +module halfband_decim + (input clock, input reset, input enable, input strobe_in, output wire strobe_out, + input wire [15:0] data_in, output reg [15:0] data_out,output wire [15:0] debugctrl); + + reg [3:0] rd_addr1; + reg [3:0] rd_addr2; + reg [3:0] phase; + reg [3:0] base_addr; + + wire signed [15:0] mac_out,middle_data, sum, coeff; + wire signed [30:0] product; + wire signed [33:0] sum_even; + wire clear; + reg store_odd; + + always @(posedge clock) + if(reset) + store_odd <= #1 1'b0; + else + if(strobe_in) + store_odd <= #1 ~store_odd; + + wire start = strobe_in & store_odd; + always @(posedge clock) + if(reset) + base_addr <= #1 4'd0; + else if(start) + base_addr <= #1 base_addr + 4'd1; + + always @(posedge clock) + if(reset) + phase <= #1 4'd8; + else if (start) + phase <= #1 4'd0; + else if(phase != 4'd8) + phase <= #1 phase + 4'd1; + + reg start_d1,start_d2,start_d3,start_d4,start_d5,start_d6,start_d7,start_d8,start_d9,start_dA,start_dB,start_dC,start_dD; + always @(posedge clock) + begin + start_d1 <= #1 start; + start_d2 <= #1 start_d1; + start_d3 <= #1 start_d2; + start_d4 <= #1 start_d3; + start_d5 <= #1 start_d4; + start_d6 <= #1 start_d5; + start_d7 <= #1 start_d6; + start_d8 <= #1 start_d7; + start_d9 <= #1 start_d8; + start_dA <= #1 start_d9; + start_dB <= #1 start_dA; + start_dC <= #1 start_dB; + start_dD <= #1 start_dC; + end // always @ (posedge clock) + + reg mult_en, mult_en_pre; + always @(posedge clock) + begin + mult_en_pre <= #1 phase!=8; + mult_en <= #1 mult_en_pre; + end + + assign clear = start_d4; // was dC + wire latch_result = start_d4; // was dC + assign strobe_out = start_d5; // was dD + wire acc_en; + + always @* + case(phase[2:0]) + 3'd0 : begin rd_addr1 = base_addr + 4'd0; rd_addr2 = base_addr + 4'd15; end + 3'd1 : begin rd_addr1 = base_addr + 4'd1; rd_addr2 = base_addr + 4'd14; end + 3'd2 : begin rd_addr1 = base_addr + 4'd2; rd_addr2 = base_addr + 4'd13; end + 3'd3 : begin rd_addr1 = base_addr + 4'd3; rd_addr2 = base_addr + 4'd12; end + 3'd4 : begin rd_addr1 = base_addr + 4'd4; rd_addr2 = base_addr + 4'd11; end + 3'd5 : begin rd_addr1 = base_addr + 4'd5; rd_addr2 = base_addr + 4'd10; end + 3'd6 : begin rd_addr1 = base_addr + 4'd6; rd_addr2 = base_addr + 4'd9; end + 3'd7 : begin rd_addr1 = base_addr + 4'd7; rd_addr2 = base_addr + 4'd8; end + default: begin rd_addr1 = base_addr + 4'd0; rd_addr2 = base_addr + 4'd15; end + endcase // case(phase) + + coeff_rom coeff_rom (.clock(clock),.addr(phase[2:0]-3'd1),.data(coeff)); + + ram16_2sum ram16_even (.clock(clock),.write(strobe_in & ~store_odd), + .wr_addr(base_addr),.wr_data(data_in), + .rd_addr1(rd_addr1),.rd_addr2(rd_addr2), + .sum(sum)); + + ram16 ram16_odd (.clock(clock),.write(strobe_in & store_odd), // Holds middle items + .wr_addr(base_addr),.wr_data(data_in), + //.rd_addr(base_addr+4'd7),.rd_data(middle_data)); + .rd_addr(base_addr+4'd6),.rd_data(middle_data)); + + mult mult(.clock(clock),.x(coeff),.y(sum),.product(product),.enable_in(mult_en),.enable_out(acc_en)); + + acc acc(.clock(clock),.reset(reset),.enable_in(acc_en),.enable_out(), + .clear(clear),.addend(product),.sum(sum_even)); + + wire signed [33:0] dout = sum_even + {{4{middle_data[15]}},middle_data,14'b0}; // We already divided product by 2!!!! + + always @(posedge clock) + if(reset) + data_out <= #1 16'd0; + else if(latch_result) + data_out <= #1 dout[30:15] + (dout[33]& |dout[14:0]); + + assign debugctrl = { clock,reset,acc_en,mult_en,clear,latch_result,store_odd,strobe_in,strobe_out,phase}; + +endmodule // halfband_decim diff --git a/usrp/fpga/sdr_lib/hb/halfband_interp.v b/usrp/fpga/sdr_lib/hb/halfband_interp.v new file mode 100644 index 00000000..cdb11c1f --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/halfband_interp.v @@ -0,0 +1,121 @@ + + +module halfband_interp + (input clock, input reset, input enable, + input strobe_in, input strobe_out, + input [15:0] signal_in_i, input [15:0] signal_in_q, + output reg [15:0] signal_out_i, output reg [15:0] signal_out_q, + output wire [12:0] debug); + + wire [15:0] coeff_ram_out; + wire [15:0] data_ram_out_i; + wire [15:0] data_ram_out_q; + + wire [3:0] data_rd_addr; + reg [3:0] data_wr_addr; + reg [2:0] coeff_rd_addr; + + wire filt_done; + + wire [15:0] mac_out_i; + wire [15:0] mac_out_q; + reg [15:0] delayed_middle_i, delayed_middle_q; + wire [7:0] shift = 8'd9; + + reg stb_out_happened; + + wire [15:0] data_ram_out_i_b; + + always @(posedge clock) + if(strobe_in) + stb_out_happened <= #1 1'b0; + else if(strobe_out) + stb_out_happened <= #1 1'b1; + +assign debug = {filt_done,data_rd_addr,data_wr_addr,coeff_rd_addr}; + + wire [15:0] signal_out_i = stb_out_happened ? mac_out_i : delayed_middle_i; + wire [15:0] signal_out_q = stb_out_happened ? mac_out_q : delayed_middle_q; + +/* always @(posedge clock) + if(reset) + begin + signal_out_i <= #1 16'd0; + signal_out_q <= #1 16'd0; + end + else if(strobe_in) + begin + signal_out_i <= #1 delayed_middle_i; // Multiply by 1 for middle coeff + signal_out_q <= #1 delayed_middle_q; + end + //else if(filt_done&stb_out_happened) + else if(stb_out_happened) + begin + signal_out_i <= #1 mac_out_i; + signal_out_q <= #1 mac_out_q; + end +*/ + + always @(posedge clock) + if(reset) + coeff_rd_addr <= #1 3'd0; + else if(coeff_rd_addr != 3'd0) + coeff_rd_addr <= #1 coeff_rd_addr + 3'd1; + else if(strobe_in) + coeff_rd_addr <= #1 3'd1; + + reg filt_done_d1; + always@(posedge clock) + filt_done_d1 <= #1 filt_done; + + always @(posedge clock) + if(reset) + data_wr_addr <= #1 4'd0; + //else if(strobe_in) + else if(filt_done & ~filt_done_d1) + data_wr_addr <= #1 data_wr_addr + 4'd1; + + always @(posedge clock) + if(coeff_rd_addr == 3'd7) + begin + delayed_middle_i <= #1 data_ram_out_i_b; + // delayed_middle_q <= #1 data_ram_out_q_b; + end + +// always @(posedge clock) +// if(reset) +// data_rd_addr <= #1 4'd0; +// else if(strobe_in) +// data_rd_addr <= #1 data_wr_addr + 4'd1; +// else if(!filt_done) +// data_rd_addr <= #1 data_rd_addr + 4'd1; +// else +// data_rd_addr <= #1 data_wr_addr; + + wire [3:0] data_rd_addr1 = data_wr_addr + {1'b0,coeff_rd_addr}; + wire [3:0] data_rd_addr2 = data_wr_addr + 15 - {1'b0,coeff_rd_addr}; +// always @(posedge clock) +// if(reset) +// filt_done <= #1 1'b1; +// else if(strobe_in) + // filt_done <= #1 1'b0; +// else if(coeff_rd_addr == 4'd0) +// filt_done <= #1 1'b1; + + assign filt_done = (coeff_rd_addr == 3'd0); + + coeff_ram coeff_ram ( .clock(clock),.rd_addr({1'b0,coeff_rd_addr}),.rd_data(coeff_ram_out) ); + + ram16_2sum data_ram_i ( .clock(clock),.write(strobe_in),.wr_addr(data_wr_addr),.wr_data(signal_in_i), + .rd_addr1(data_rd_addr1),.rd_addr2(data_rd_addr2),.rd_data(data_ram_out_i_b),.sum(data_ram_out_i)); + + ram16_2sum data_ram_q ( .clock(clock),.write(strobe_in),.wr_addr(data_wr_addr),.wr_data(signal_in_q), + .rd_addr1(data_rd_addr1),.rd_addr2(data_rd_addr2),.rd_data(data_ram_out_q)); + + mac mac_i (.clock(clock),.reset(reset),.enable(~filt_done),.clear(strobe_in), + .x(data_ram_out_i),.y(coeff_ram_out),.shift(shift),.z(mac_out_i) ); + + mac mac_q (.clock(clock),.reset(reset),.enable(~filt_done),.clear(strobe_in), + .x(data_ram_out_q),.y(coeff_ram_out),.shift(shift),.z(mac_out_q) ); + +endmodule // halfband_interp diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/HBD b/usrp/fpga/sdr_lib/hb/hbd_tb/HBD new file mode 100644 index 00000000..574fbba9 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/hbd_tb/HBD @@ -0,0 +1,80 @@ +*-6.432683 5736 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +@28 +test_hbd.clock +test_hbd.reset +@420 +test_hbd.halfband_decim.middle_data[15:0] +@22 +test_hbd.halfband_decim.sum_even[33:0] +test_hbd.halfband_decim.base_addr[3:0] +@420 +test_hbd.i_in[15:0] +@24 +test_hbd.halfband_decim.phase[3:0] +test_hbd.halfband_decim.ram16_even.rd_addr1[3:0] +test_hbd.halfband_decim.ram16_even.rd_addr2[3:0] +test_hbd.halfband_decim.ram16_even.wr_addr[3:0] +test_hbd.halfband_decim.ram16_even.wr_data[15:0] +@28 +test_hbd.halfband_decim.ram16_even.write +@420 +test_hbd.halfband_decim.sum[15:0] +test_hbd.halfband_decim.product[30:0] +test_hbd.halfband_decim.dout[33:0] +test_hbd.halfband_decim.sum_even[33:0] +@22 +test_hbd.halfband_decim.acc.addend[30:0] +@28 +test_hbd.halfband_decim.acc.reset +@420 +test_hbd.halfband_decim.acc.sum[33:0] +test_hbd.halfband_decim.mult.x[15:0] +test_hbd.halfband_decim.mult.y[15:0] +@28 +test_hbd.halfband_decim.acc.clear +test_hbd.strobe_in +test_hbd.strobe_out +test_hbd.halfband_decim.acc_en +@420 +test_hbd.i_out[15:0] +@28 +test_hbd.halfband_decim.mult_en +test_hbd.halfband_decim.latch_result +@420 +test_hbd.halfband_decim.sum[15:0] +test_hbd.halfband_decim.sum_even[33:0] +test_hbd.halfband_decim.dout[33:0] +test_hbd.halfband_decim.data_out[15:0] +@22 +test_hbd.halfband_decim.data_out[15:0] +@28 +test_hbd.halfband_decim.dout[33:0] +@29 +test_hbd.halfband_decim.acc_en +@22 +test_hbd.halfband_decim.base_addr[3:0] +@28 +test_hbd.halfband_decim.clear +test_hbd.halfband_decim.latch_result +test_hbd.halfband_decim.mult_en +test_hbd.halfband_decim.mult_en_pre +@22 +test_hbd.halfband_decim.phase[3:0] +@28 +test_hbd.halfband_decim.start +test_hbd.halfband_decim.start_d1 +test_hbd.halfband_decim.start_d2 +test_hbd.halfband_decim.start_d3 +test_hbd.halfband_decim.start_d4 +test_hbd.halfband_decim.start_d5 +test_hbd.halfband_decim.start_d6 +test_hbd.halfband_decim.start_d7 +test_hbd.halfband_decim.start_d8 +test_hbd.halfband_decim.start_d9 +test_hbd.halfband_decim.start_dA +test_hbd.halfband_decim.start_dB +test_hbd.halfband_decim.start_dC +test_hbd.halfband_decim.start_dD +test_hbd.halfband_decim.store_odd +test_hbd.halfband_decim.strobe_in +test_hbd.halfband_decim.strobe_out diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/really_golden b/usrp/fpga/sdr_lib/hb/hbd_tb/really_golden new file mode 100644 index 00000000..2d24a9e1 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/hbd_tb/really_golden @@ -0,0 +1,142 @@ +VCD info: dumpfile test_hbd.vcd opened for output. + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8192 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +- 4 + 18 +- 63 + 167 +- 367 + 737 +- 1539 + 5146 + 5146 +- 1539 + 737 +- 367 + 167 +- 63 + 18 +- 4 + 0 + 0 + 0 + 0 + 0 +- 4 + 14 +- 49 + 118 +- 249 + 488 + 7141 +12287 +17433 +15894 +16631 +16264 +16432 +16368 +16387 +16383 +16383 +16383 +16383 +16383 +16387 +16368 +16432 +16264 +16631 +15894 + 9241 + 4095 +- 1051 + 488 +- 249 + 118 +- 49 + 14 +- 4 + 0 + 0 + 0 + 0 + 0 +- 4 + 14 +- 49 + 118 +- 249 + 488 +- 1051 +12287 +17433 +15894 +16631 +16264 +16432 +16368 +16387 +16383 +16383 +16383 +16383 +16383 +16387 +16368 +16432 +16264 +16631 +15894 +17433 + 4095 +- 1051 + 488 +- 249 + 118 +- 49 + 14 +- 4 + 0 + 0 + 0 + 0 diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/regression b/usrp/fpga/sdr_lib/hb/hbd_tb/regression new file mode 100644 index 00000000..fc279c2f --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/hbd_tb/regression @@ -0,0 +1,95 @@ +echo "Baseline 1000" +iverilog -y .. -o test_hbd -DRATE=1000 test_hbd.v ; ./test_hbd >golden +diff golden really_golden + +echo +echo "Test 100" +iverilog -y .. -o test_hbd -DRATE=100 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 50" +iverilog -y .. -o test_hbd -DRATE=50 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 40" +iverilog -y .. -o test_hbd -DRATE=40 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 30" +iverilog -y .. -o test_hbd -DRATE=30 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 25" +iverilog -y .. -o test_hbd -DRATE=25 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 20" +iverilog -y .. -o test_hbd -DRATE=20 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 19" +iverilog -y .. -o test_hbd -DRATE=19 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 18" +iverilog -y .. -o test_hbd -DRATE=18 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 17" +iverilog -y .. -o test_hbd -DRATE=17 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 16" +iverilog -y .. -o test_hbd -DRATE=16 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 15" +iverilog -y .. -o test_hbd -DRATE=15 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 14" +iverilog -y .. -o test_hbd -DRATE=14 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 13" +iverilog -y .. -o test_hbd -DRATE=13 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 12" +iverilog -y .. -o test_hbd -DRATE=12 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 11" +iverilog -y .. -o test_hbd -DRATE=11 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 10" +iverilog -y .. -o test_hbd -DRATE=10 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 9" +iverilog -y .. -o test_hbd -DRATE=9 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 8" +iverilog -y .. -o test_hbd -DRATE=8 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 7" +iverilog -y .. -o test_hbd -DRATE=7 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 6" +iverilog -y .. -o test_hbd -DRATE=6 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 5" +iverilog -y .. -o test_hbd -DRATE=5 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 4" +iverilog -y .. -o test_hbd -DRATE=4 test_hbd.v ; ./test_hbd >output ; diff output golden + +echo +echo "Test 3" +iverilog -y .. -o test_hbd -DRATE=3 test_hbd.v ; ./test_hbd >output ; diff output golden diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd b/usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd new file mode 100755 index 00000000..b8aec757 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd @@ -0,0 +1,4 @@ +#!/bin/sh + +iverilog -y .. -o test_hbd test_hbd.v +./test_hbd diff --git a/usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v b/usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v new file mode 100644 index 00000000..01ab5e7e --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v @@ -0,0 +1,75 @@ + + +module test_hbd(); + + reg clock; + initial clock = 1'b0; + always #5 clock <= ~clock; + + reg reset; + initial reset = 1'b1; + initial #1000 reset = 1'b0; + + initial $dumpfile("test_hbd.vcd"); + initial $dumpvars(0,test_hbd); + + reg [15:0] i_in, q_in; + wire [15:0] i_out, q_out; + + reg strobe_in; + wire strobe_out; + reg coeff_write; + reg [15:0] coeff_data; + reg [4:0] coeff_addr; + + halfband_decim halfband_decim + ( .clock(clock),.reset(reset),.enable(),.strobe_in(strobe_in),.strobe_out(strobe_out), + .data_in(i_in),.data_out(i_out) ); + + always @(posedge strobe_out) + if(i_out[15]) + $display("-%d",65536-i_out); + else + $display("%d",i_out); + + initial + begin + strobe_in = 1'b0; + @(negedge reset); + @(posedge clock); + while(1) + begin + strobe_in <= #1 1'b1; + @(posedge clock); + strobe_in <= #1 1'b0; + repeat (`RATE) + @(posedge clock); + end + end + + initial #10000000 $finish; // Just in case... + + initial + begin + i_in <= #1 16'd0; + repeat (40) @(posedge strobe_in); + i_in <= #1 16'd16384; + @(posedge strobe_in); + i_in <= #1 16'd0; + repeat (40) @(posedge strobe_in); + i_in <= #1 16'd16384; + @(posedge strobe_in); + i_in <= #1 16'd0; + repeat (40) @(posedge strobe_in); + i_in <= #1 16'd16384; + repeat (40) @(posedge strobe_in); + i_in <= #1 16'd0; + repeat (41) @(posedge strobe_in); + i_in <= #1 16'd16384; + repeat (40) @(posedge strobe_in); + i_in <= #1 16'd0; + repeat (40) @(posedge strobe_in); + repeat (7) @(posedge clock); + $finish; + end // initial begin +endmodule // test_hb diff --git a/usrp/fpga/sdr_lib/hb/mac.v b/usrp/fpga/sdr_lib/hb/mac.v new file mode 100644 index 00000000..5a270bc7 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/mac.v @@ -0,0 +1,58 @@ + + +module mac (input clock, input reset, input enable, input clear, + input signed [15:0] x, input signed [15:0] y, + input [7:0] shift, output [15:0] z ); + + reg signed [30:0] product; + reg signed [39:0] z_int; + reg signed [15:0] z_shift; + + reg enable_d1; + always @(posedge clock) + enable_d1 <= #1 enable; + + always @(posedge clock) + if(reset | clear) + z_int <= #1 40'd0; + else if(enable_d1) + z_int <= #1 z_int + {{9{product[30]}},product}; + + always @(posedge clock) + product <= #1 x*y; + + always @* // FIXME full case? parallel case? + case(shift) + //8'd0 : z_shift <= z_int[39:24]; + //8'd1 : z_shift <= z_int[38:23]; + //8'd2 : z_shift <= z_int[37:22]; + //8'd3 : z_shift <= z_int[36:21]; + //8'd4 : z_shift <= z_int[35:20]; + //8'd5 : z_shift <= z_int[34:19]; + 8'd6 : z_shift <= z_int[33:18]; + 8'd7 : z_shift <= z_int[32:17]; + 8'd8 : z_shift <= z_int[31:16]; + 8'd9 : z_shift <= z_int[30:15]; + 8'd10 : z_shift <= z_int[29:14]; + 8'd11 : z_shift <= z_int[28:13]; + //8'd12 : z_shift <= z_int[27:12]; + //8'd13 : z_shift <= z_int[26:11]; + //8'd14 : z_shift <= z_int[25:10]; + //8'd15 : z_shift <= z_int[24:9]; + //8'd16 : z_shift <= z_int[23:8]; + //8'd17 : z_shift <= z_int[22:7]; + //8'd18 : z_shift <= z_int[21:6]; + //8'd19 : z_shift <= z_int[20:5]; + //8'd20 : z_shift <= z_int[19:4]; + //8'd21 : z_shift <= z_int[18:3]; + //8'd22 : z_shift <= z_int[17:2]; + //8'd23 : z_shift <= z_int[16:1]; + //8'd24 : z_shift <= z_int[15:0]; + default : z_shift <= z_int[15:0]; + endcase // case(shift) + + // FIXME do we need to saturate? + //assign z = z_shift; + assign z = z_int[15:0]; + +endmodule // mac diff --git a/usrp/fpga/sdr_lib/hb/mult.v b/usrp/fpga/sdr_lib/hb/mult.v new file mode 100644 index 00000000..a8d4cb1b --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/mult.v @@ -0,0 +1,16 @@ + + +module mult (input clock, input signed [15:0] x, input signed [15:0] y, output reg signed [30:0] product, + input enable_in, output reg enable_out ); + + always @(posedge clock) + if(enable_in) + product <= #1 x*y; + else + product <= #1 31'd0; + + always @(posedge clock) + enable_out <= #1 enable_in; + +endmodule // mult + diff --git a/usrp/fpga/sdr_lib/hb/ram16_2port.v b/usrp/fpga/sdr_lib/hb/ram16_2port.v new file mode 100644 index 00000000..e1761a92 --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/ram16_2port.v @@ -0,0 +1,22 @@ + + +module ram16_2port (input clock, input write, + input [3:0] wr_addr, input [15:0] wr_data, + input [3:0] rd_addr1, output reg [15:0] rd_data1, + input [3:0] rd_addr2, output reg [15:0] rd_data2); + + reg [15:0] ram_array [0:31]; + + always @(posedge clock) + rd_data1 <= #1 ram_array[rd_addr1]; + + always @(posedge clock) + rd_data2 <= #1 ram_array[rd_addr2]; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + +endmodule // ram16_2port + + diff --git a/usrp/fpga/sdr_lib/hb/ram16_2sum.v b/usrp/fpga/sdr_lib/hb/ram16_2sum.v new file mode 100644 index 00000000..559b06fd --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/ram16_2sum.v @@ -0,0 +1,27 @@ + + +module ram16_2sum (input clock, input write, + input [3:0] wr_addr, input [15:0] wr_data, + input [3:0] rd_addr1, input [3:0] rd_addr2, + output reg [15:0] sum); + + reg signed [15:0] ram_array [0:15]; + reg signed [15:0] a,b; + wire signed [16:0] sum_int; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + + always @(posedge clock) + begin + a <= #1 ram_array[rd_addr1]; + b <= #1 ram_array[rd_addr2]; + end + + assign sum_int = {a[15],a} + {b[15],b}; + + always @(posedge clock) + sum <= #1 sum_int[16:1] + (sum_int[16]&sum_int[0]); + +endmodule // ram16_2sum diff --git a/usrp/fpga/sdr_lib/hb/ram32_2sum.v b/usrp/fpga/sdr_lib/hb/ram32_2sum.v new file mode 100644 index 00000000..d1f55b7d --- /dev/null +++ b/usrp/fpga/sdr_lib/hb/ram32_2sum.v @@ -0,0 +1,22 @@ + + +module ram32_2sum (input clock, input write, + input [4:0] wr_addr, input [15:0] wr_data, + input [4:0] rd_addr1, input [4:0] rd_addr2, + output reg [15:0] sum); + + reg [15:0] ram_array [0:31]; + wire [16:0] sum_int; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + + assign sum_int = ram_array[rd_addr1] + ram_array[rd_addr2]; + + always @(posedge clock) + sum <= #1 sum_int[16:1] + (sum_int[16]&sum_int[0]); + + +endmodule // ram32_2sum + diff --git a/usrp/fpga/sdr_lib/io_pins.v b/usrp/fpga/sdr_lib/io_pins.v new file mode 100644 index 00000000..da20b3b0 --- /dev/null +++ b/usrp/fpga/sdr_lib/io_pins.v @@ -0,0 +1,52 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2005,2006 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +`include "../../firmware/include/fpga_regs_common.v" +`include "../../firmware/include/fpga_regs_standard.v" + +module io_pins + ( inout wire [15:0] io_0, inout wire [15:0] io_1, inout wire [15:0] io_2, inout wire [15:0] io_3, + input wire [15:0] reg_0, input wire [15:0] reg_1, input wire [15:0] reg_2, input wire [15:0] reg_3, + input clock, input rx_reset, input tx_reset, + input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe); + + reg [15:0] io_0_oe,io_1_oe,io_2_oe,io_3_oe; + + bidir_reg bidir_reg_0 (.tristate(io_0),.oe(io_0_oe),.reg_val(reg_0)); + bidir_reg bidir_reg_1 (.tristate(io_1),.oe(io_1_oe),.reg_val(reg_1)); + bidir_reg bidir_reg_2 (.tristate(io_2),.oe(io_2_oe),.reg_val(reg_2)); + bidir_reg bidir_reg_3 (.tristate(io_3),.oe(io_3_oe),.reg_val(reg_3)); + + // Upper 16 bits are mask for lower 16 + always @(posedge clock) + if(serial_strobe) + case(serial_addr) + `FR_OE_0 : io_0_oe + <= #1 (io_0_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + `FR_OE_1 : io_1_oe + <= #1 (io_1_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + `FR_OE_2 : io_2_oe + <= #1 (io_2_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + `FR_OE_3 : io_3_oe + <= #1 (io_3_oe & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + endcase // case(serial_addr) + +endmodule // io_pins diff --git a/usrp/fpga/sdr_lib/master_control.v b/usrp/fpga/sdr_lib/master_control.v new file mode 100644 index 00000000..d42817c7 --- /dev/null +++ b/usrp/fpga/sdr_lib/master_control.v @@ -0,0 +1,155 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003,2005 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Clock, enable, and reset controls for whole system + +module master_control + ( input master_clk, input usbclk, + input wire [6:0] serial_addr, input wire [31:0] serial_data, input wire serial_strobe, + output tx_bus_reset, output rx_bus_reset, + output wire tx_dsp_reset, output wire rx_dsp_reset, + output wire enable_tx, output wire enable_rx, + output wire [7:0] interp_rate, output wire [7:0] decim_rate, + output tx_sample_strobe, output strobe_interp, + output rx_sample_strobe, output strobe_decim, + input tx_empty, + input wire [15:0] debug_0,input wire [15:0] debug_1,input wire [15:0] debug_2,input wire [15:0] debug_3, + output wire [15:0] reg_0, output wire [15:0] reg_1, output wire [15:0] reg_2, output wire [15:0] reg_3 + ); + + // FIXME need a separate reset for all control settings + // Master Controls assignments + wire [7:0] master_controls; + setting_reg #(`FR_MASTER_CTRL) sr_mstr_ctrl(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(master_controls)); + assign enable_tx = master_controls[0]; + assign enable_rx = master_controls[1]; + assign tx_dsp_reset = master_controls[2]; + assign rx_dsp_reset = master_controls[3]; + // Unused - 4-7 + + // Strobe Generators + setting_reg #(`FR_INTERP_RATE) sr_interp(.clock(master_clk),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(interp_rate)); + setting_reg #(`FR_DECIM_RATE) sr_decim(.clock(master_clk),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(decim_rate)); + + strobe_gen da_strobe_gen + ( .clock(master_clk),.reset(tx_dsp_reset),.enable(enable_tx), + .rate(8'd1),.strobe_in(1'b1),.strobe(tx_sample_strobe) ); + + strobe_gen tx_strobe_gen + ( .clock(master_clk),.reset(tx_dsp_reset),.enable(enable_tx), + .rate(interp_rate),.strobe_in(tx_sample_strobe),.strobe(strobe_interp) ); + + assign rx_sample_strobe = 1'b1; + + strobe_gen decim_strobe_gen + ( .clock(master_clk),.reset(rx_dsp_reset),.enable(enable_rx), + .rate(decim_rate),.strobe_in(rx_sample_strobe),.strobe(strobe_decim) ); + + // Reset syncs for bus (usbclk) side + // The RX bus side reset isn't used, the TX bus side one may not be needed + reg tx_reset_bus_sync1, rx_reset_bus_sync1, tx_reset_bus_sync2, rx_reset_bus_sync2; + + always @(posedge usbclk) + begin + tx_reset_bus_sync1 <= #1 tx_dsp_reset; + rx_reset_bus_sync1 <= #1 rx_dsp_reset; + tx_reset_bus_sync2 <= #1 tx_reset_bus_sync1; + rx_reset_bus_sync2 <= #1 rx_reset_bus_sync1; + end + + assign tx_bus_reset = tx_reset_bus_sync2; + assign rx_bus_reset = rx_reset_bus_sync2; + + wire [7:0] txa_refclk, rxa_refclk, txb_refclk, rxb_refclk; + wire txaclk,txbclk,rxaclk,rxbclk; + wire [3:0] debug_en, txcvr_ctrl; + + wire [31:0] txcvr_rxlines, txcvr_txlines; + + setting_reg #(`FR_TX_A_REFCLK) sr_txaref(.clock(master_clk),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(txa_refclk)); + setting_reg #(`FR_RX_A_REFCLK) sr_rxaref(.clock(master_clk),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(rxa_refclk)); + setting_reg #(`FR_TX_B_REFCLK) sr_txbref(.clock(master_clk),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(txb_refclk)); + setting_reg #(`FR_RX_B_REFCLK) sr_rxbref(.clock(master_clk),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(rxb_refclk)); + + setting_reg #(`FR_DEBUG_EN) sr_debugen(.clock(master_clk),.reset(rx_dsp_reset|tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(debug_en)); + + clk_divider clk_div_0 (.reset(tx_dsp_reset),.in_clk(master_clk),.out_clk(txaclk),.ratio(txa_refclk[6:0])); + clk_divider clk_div_1 (.reset(rx_dsp_reset),.in_clk(master_clk),.out_clk(rxaclk),.ratio(rxa_refclk[6:0])); + clk_divider clk_div_2 (.reset(tx_dsp_reset),.in_clk(master_clk),.out_clk(txbclk),.ratio(txb_refclk[6:0])); + clk_divider clk_div_3 (.reset(rx_dsp_reset),.in_clk(master_clk),.out_clk(rxbclk),.ratio(rxb_refclk[6:0])); + + reg [15:0] io_0_reg,io_1_reg,io_2_reg,io_3_reg; + // Upper 16 bits are mask for lower 16 + always @(posedge master_clk) + if(serial_strobe) + case(serial_addr) + `FR_IO_0 : io_0_reg + <= #1 (io_0_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + `FR_IO_1 : io_1_reg + <= #1 (io_1_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + `FR_IO_2 : io_2_reg + <= #1 (io_2_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + `FR_IO_3 : io_3_reg + <= #1 (io_3_reg & ~serial_data[31:16]) | (serial_data[15:0] & serial_data[31:16] ); + endcase // case(serial_addr) + + wire transmit_now = !tx_empty & enable_tx; + wire atr_ctl; + wire [15:0] atr_mask_0, atr_txval_0, atr_rxval_0, atr_mask_1, atr_txval_1, atr_rxval_1, atr_mask_2, atr_txval_2, atr_rxval_2, atr_mask_3, atr_txval_3, atr_rxval_3; + + setting_reg #(`FR_ATR_MASK_0) sr_atr_mask_0(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_0)); + setting_reg #(`FR_ATR_TXVAL_0) sr_atr_txval_0(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_0)); + setting_reg #(`FR_ATR_RXVAL_0) sr_atr_rxval_0(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_0)); + + setting_reg #(`FR_ATR_MASK_1) sr_atr_mask_1(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_1)); + setting_reg #(`FR_ATR_TXVAL_1) sr_atr_txval_1(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_1)); + setting_reg #(`FR_ATR_RXVAL_1) sr_atr_rxval_1(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_1)); + + setting_reg #(`FR_ATR_MASK_2) sr_atr_mask_2(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_2)); + setting_reg #(`FR_ATR_TXVAL_2) sr_atr_txval_2(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_2)); + setting_reg #(`FR_ATR_RXVAL_2) sr_atr_rxval_2(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_2)); + + setting_reg #(`FR_ATR_MASK_3) sr_atr_mask_3(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_mask_3)); + setting_reg #(`FR_ATR_TXVAL_3) sr_atr_txval_3(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_txval_3)); + setting_reg #(`FR_ATR_RXVAL_3) sr_atr_rxval_3(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_rxval_3)); + + //setting_reg #(`FR_ATR_CTL) sr_atr_ctl(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(atr_ctl)); + assign atr_ctl = 1'b1; + + wire [15:0] atr_selected_0 = transmit_now ? atr_txval_0 : atr_rxval_0; + wire [15:0] io_0 = ({{16{atr_ctl}}} & atr_mask_0 & atr_selected_0) | (~({{16{atr_ctl}}} & atr_mask_0) & io_0_reg); + + wire [15:0] atr_selected_1 = transmit_now ? atr_txval_1 : atr_rxval_1; + wire [15:0] io_1 = ({{16{atr_ctl}}} & atr_mask_1 & atr_selected_1) | (~({{16{atr_ctl}}} & atr_mask_1) & io_1_reg); + + wire [15:0] atr_selected_2 = transmit_now ? atr_txval_2 : atr_rxval_2; + wire [15:0] io_2 = ({{16{atr_ctl}}} & atr_mask_2 & atr_selected_2) | (~({{16{atr_ctl}}} & atr_mask_2) & io_2_reg); + + wire [15:0] atr_selected_3 = transmit_now ? atr_txval_3 : atr_rxval_3; + wire [15:0] io_3 = ({{16{atr_ctl}}} & atr_mask_3 & atr_selected_3) | (~({{16{atr_ctl}}} & atr_mask_3) & io_3_reg); + + assign reg_0 = debug_en[0] ? debug_0 : txa_refclk[7] ? {io_0[15:1],txaclk} : io_0; + assign reg_1 = debug_en[1] ? debug_1 : rxa_refclk[7] ? {io_1[15:1],rxaclk} : io_1; + assign reg_2 = debug_en[2] ? debug_2 : txb_refclk[7] ? {io_2[15:1],txbclk} : io_2; + assign reg_3 = debug_en[3] ? debug_3 : rxb_refclk[7] ? {io_3[15:1],rxbclk} : io_3; + + +endmodule // master_control diff --git a/usrp/fpga/sdr_lib/master_control_multi.v b/usrp/fpga/sdr_lib/master_control_multi.v new file mode 100644 index 00000000..af1e0b1f --- /dev/null +++ b/usrp/fpga/sdr_lib/master_control_multi.v @@ -0,0 +1,73 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +`include "usrp_multi.vh" +`include "../../../firmware/include/fpga_regs_common.v" +`include "../../../firmware/include/fpga_regs_standard.v" +// Clock, enable, and reset controls for whole system +// Modified version to enable multi_usrp synchronisation + +module master_control_multi + ( input master_clk, input usbclk, + input wire [6:0] serial_addr, input wire [31:0] serial_data, input wire serial_strobe, + input wire rx_slave_sync, + output tx_bus_reset, output rx_bus_reset, + output wire tx_dsp_reset, output wire rx_dsp_reset, + output wire enable_tx, output wire enable_rx, + output wire sync_rx, + output wire [7:0] interp_rate, output wire [7:0] decim_rate, + output tx_sample_strobe, output strobe_interp, + output rx_sample_strobe, output strobe_decim, + input tx_empty, + input wire [15:0] debug_0,input wire [15:0] debug_1,input wire [15:0] debug_2,input wire [15:0] debug_3, + output wire [15:0] reg_0, output wire [15:0] reg_1, output wire [15:0] reg_2, output wire [15:0] reg_3 + ); + + wire [15:0] reg_1_std; + + master_control master_control_standard + ( .master_clk(master_clk),.usbclk(usbclk), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .tx_bus_reset(tx_bus_reset),.rx_bus_reset(rx_bus_reset), + .tx_dsp_reset(tx_dsp_reset),.rx_dsp_reset(rx_dsp_reset), + .enable_tx(enable_tx),.enable_rx(enable_rx), + .interp_rate(interp_rate),.decim_rate(decim_rate), + .tx_sample_strobe(tx_sample_strobe),.strobe_interp(strobe_interp), + .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim), + .tx_empty(tx_empty), + .debug_0(debug_0),.debug_1(debug_1), + .debug_2(debug_2),.debug_3(debug_3), + .reg_0(reg_0),.reg_1(reg_1_std),.reg_2(reg_2),.reg_3(reg_3) ); + + // FIXME need a separate reset for all control settings + // Master/slave Controls assignments + wire [7:0] rx_master_slave_controls; + setting_reg_masked #(`FR_RX_MASTER_SLAVE) sr_rx_mstr_slv_ctrl(.clock(master_clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(rx_master_slave_controls)); + + assign sync_rx = rx_master_slave_controls[`bitnoFR_RX_SYNC] | (rx_master_slave_controls[`bitnoFR_RX_SYNC_SLAVE] & rx_slave_sync); + //sync if we are told by master_control or if we get a hardware slave sync + //TODO There can be a one sample difference between master and slave sync. + // Maybe use a register for sync_rx which uses the (neg or pos) edge of master_clock and/or rx_slave_sync to trigger + // Or even use a seperate sync_rx_out and sync_rx_internal (which lags behind) + //TODO make output pin not hardwired +assign reg_1 ={(rx_master_slave_controls[`bitnoFR_RX_SYNC_MASTER])? sync_rx:reg_1_std[15],reg_1_std[14:0]}; + + +endmodule // master_control diff --git a/usrp/fpga/sdr_lib/phase_acc.v b/usrp/fpga/sdr_lib/phase_acc.v new file mode 100755 index 00000000..d00716fd --- /dev/null +++ b/usrp/fpga/sdr_lib/phase_acc.v @@ -0,0 +1,52 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +// Basic Phase accumulator for DDS + + +module phase_acc (clk,reset,enable,strobe,serial_addr,serial_data,serial_strobe,phase); + parameter FREQADDR = 0; + parameter PHASEADDR = 0; + parameter resolution = 32; + + input clk, reset, enable, strobe; + input [6:0] serial_addr; + input [31:0] serial_data; + input serial_strobe; + + output reg [resolution-1:0] phase; + wire [resolution-1:0] freq; + + setting_reg #(FREQADDR) sr_rxfreq0(.clock(clk),.reset(1'b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(freq)); + + always @(posedge clk) + if(reset) + phase <= #1 32'b0; + else if(serial_strobe & (serial_addr == PHASEADDR)) + phase <= #1 serial_data; + else if(enable & strobe) + phase <= #1 phase + freq; + +endmodule // phase_acc + + diff --git a/usrp/fpga/sdr_lib/ram.v b/usrp/fpga/sdr_lib/ram.v new file mode 100644 index 00000000..fb64cdea --- /dev/null +++ b/usrp/fpga/sdr_lib/ram.v @@ -0,0 +1,16 @@ + + +module ram (input clock, input write, + input [4:0] wr_addr, input [15:0] wr_data, + input [4:0] rd_addr, output reg [15:0] rd_data); + + reg [15:0] ram_array [0:31]; + + always @(posedge clock) + rd_data <= #1 ram_array[rd_addr]; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + +endmodule // ram diff --git a/usrp/fpga/sdr_lib/ram16.v b/usrp/fpga/sdr_lib/ram16.v new file mode 100644 index 00000000..0c93da2b --- /dev/null +++ b/usrp/fpga/sdr_lib/ram16.v @@ -0,0 +1,17 @@ + + +module ram16 (input clock, input write, + input [3:0] wr_addr, input [15:0] wr_data, + input [3:0] rd_addr, output reg [15:0] rd_data); + + reg [15:0] ram_array [0:15]; + + always @(posedge clock) + rd_data <= #1 ram_array[rd_addr]; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + +endmodule // ram16 + diff --git a/usrp/fpga/sdr_lib/ram32.v b/usrp/fpga/sdr_lib/ram32.v new file mode 100644 index 00000000..064e2735 --- /dev/null +++ b/usrp/fpga/sdr_lib/ram32.v @@ -0,0 +1,17 @@ + + +module ram32 (input clock, input write, + input [4:0] wr_addr, input [15:0] wr_data, + input [4:0] rd_addr, output reg [15:0] rd_data); + + reg [15:0] ram_array [0:31]; + + always @(posedge clock) + rd_data <= #1 ram_array[rd_addr]; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + +endmodule // ram32 + diff --git a/usrp/fpga/sdr_lib/ram64.v b/usrp/fpga/sdr_lib/ram64.v new file mode 100644 index 00000000..08454580 --- /dev/null +++ b/usrp/fpga/sdr_lib/ram64.v @@ -0,0 +1,16 @@ + + +module ram64 (input clock, input write, + input [5:0] wr_addr, input [15:0] wr_data, + input [5:0] rd_addr, output reg [15:0] rd_data); + + reg [15:0] ram_array [0:63]; + + always @(posedge clock) + rd_data <= #1 ram_array[rd_addr]; + + always @(posedge clock) + if(write) + ram_array[wr_addr] <= #1 wr_data; + +endmodule // ram64 diff --git a/usrp/fpga/sdr_lib/rssi.v b/usrp/fpga/sdr_lib/rssi.v new file mode 100644 index 00000000..e45e2148 --- /dev/null +++ b/usrp/fpga/sdr_lib/rssi.v @@ -0,0 +1,30 @@ + + +module rssi (input clock, input reset, input enable, + input [11:0] adc, output [15:0] rssi, output [15:0] over_count); + + wire over_hi = (adc == 12'h7FF); + wire over_lo = (adc == 12'h800); + wire over = over_hi | over_lo; + + reg [25:0] over_count_int; + always @(posedge clock) + if(reset | ~enable) + over_count_int <= #1 26'd0; + else + over_count_int <= #1 over_count_int + (over ? 26'd65535 : 26'd0) - over_count_int[25:10]; + + assign over_count = over_count_int[25:10]; + + wire [11:0] abs_adc = adc[11] ? ~adc : adc; + + reg [25:0] rssi_int; + always @(posedge clock) + if(reset | ~enable) + rssi_int <= #1 26'd0; + else + rssi_int <= #1 rssi_int + abs_adc - rssi_int[25:10]; + + assign rssi = rssi_int[25:10]; + +endmodule // rssi diff --git a/usrp/fpga/sdr_lib/rx_buffer.v b/usrp/fpga/sdr_lib/rx_buffer.v new file mode 100644 index 00000000..70c800e3 --- /dev/null +++ b/usrp/fpga/sdr_lib/rx_buffer.v @@ -0,0 +1,182 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Interface to Cypress FX2 bus +// A packet is 512 Bytes. Each fifo line is 2 bytes +// Fifo has 1024 or 2048 lines + +`include "../../firmware/include/fpga_regs_common.v" +`include "../../firmware/include/fpga_regs_standard.v" + +module rx_buffer + ( input usbclk, + input bus_reset, // Not used in RX + input reset, // DSP side reset (used here), do not reset registers + input reset_regs, //Only reset registers + output [15:0] usbdata, + input RD, + output wire have_pkt_rdy, + output reg rx_overrun, + input wire [3:0] channels, + input wire [15:0] ch_0, + input wire [15:0] ch_1, + input wire [15:0] ch_2, + input wire [15:0] ch_3, + input wire [15:0] ch_4, + input wire [15:0] ch_5, + input wire [15:0] ch_6, + input wire [15:0] ch_7, + input rxclk, + input rxstrobe, + input clear_status, + input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe, + output [15:0] debugbus + ); + + wire [15:0] fifodata, fifodata_8; + reg [15:0] fifodata_16; + + wire [11:0] rxfifolevel; + wire rx_empty, rx_full; + + wire bypass_hb, want_q; + wire [4:0] bitwidth; + wire [3:0] bitshift; + + setting_reg #(`FR_RX_FORMAT) sr_rxformat(.clock(rxclk),.reset(reset_regs), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({bypass_hb,want_q,bitwidth,bitshift})); + + // Receive FIFO (ADC --> USB) + + // 257 Bug Fix + reg [8:0] read_count; + always @(negedge usbclk) + if(bus_reset) + read_count <= #1 9'd0; + else if(RD & ~read_count[8]) + read_count <= #1 read_count + 9'd1; + else + read_count <= #1 RD ? read_count : 9'b0; + + // Detect overrun + always @(posedge rxclk) + if(reset) + rx_overrun <= 1'b0; + else if(rxstrobe & (store_next != 0)) + rx_overrun <= 1'b1; + else if(clear_status) + rx_overrun <= 1'b0; + + reg [3:0] store_next; + always @(posedge rxclk) + if(reset) + store_next <= #1 4'd0; + else if(rxstrobe & (store_next == 0)) + store_next <= #1 4'd1; + else if(~rx_full & (store_next == channels)) + store_next <= #1 4'd0; + else if(~rx_full & (bitwidth == 5'd8) & (store_next == (channels>>1))) + store_next <= #1 4'd0; + else if(~rx_full & (store_next != 0)) + store_next <= #1 store_next + 4'd1; + + assign fifodata = (bitwidth == 5'd8) ? fifodata_8 : fifodata_16; + + assign fifodata_8 = {round_8(top),round_8(bottom)}; + reg [15:0] top,bottom; + + function [7:0] round_8; + input [15:0] in_val; + + round_8 = in_val[15:8] + (in_val[15] & |in_val[7:0]); + endfunction // round_8 + + always @* + case(store_next) + 4'd1 : begin + bottom = ch_0; + top = ch_1; + end + 4'd2 : begin + bottom = ch_2; + top = ch_3; + end + 4'd3 : begin + bottom = ch_4; + top = ch_5; + end + 4'd4 : begin + bottom = ch_6; + top = ch_7; + end + default : begin + top = 16'hFFFF; + bottom = 16'hFFFF; + end + endcase // case(store_next) + + always @* + case(store_next) + 4'd1 : fifodata_16 = ch_0; + 4'd2 : fifodata_16 = ch_1; + 4'd3 : fifodata_16 = ch_2; + 4'd4 : fifodata_16 = ch_3; + 4'd5 : fifodata_16 = ch_4; + 4'd6 : fifodata_16 = ch_5; + 4'd7 : fifodata_16 = ch_6; + 4'd8 : fifodata_16 = ch_7; + default : fifodata_16 = 16'hFFFF; + endcase // case(store_next) + + fifo_4k rxfifo + ( .data ( fifodata ), + .wrreq (~rx_full & (store_next != 0)), + .wrclk ( rxclk ), + + .q ( usbdata ), + .rdreq ( RD & ~read_count[8] ), + .rdclk ( ~usbclk ), + + .aclr ( reset ), // This one is asynchronous, so we can use either reset + + .rdempty ( rx_empty ), + .rdusedw ( rxfifolevel ), + .wrfull ( rx_full ), + .wrusedw ( ) + ); + + assign have_pkt_rdy = (rxfifolevel >= 256); + + // Debugging Aids + assign debugbus[0] = RD; + assign debugbus[1] = rx_overrun; + assign debugbus[2] = read_count[8]; + assign debugbus[3] = rx_full; + assign debugbus[4] = rxstrobe; + assign debugbus[5] = usbclk; + assign debugbus[6] = have_pkt_rdy; + assign debugbus[10:7] = store_next; + //assign debugbus[15:11] = rxfifolevel[4:0]; + assign debugbus[15:11] = bitwidth; + +endmodule // rx_buffer + diff --git a/usrp/fpga/sdr_lib/rx_chain.v b/usrp/fpga/sdr_lib/rx_chain.v new file mode 100644 index 00000000..4031e6bf --- /dev/null +++ b/usrp/fpga/sdr_lib/rx_chain.v @@ -0,0 +1,105 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Following defines conditionally include RX path circuitry + +`include "usrp_std.vh" +module rx_chain + (input clock, + input reset, + input enable, + input wire [7:0] decim_rate, + input sample_strobe, + input decimator_strobe, + output wire hb_strobe, + input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe, + input wire [15:0] i_in, + input wire [15:0] q_in, + output wire [15:0] i_out, + output wire [15:0] q_out, + output wire [15:0] debugdata,output wire [15:0] debugctrl + ); + + parameter FREQADDR = 0; + parameter PHASEADDR = 0; + + wire [31:0] phase; + wire [15:0] bb_i, bb_q; + wire [15:0] hb_in_i, hb_in_q; + + assign debugdata = hb_in_i; + +`ifdef RX_NCO_ON + phase_acc #(FREQADDR,PHASEADDR,32) rx_phase_acc + (.clk(clock),.reset(reset),.enable(enable), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .strobe(sample_strobe),.phase(phase) ); + + cordic rx_cordic + ( .clock(clock),.reset(reset),.enable(enable), + .xi(i_in),.yi(q_in),.zi(phase[31:16]), + .xo(bb_i),.yo(bb_q),.zo() ); +`else + assign bb_i = i_in; + assign bb_q = q_in; + assign sample_strobe = 1; +`endif // !`ifdef RX_NCO_ON + +`ifdef RX_CIC_ON + cic_decim cic_decim_i_0 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe), + .signal_in(bb_i),.signal_out(hb_in_i) ); +`else + assign hb_in_i = bb_i; + assign decimator_strobe = sample_strobe; +`endif + +`ifdef RX_HB_ON + halfband_decim hbd_i_0 + ( .clock(clock),.reset(reset),.enable(enable), + .strobe_in(decimator_strobe),.strobe_out(hb_strobe), + .data_in(hb_in_i),.data_out(i_out),.debugctrl(debugctrl) ); +`else + assign i_out = hb_in_i; + assign hb_strobe = decimator_strobe; +`endif + +`ifdef RX_CIC_ON + cic_decim cic_decim_q_0 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe), + .signal_in(bb_q),.signal_out(hb_in_q) ); +`else + assign hb_in_q = bb_q; +`endif + +`ifdef RX_HB_ON + halfband_decim hbd_q_0 + ( .clock(clock),.reset(reset),.enable(enable), + .strobe_in(decimator_strobe),.strobe_out(), + .data_in(hb_in_q),.data_out(q_out) ); +`else + assign q_out = hb_in_q; +`endif + + +endmodule // rx_chain diff --git a/usrp/fpga/sdr_lib/rx_chain_dual.v b/usrp/fpga/sdr_lib/rx_chain_dual.v new file mode 100644 index 00000000..69885946 --- /dev/null +++ b/usrp/fpga/sdr_lib/rx_chain_dual.v @@ -0,0 +1,103 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +module rx_chain_dual + (input clock, + input clock_2x, + input reset, + input enable, + input wire [7:0] decim_rate, + input sample_strobe, + input decimator_strobe, + input wire [31:0] freq0, + input wire [15:0] i_in0, + input wire [15:0] q_in0, + output wire [15:0] i_out0, + output wire [15:0] q_out0, + input wire [31:0] freq1, + input wire [15:0] i_in1, + input wire [15:0] q_in1, + output wire [15:0] i_out1, + output wire [15:0] q_out1 + ); + + wire [15:0] phase; + wire [15:0] bb_i, bb_q; + wire [15:0] i_in, q_in; + + wire [31:0] phase0; + wire [31:0] phase1; + reg [15:0] bb_i0, bb_q0; + reg [15:0] bb_i1, bb_q1; + + // We want to time-share the CORDIC by double-clocking it + + phase_acc rx_phase_acc_0 + (.clk(clock),.reset(reset),.enable(enable), + .strobe(sample_strobe),.freq(freq0),.phase(phase0) ); + + phase_acc rx_phase_acc_1 + (.clk(clock),.reset(reset),.enable(enable), + .strobe(sample_strobe),.freq(freq1),.phase(phase1) ); + + assign phase = clock ? phase0[31:16] : phase1[31:16]; + assign i_in = clock ? i_in0 : i_in1; + assign q_in = clock ? q_in0 : q_in1; + +// This appears reversed because of the number of CORDIC stages + always @(posedge clock_2x) + if(clock) + begin + bb_i1 <= #1 bb_i; + bb_q1 <= #1 bb_q; + end + else + begin + bb_i0 <= #1 bb_i; + bb_q0 <= #1 bb_q; + end + + cordic rx_cordic + ( .clock(clock_2x),.reset(reset),.enable(enable), + .xi(i_in),.yi(q_in),.zi(phase), + .xo(bb_i),.yo(bb_q),.zo() ); + + cic_decim cic_decim_i_0 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe), + .signal_in(bb_i0),.signal_out(i_out0) ); + + cic_decim cic_decim_q_0 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe), + .signal_in(bb_q0),.signal_out(q_out0) ); + + cic_decim cic_decim_i_1 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe), + .signal_in(bb_i1),.signal_out(i_out1) ); + + cic_decim cic_decim_q_1 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(decim_rate),.strobe_in(sample_strobe),.strobe_out(decimator_strobe), + .signal_in(bb_q1),.signal_out(q_out1) ); + +endmodule // rx_chain diff --git a/usrp/fpga/sdr_lib/rx_dcoffset.v b/usrp/fpga/sdr_lib/rx_dcoffset.v new file mode 100644 index 00000000..3be475ed --- /dev/null +++ b/usrp/fpga/sdr_lib/rx_dcoffset.v @@ -0,0 +1,22 @@ + + +module rx_dcoffset (input clock, input enable, input reset, + input signed [15:0] adc_in, output signed [15:0] adc_out, + input wire [6:0] serial_addr, input wire [31:0] serial_data, input serial_strobe); + parameter MYADDR = 0; + + reg signed [31:0] integrator; + wire signed [15:0] scaled_integrator = integrator[31:16] + (integrator[31] & |integrator[15:0]); + assign adc_out = adc_in - scaled_integrator; + + // FIXME do we need signed? + //FIXME What do we do when clipping? + always @(posedge clock) + if(reset) + integrator <= #1 32'd0; + else if(serial_strobe & (MYADDR == serial_addr)) + integrator <= #1 {serial_data[15:0],16'd0}; + else if(enable) + integrator <= #1 integrator + adc_out; + +endmodule // rx_dcoffset diff --git a/usrp/fpga/sdr_lib/serial_io.v b/usrp/fpga/sdr_lib/serial_io.v new file mode 100644 index 00000000..1fe43c95 --- /dev/null +++ b/usrp/fpga/sdr_lib/serial_io.v @@ -0,0 +1,118 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003,2004 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +// Serial Control Bus from Cypress chip + +module serial_io + ( input master_clk, + input serial_clock, + input serial_data_in, + input enable, + input reset, + inout wire serial_data_out, + output reg [6:0] serial_addr, + output reg [31:0] serial_data, + output wire serial_strobe, + input wire [31:0] readback_0, + input wire [31:0] readback_1, + input wire [31:0] readback_2, + input wire [31:0] readback_3, + input wire [31:0] readback_4, + input wire [31:0] readback_5, + input wire [31:0] readback_6, + input wire [31:0] readback_7 + ); + + reg is_read; + reg [7:0] ser_ctr; + reg write_done; + + assign serial_data_out = is_read ? serial_data[31] : 1'bz; + + always @(posedge serial_clock, posedge reset, negedge enable) + if(reset) + ser_ctr <= #1 8'd0; + else if(~enable) + ser_ctr <= #1 8'd0; + else if(ser_ctr == 39) + ser_ctr <= #1 8'd0; + else + ser_ctr <= #1 ser_ctr + 8'd1; + + always @(posedge serial_clock, posedge reset, negedge enable) + if(reset) + is_read <= #1 1'b0; + else if(~enable) + is_read <= #1 1'b0; + else if((ser_ctr == 7)&&(serial_addr[6]==1)) + is_read <= #1 1'b1; + + always @(posedge serial_clock, posedge reset) + if(reset) + begin + serial_addr <= #1 7'b0; + serial_data <= #1 32'b0; + write_done <= #1 1'b0; + end + else if(~enable) + begin + //serial_addr <= #1 7'b0; + //serial_data <= #1 32'b0; + write_done <= #1 1'b0; + end + else + begin + if(~is_read && (ser_ctr == 39)) + write_done <= #1 1'b1; + else + write_done <= #1 1'b0; + if(is_read & (ser_ctr==8)) + case (serial_addr) + 7'd1: serial_data <= #1 readback_0; + 7'd2: serial_data <= #1 readback_1; + 7'd3: serial_data <= #1 readback_2; + 7'd4: serial_data <= #1 readback_3; + 7'd5: serial_data <= #1 readback_4; + 7'd6: serial_data <= #1 readback_5; + 7'd7: serial_data <= #1 readback_6; + 7'd8: serial_data <= #1 readback_7; + default: serial_data <= #1 32'd0; + endcase // case(serial_addr) + else if(ser_ctr >= 8) + serial_data <= #1 {serial_data[30:0],serial_data_in}; + else if(ser_ctr < 8) + serial_addr <= #1 {serial_addr[5:0],serial_data_in}; + end // else: !if(~enable) + + reg enable_d1, enable_d2; + always @(posedge master_clk) + begin + enable_d1 <= #1 enable; + enable_d2 <= #1 enable_d1; + end + + assign serial_strobe = enable_d2 & ~enable_d1; + +endmodule // serial_io + + diff --git a/usrp/fpga/sdr_lib/setting_reg.v b/usrp/fpga/sdr_lib/setting_reg.v new file mode 100644 index 00000000..3d31a9ef --- /dev/null +++ b/usrp/fpga/sdr_lib/setting_reg.v @@ -0,0 +1,23 @@ + + +module setting_reg + ( input clock, input reset, input strobe, input wire [6:0] addr, + input wire [31:0] in, output reg [31:0] out, output reg changed); + parameter my_addr = 0; + + always @(posedge clock) + if(reset) + begin + out <= #1 32'd0; + changed <= #1 1'b0; + end + else + if(strobe & (my_addr==addr)) + begin + out <= #1 in; + changed <= #1 1'b1; + end + else + changed <= #1 1'b0; + +endmodule // setting_reg diff --git a/usrp/fpga/sdr_lib/setting_reg_masked.v b/usrp/fpga/sdr_lib/setting_reg_masked.v new file mode 100644 index 00000000..72f7e21e --- /dev/null +++ b/usrp/fpga/sdr_lib/setting_reg_masked.v @@ -0,0 +1,26 @@ + + +module setting_reg_masked + ( input clock, input reset, input strobe, input wire [6:0] addr, + input wire [31:0] in, output reg [31:0] out, output reg changed); +/* upper 16 bits are mask, lower 16 bits are value + * Note that you get a 16 bit register, not a 32 bit one */ + + parameter my_addr = 0; + + always @(posedge clock) + if(reset) + begin + out <= #1 32'd0; + changed <= #1 1'b0; + end + else + if(strobe & (my_addr==addr)) + begin + out <= #1 (out & ~in[31:16]) | (in[15:0] & in[31:16] ); + changed <= #1 1'b1; + end + else + changed <= #1 1'b0; + +endmodule // setting_reg_masked diff --git a/usrp/fpga/sdr_lib/sign_extend.v b/usrp/fpga/sdr_lib/sign_extend.v new file mode 100644 index 00000000..2417909b --- /dev/null +++ b/usrp/fpga/sdr_lib/sign_extend.v @@ -0,0 +1,35 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +// Sign extension "macro" +// bits_out should be greater than bits_in + +module sign_extend (in,out); + parameter bits_in=0; // FIXME Quartus insists on a default + parameter bits_out=0; + + input [bits_in-1:0] in; + output [bits_out-1:0] out; + + assign out = {{(bits_out-bits_in){in[bits_in-1]}},in}; + +endmodule diff --git a/usrp/fpga/sdr_lib/strobe_gen.v b/usrp/fpga/sdr_lib/strobe_gen.v new file mode 100644 index 00000000..0511b6a1 --- /dev/null +++ b/usrp/fpga/sdr_lib/strobe_gen.v @@ -0,0 +1,44 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +module strobe_gen + ( input clock, + input reset, + input enable, + input [7:0] rate, + input strobe_in, + output wire strobe ); + +// parameter width = 8; + + reg [7:0] counter; + assign strobe = ~|counter && enable && strobe_in; + + always @(posedge clock) + if(reset | ~enable) + counter <= #1 8'd0; + else if(strobe_in) + if(counter == 0) + counter <= #1 rate; + else + counter <= #1 counter - 8'd1; + +endmodule // strobe_gen diff --git a/usrp/fpga/sdr_lib/tx_buffer.v b/usrp/fpga/sdr_lib/tx_buffer.v new file mode 100644 index 00000000..cae6607b --- /dev/null +++ b/usrp/fpga/sdr_lib/tx_buffer.v @@ -0,0 +1,138 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Interface to Cypress FX2 bus +// A packet is 512 Bytes. Each fifo line is 2 bytes +// Fifo has 1024 or 2048 lines + +module tx_buffer + ( input usbclk, + input bus_reset, // Used here for the 257-Hack to fix the FX2 bug + input reset, // standard DSP-side reset + input [15:0] usbdata, + input wire WR, + output wire have_space, + output reg tx_underrun, + input wire [3:0] channels, + output reg [15:0] tx_i_0, + output reg [15:0] tx_q_0, + output reg [15:0] tx_i_1, + output reg [15:0] tx_q_1, + output reg [15:0] tx_i_2, + output reg [15:0] tx_q_2, + output reg [15:0] tx_i_3, + output reg [15:0] tx_q_3, + input txclk, + input txstrobe, + input clear_status, + output wire tx_empty, + output [11:0] debugbus + ); + + wire [11:0] txfifolevel; + reg [8:0] write_count; + wire tx_full; + wire [15:0] fifodata; + wire rdreq; + + reg [3:0] load_next; + + // DAC Side of FIFO + assign rdreq = ((load_next != channels) & !tx_empty); + + always @(posedge txclk) + if(reset) + begin + {tx_i_0,tx_q_0,tx_i_1,tx_q_1,tx_i_2,tx_q_2,tx_i_3,tx_q_3} + <= #1 128'h0; + load_next <= #1 4'd0; + end + else + if((load_next != channels) & !tx_empty) + begin + load_next <= #1 load_next + 4'd1; + case(load_next) + 4'd0 : tx_i_0 <= #1 fifodata; + 4'd1 : tx_q_0 <= #1 fifodata; + 4'd2 : tx_i_1 <= #1 fifodata; + 4'd3 : tx_q_1 <= #1 fifodata; + 4'd4 : tx_i_2 <= #1 fifodata; + 4'd5 : tx_q_2 <= #1 fifodata; + 4'd6 : tx_i_3 <= #1 fifodata; + 4'd7 : tx_q_3 <= #1 fifodata; + endcase // case(load_next) + end // if ((load_next != channels) & !tx_empty) + else if(txstrobe & (load_next == channels)) + begin + load_next <= #1 4'd0; + end + + // USB Side of FIFO + assign have_space = (txfifolevel <= (4095-256)); + + always @(posedge usbclk) + if(bus_reset) // Use bus reset because this is on usbclk + write_count <= #1 0; + else if(WR & ~write_count[8]) + write_count <= #1 write_count + 9'd1; + else + write_count <= #1 WR ? write_count : 9'b0; + + // Detect Underruns + always @(posedge txclk) + if(reset) + tx_underrun <= 1'b0; + else if(txstrobe & (load_next != channels)) + tx_underrun <= 1'b1; + else if(clear_status) + tx_underrun <= 1'b0; + + // FIFO + fifo_4k txfifo + ( .data ( usbdata ), + .wrreq ( WR & ~write_count[8] ), + .wrclk ( usbclk ), + + .q ( fifodata ), + .rdreq ( rdreq ), + .rdclk ( txclk ), + + .aclr ( reset ), // asynch, so we can use either + + .rdempty ( tx_empty ), + .rdusedw ( ), + .wrfull ( tx_full ), + .wrusedw ( txfifolevel ) + ); + + // Debugging Aids + assign debugbus[0] = WR; + assign debugbus[1] = have_space; + assign debugbus[2] = tx_empty; + assign debugbus[3] = tx_full; + assign debugbus[4] = tx_underrun; + assign debugbus[5] = write_count[8]; + assign debugbus[6] = txstrobe; + assign debugbus[7] = rdreq; + assign debugbus[11:8] = load_next; + +endmodule // tx_buffer + diff --git a/usrp/fpga/sdr_lib/tx_chain.v b/usrp/fpga/sdr_lib/tx_chain.v new file mode 100644 index 00000000..8f0a17a5 --- /dev/null +++ b/usrp/fpga/sdr_lib/tx_chain.v @@ -0,0 +1,65 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +module tx_chain + (input clock, + input reset, + input enable, + input wire [7:0] interp_rate, + input sample_strobe, + input interpolator_strobe, + input wire [31:0] freq, + input wire [15:0] i_in, + input wire [15:0] q_in, + output wire [15:0] i_out, + output wire [15:0] q_out + ); + + wire [15:0] bb_i, bb_q; + + cic_interp cic_interp_i + ( .clock(clock),.reset(reset),.enable(enable), + .rate(interp_rate),.strobe_in(interpolator_strobe),.strobe_out(sample_strobe), + .signal_in(i_in),.signal_out(bb_i) ); + + cic_interp cic_interp_q + ( .clock(clock),.reset(reset),.enable(enable), + .rate(interp_rate),.strobe_in(interpolator_strobe),.strobe_out(sample_strobe), + .signal_in(q_in),.signal_out(bb_q) ); + +`define NOCORDIC_TX +`ifdef NOCORDIC_TX + assign i_out = bb_i; + assign q_out = bb_q; +`else + wire [31:0] phase; + + phase_acc phase_acc_tx + (.clk(clock),.reset(reset),.enable(enable), + .strobe(sample_strobe),.freq(freq),.phase(phase) ); + + cordic tx_cordic_0 + ( .clock(clock),.reset(reset),.enable(sample_strobe), + .xi(bb_i),.yi(bb_q),.zi(phase[31:16]), + .xo(i_out),.yo(q_out),.zo() ); +`endif + +endmodule // tx_chain diff --git a/usrp/fpga/sdr_lib/tx_chain_hb.v b/usrp/fpga/sdr_lib/tx_chain_hb.v new file mode 100644 index 00000000..6cbe29c0 --- /dev/null +++ b/usrp/fpga/sdr_lib/tx_chain_hb.v @@ -0,0 +1,76 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +module tx_chain_hb + (input clock, + input reset, + input enable, + input wire [7:0] interp_rate, + input sample_strobe, + input interpolator_strobe, + input hb_strobe, + input wire [31:0] freq, + input wire [15:0] i_in, + input wire [15:0] q_in, + output wire [15:0] i_out, + output wire [15:0] q_out, +output wire [15:0] debug, output [15:0] hb_i_out + ); +assign debug[15:13] = {sample_strobe,hb_strobe,interpolator_strobe}; + + wire [15:0] bb_i, bb_q; + wire [15:0] hb_i_out, hb_q_out; + + halfband_interp hb + (.clock(clock),.reset(reset),.enable(enable), + .strobe_in(interpolator_strobe),.strobe_out(hb_strobe), + .signal_in_i(i_in),.signal_in_q(q_in), + .signal_out_i(hb_i_out),.signal_out_q(hb_q_out), + .debug(debug[12:0])); + + cic_interp cic_interp_i + ( .clock(clock),.reset(reset),.enable(enable), + .rate(interp_rate),.strobe_in(hb_strobe),.strobe_out(sample_strobe), + .signal_in(hb_i_out),.signal_out(bb_i) ); + + cic_interp cic_interp_q + ( .clock(clock),.reset(reset),.enable(enable), + .rate(interp_rate),.strobe_in(hb_strobe),.strobe_out(sample_strobe), + .signal_in(hb_q_out),.signal_out(bb_q) ); + +`define NOCORDIC_TX +`ifdef NOCORDIC_TX + assign i_out = bb_i; + assign q_out = bb_q; +`else + wire [31:0] phase; + + phase_acc phase_acc_tx + (.clk(clock),.reset(reset),.enable(enable), + .strobe(sample_strobe),.freq(freq),.phase(phase) ); + + cordic tx_cordic_0 + ( .clock(clock),.reset(reset),.enable(sample_strobe), + .xi(bb_i),.yi(bb_q),.zi(phase[31:16]), + .xo(i_out),.yo(q_out),.zo() ); +`endif + +endmodule // tx_chain diff --git a/usrp/fpga/tb/cbus_tb.v b/usrp/fpga/tb/cbus_tb.v new file mode 100644 index 00000000..53cc1272 --- /dev/null +++ b/usrp/fpga/tb/cbus_tb.v @@ -0,0 +1,71 @@ +module cbus_tb; + +`define ch1in_freq 0 +`define ch2in_freq 1 +`define ch3in_freq 2 +`define ch4in_freq 3 +`define ch1out_freq 4 +`define ch2out_freq 5 +`define ch3out_freq 6 +`define ch4out_freq 7 +`define rates 8 +`define misc 9 + + task send_config_word; + input [7:0] addr; + input [31:0] data; + integer i; + + begin + #10 serenable = 1; + for(i=7;i>=0;i=i-1) + begin + #10 serdata = addr[i]; + #10 serclk = 0; + #10 serclk = 1; + #10 serclk = 0; + end + for(i=31;i>=0;i=i-1) + begin + #10 serdata = data[i]; + #10 serclk = 0; + #10 serclk = 1; + #10 serclk = 0; + end + #10 serenable = 0; + // #10 serclk = 1; + // #10 serclk = 0; + end + endtask // send_config_word + + initial $dumpfile("cbus_tb.vcd"); + initial $dumpvars(0,cbus_tb); + + initial reset = 1; + initial #500 reset = 0; + + reg serclk, serdata, serenable, reset; + wire SDO; + + control_bus control_bus + ( .serial_clock(serclk), + .serial_data_in(serdata), + .enable(serenable), + .reset(reset), + .serial_data_out(SDO) ); + + + initial + begin + #1000 send_config_word(8'd1,32'hDEAD_BEEF); + #1000 send_config_word(8'd3,32'hDDEE_FF01); + #1000 send_config_word(8'd19,32'hFFFF_FFFF); + #1000 send_config_word(8'd23,32'h1234_FEDC); + #1000 send_config_word(8'h80,32'h0); + #1000 send_config_word(8'h81,32'h0); + #1000 send_config_word(8'h82,32'h0); + #1000 reset = 1; + #1 $finish; + end + +endmodule // cbus_tb diff --git a/usrp/fpga/tb/cordic_tb.v b/usrp/fpga/tb/cordic_tb.v new file mode 100644 index 00000000..ed85b37b --- /dev/null +++ b/usrp/fpga/tb/cordic_tb.v @@ -0,0 +1,61 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +module cordic_tb(); + + cordic cordic(clk, reset, enable, xi, yi, zi, xo, yo, zo ); + + reg reset; + reg clk; + reg enable; + reg [15:0] xi, yi, zi; + + initial reset = 1'b1; + initial #1000 reset = 1'b0; + + initial clk = 1'b0; + always #50 clk <= ~clk; + + initial enable = 1'b1; + + initial zi = 16'b0; + + always @(posedge clk) + zi <= #1 zi + 16'd0; + + wire [15:0] xo,yo,zo; + + initial $dumpfile("cordic.vcd"); + initial $dumpvars(0,cordic_tb); + initial + begin +`include "sine.txt" + end + + wire [15:0] xiu = {~xi[15],xi[14:0]}; + wire [15:0] yiu = {~yi[15],yi[14:0]}; + wire [15:0] xou = {~xo[15],xo[14:0]}; + wire [15:0] you = {~yo[15],yo[14:0]}; + initial $monitor("%d\t%d\t%d\t%d\t%d",$time,xiu,yiu,xou,you); + +endmodule // cordic_tb diff --git a/usrp/fpga/tb/decim_tb.v b/usrp/fpga/tb/decim_tb.v new file mode 100644 index 00000000..ecf20cf4 --- /dev/null +++ b/usrp/fpga/tb/decim_tb.v @@ -0,0 +1,108 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +// testbench for fullchip + +module decim_tb(); + +`include "usrp_tasks.v" + + reg clk_120mhz; + reg usbclk; + reg reset; + + reg [11:0] adc1_data, adc2_data; + wire [13:0] dac1_data, dac2_data; + + wire [5:0] usbctl; + wire [5:0] usbrdy; + + wire [15:0] usbdata; + + reg WE, RD, OE; + + assign usbctl[0] = WE; + assign usbctl[1] = RD; + assign usbctl[2] = OE; + assign usbctl[5:3] = 0; + + reg tb_oe; + assign usbdata = tb_oe ? usbdatareg : 16'hxxxx; + reg serload, serenable, serclk, serdata; + reg enable_tx, enable_rx; + reg [15:0] usbdatareg; + +/////////////////////////////////////////////// +// Simulation Control +initial +begin + $dumpfile("decim_tb.vcd"); + $dumpvars(0, fc_tb); +end + +initial #100000 $finish; + +/////////////////////////////////////////////// +// Monitors + +reg [7:0] counter_decim; +wire [7:0] decim_rate; +assign decim_rate = 32; +initial $monitor(dac1_data); + + always @(posedge clk_120mhz) + begin + if(reset | ~enable_tx) + counter_decim <= #1 0; + else if(counter_decim == 0) + counter_decim <= #1 decim_rate - 8'b1; + else + counter_decim <= #1 counter_decim - 8'b1; + end + +/////////////////////////////////////////////// +// Clock and reset + +initial clk_120mhz = 0; +initial usbclk = 0; +always #48 clk_120mhz = ~clk_120mhz; +always #120 usbclk = ~usbclk; + +initial reset = 1'b1; +initial #500 reset = 1'b0; + + +initial enable_tx = 1'b1; + + wire [31:0] decim_out, q_decim_out; + wire [31:0] decim_out; + wire [31:0] phase; + + cic_decim #(.bitwidth(32),.stages(4)) + decim_i(.clock(clk_120mhz),.reset(reset),.enable(enable_tx), + .strobe(counter_decim == 8'b0),.signal_in(32'h1),.signal_out(decim_out)); + + cic_decim #(.bitwidth(32),.stages(4)) + decim(.clock(clk_120mhz),.reset(reset),.enable(enable_tx), + .strobe(counter_decim == 8'b0),.signal_in(32'h1),.signal_out(decim_out)); + +endmodule diff --git a/usrp/fpga/tb/fullchip_tb.v b/usrp/fpga/tb/fullchip_tb.v new file mode 100755 index 00000000..c446ff0e --- /dev/null +++ b/usrp/fpga/tb/fullchip_tb.v @@ -0,0 +1,174 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +// testbench for fullchip + +`timescale 1ns/1ns + +module fullchip_tb(); + +`include "usrp_tasks.v" + +fullchip fullchip + ( + .clk_120mhz(clk_120mhz), + .reset(reset), + .enable_rx(enable_rx), + .enable_tx(enable_tx), + .SLD(serload), + .SEN(serenable), + .clear_status(), + .SDI(serdata), + .SCLK(serclk), + + .adc1_data(adc1_data), + .adc2_data(adc2_data), + .adc3_data(adc1_data), + .adc4_data(adc2_data), + + .dac1_data(dac1_data), + .dac2_data(dac2_data), + .dac3_data(),.dac4_data(), + + .adclk0(adclk),.adclk1(), + + .adc_oeb(),.adc_otr(4'b0), + + .clk_out(clk_out), + + .misc_pins(), + + // USB interface + .usbclk(usbclk),.usbctl(usbctl), + .usbrdy(usbrdy),.usbdata(usbdata) + ); + + reg clk_120mhz; + reg usbclk; + reg reset; + + reg [11:0] adc1_data, adc2_data; + wire [13:0] dac1_data, dac2_data; + + wire [5:0] usbctl; + wire [5:0] usbrdy; + + wire [15:0] usbdata; + + reg WE, RD, OE; + + assign usbctl[0] = WE; + assign usbctl[1] = RD; + assign usbctl[2] = OE; + assign usbctl[5:3] = 0; + + wire have_packet_rdy = usbrdy[1]; + + reg tb_oe; + initial tb_oe=1'b1; + + assign usbdata = tb_oe ? usbdatareg : 16'hxxxx; + reg serload, serenable, serclk, serdata; + reg enable_tx, enable_rx; + reg [15:0] usbdatareg; + +/////////////////////////////////////////////// +// Simulation Control +initial +begin + $dumpfile("fullchip_tb.vcd"); + $dumpvars(0, fullchip_tb); +end + +//initial #1000000 $finish; + +/////////////////////////////////////////////// +// Monitors + +//initial $monitor(dac1_data); + +/////////////////////////////////////////////// +// Clock and reset + +initial clk_120mhz = 0; +initial usbclk = 0; +always #24 clk_120mhz = ~clk_120mhz; +always #60 usbclk = ~usbclk; + +initial reset = 1'b1; +initial #500 reset = 1'b0; + +///////////////////////////////////////////////// +// Run AD input + +always @(posedge adclk) adc1_data <= #1 12'd1234; +always @(posedge adclk) adc2_data <= #1 12'd1234; + +///////////////////////////////////////////////// +// USB interface + + initial + begin + initialize_usb; + #30000 @(posedge usbclk); + burst_usb_write(257); + + #30000 burst_usb_read(256); + #10000 $finish; + +// repeat(30) +// begin +// write_from_usb; +// read_from_usb; +// end +end + +///////////////////////////////////////////////// +// TX and RX enable + +initial enable_tx = 1'b0; +initial #40000 enable_tx = 1'b1; +initial enable_rx = 1'b0; +initial #40000 enable_rx = 1'b1; + +////////////////////////////////////////////////// +// Set up control bus + +initial +begin + #1000 send_config_word(`ch1in_freq,32'h0); // 1 MHz on 60 MHz clock + send_config_word(`ch2in_freq,32'h0); + send_config_word(`ch3in_freq,32'h0); + send_config_word(`ch4in_freq,32'h0); + send_config_word(`ch1out_freq,32'h01234567); + send_config_word(`ch2out_freq,32'h0); + send_config_word(`ch3out_freq,32'h0); + send_config_word(`ch4out_freq,32'h0); + send_config_word(`misc,32'h0); + send_config_word(`rates,{8'd2,8'd12,8'h0f,8'h07}); + // adc, ext, interp, decim +end + +///////////////////////////////////////////////////////// + +endmodule + diff --git a/usrp/fpga/tb/interp_tb.v b/usrp/fpga/tb/interp_tb.v new file mode 100755 index 00000000..8a8e89ff --- /dev/null +++ b/usrp/fpga/tb/interp_tb.v @@ -0,0 +1,108 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +// testbench for fullchip + +module interp_tb(); + +`include "usrp_tasks.v" + + reg clk_120mhz; + reg usbclk; + reg reset; + + reg [11:0] adc1_data, adc2_data; + wire [13:0] dac1_data, dac2_data; + + wire [5:0] usbctl; + wire [5:0] usbrdy; + + wire [15:0] usbdata; + + reg WE, RD, OE; + + assign usbctl[0] = WE; + assign usbctl[1] = RD; + assign usbctl[2] = OE; + assign usbctl[5:3] = 0; + + reg tb_oe; + assign usbdata = tb_oe ? usbdatareg : 16'hxxxx; + reg serload, serenable, serclk, serdata; + reg enable_tx, enable_rx; + reg [15:0] usbdatareg; + +/////////////////////////////////////////////// +// Simulation Control +initial +begin + $dumpfile("interp_tb.vcd"); + $dumpvars(0, fc_tb); +end + +initial #100000 $finish; + +/////////////////////////////////////////////// +// Monitors + +reg [7:0] counter_interp; +wire [7:0] interp_rate; +assign interp_rate = 32; +initial $monitor(dac1_data); + + always @(posedge clk_120mhz) + begin + if(reset | ~enable_tx) + counter_interp <= #1 0; + else if(counter_interp == 0) + counter_interp <= #1 interp_rate - 8'b1; + else + counter_interp <= #1 counter_interp - 8'b1; + end + +/////////////////////////////////////////////// +// Clock and reset + +initial clk_120mhz = 0; +initial usbclk = 0; +always #48 clk_120mhz = ~clk_120mhz; +always #120 usbclk = ~usbclk; + +initial reset = 1'b1; +initial #500 reset = 1'b0; + + +initial enable_tx = 1'b1; + + wire [31:0] interp_out, q_interp_out; + wire [31:0] decim_out; + wire [31:0] phase; + + cic_interp #(.bitwidth(32),.stages(4)) + interp_i(.clock(clk_120mhz),.reset(reset),.enable(enable_tx), + .strobe(counter_interp == 8'b0),.signal_in(32'h1),.signal_out(interp_out)); + + cic_decim #(.bitwidth(32),.stages(4)) + decim(.clock(clk_120mhz),.reset(reset),.enable(enable_tx), + .strobe(counter_interp == 8'b0),.signal_in(32'h1),.signal_out(decim_out)); + +endmodule diff --git a/usrp/fpga/tb/justinterp_tb.v b/usrp/fpga/tb/justinterp_tb.v new file mode 100644 index 00000000..ffbd0f17 --- /dev/null +++ b/usrp/fpga/tb/justinterp_tb.v @@ -0,0 +1,73 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +module cic_decim_tb; + +cic_decim #(.bitwidth(16),.stages(4)) + decim(clock,reset,enable,strobe_in,strobe_out,signal_in,signal_out); + + reg clock; + reg reset; + reg enable; + wire strobe; + reg [15:0] signal_in; + wire [15:0] signal_out; + + assign strobe_in = 1'b1; + reg strobe_out; + + always @(posedge clock) + while(1) + begin + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + strobe_out <= 1'b1; + @(posedge clock); + @(posedge clock); + @(posedge clock); + @(posedge clock); + strobe_out <= 1'b0; + end + + initial clock = 0; + always #50 clock = ~clock; + + initial reset = 1; + initial #1000 reset = 0; + + initial enable = 0; + initial #2000 enable = 1; + + initial signal_in = 16'h1; + initial #500000 signal_in = 16'h7fff; + initial #1000000 signal_in = 16'h8000; + initial #1500000 signal_in = 16'hffff; + + + initial $dumpfile("decim.vcd"); + initial $dumpvars(0,cic_decim_tb); + + initial #10000000 $finish; + +endmodule // cic_decim_tb diff --git a/usrp/fpga/tb/makesine.pl b/usrp/fpga/tb/makesine.pl new file mode 100755 index 00000000..9aebd694 --- /dev/null +++ b/usrp/fpga/tb/makesine.pl @@ -0,0 +1,14 @@ +#!/usr/bin/perl + +$angle = 0; +$angle_inc = 2*3.14159/87.2; +$amp = 1; +$amp_rate = 1.0035; +for($i=0;$i<3500;$i++) + { + printf("@(posedge clk);xi<= #1 16'h%x;yi<= #1 16'h%x;\n",65535&int($amp*cos($angle)),65535&int($amp*sin($angle))); + $angle += $angle_inc; + $amp *= $amp_rate; + } + +printf("\$finish;\n"); diff --git a/usrp/fpga/tb/run_cordic b/usrp/fpga/tb/run_cordic new file mode 100755 index 00000000..68144fc8 --- /dev/null +++ b/usrp/fpga/tb/run_cordic @@ -0,0 +1,4 @@ +#!/bin/sh + +iverilog -y ../sdr_lib -o cordic_tb cordic_tb.v + diff --git a/usrp/fpga/tb/run_fullchip b/usrp/fpga/tb/run_fullchip new file mode 100755 index 00000000..eb81d7ff --- /dev/null +++ b/usrp/fpga/tb/run_fullchip @@ -0,0 +1,4 @@ +#!/bin/sh + +iverilog -y ../toplevel/fullchip -y ../sdr_lib -y ../models -y . -o fullchip_tb fullchip_tb.v + diff --git a/usrp/fpga/tb/usrp_tasks.v b/usrp/fpga/tb/usrp_tasks.v new file mode 100755 index 00000000..00f82b9e --- /dev/null +++ b/usrp/fpga/tb/usrp_tasks.v @@ -0,0 +1,145 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Tasks + +///////////////////////////////////////////////// +// USB interface + +task initialize_usb; +begin + OE = 0;WE = 0;RD = 0; + usbdatareg <= 16'h0; +end +endtask + +task write_from_usb; +begin + tb_oe <= 1'b1; + @(posedge usbclk); + usbdatareg <= #1 $random % 65536; + WE <= #1 1'b1; + @(posedge usbclk) + WE <= #1 1'b0; + tb_oe <= #1 1'b0; +end +endtask + +task burst_usb_write; + input [31:0] repeat_count; + + begin + tb_oe <= 1'b1; + repeat(repeat_count) + begin + @(posedge usbclk) + usbdatareg <= #1 usbdatareg + 1; //$random % 65536; + WE <= #1 1'b1; + end + @(posedge usbclk) + WE <= #1 1'b0; + tb_oe <= 1'b0; + end +endtask // burst_usb_write + + +task read_from_usb; +begin + @(posedge usbclk); + RD <= #1 1'b1; + @(posedge usbclk); + RD <= #1 1'b0; + OE <= #1 1'b1; + @(posedge usbclk); + OE <= #1 1'b0; +end +endtask + +task burst_usb_read; + input [31:0] repeat_count; + begin + while (~have_packet_rdy) begin + @(posedge usbclk); + end + + @(posedge usbclk) + RD <= #1 1'b1; + repeat(repeat_count) + begin + @(posedge usbclk) + OE <= #1 1'b1; + end + RD <= #1 1'b0; + @(posedge usbclk); + OE <= #1 1'b0; + end +endtask // burst_usb_read + +///////////////////////////////////////////////// +// TX and RX enable + +////////////////////////////////////////////////// +// Set up control bus + +`define ch1in_freq 0 +`define ch2in_freq 1 +`define ch3in_freq 2 +`define ch4in_freq 3 +`define ch1out_freq 4 +`define ch2out_freq 5 +`define ch3out_freq 6 +`define ch4out_freq 7 +`define rates 8 +`define misc 9 + + task send_config_word; + input [7:0] addr; + input [31:0] data; + integer i; + + begin + #10 serenable = 1; + for(i=7;i>=0;i=i-1) + begin + #10 serdata = addr[i]; + #10 serclk = 0; + #10 serclk = 1; + #10 serclk = 0; + end + for(i=31;i>=0;i=i-1) + begin + #10 serdata = data[i]; + #10 serclk = 0; + #10 serclk = 1; + #10 serclk = 0; + end + #10 serenable = 0; + // #10 serload = 0; + // #10 serload = 1; + #10 serclk = 1; + #10 serclk = 0; + //#10 serload = 0; + end + endtask // send_config_word + + +///////////////////////////////////////////////////////// + diff --git a/usrp/fpga/toplevel/mrfm/biquad_2stage.v b/usrp/fpga/toplevel/mrfm/biquad_2stage.v new file mode 100644 index 00000000..9b769014 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/biquad_2stage.v @@ -0,0 +1,131 @@ +`include "mrfm.vh" + +module biquad_2stage (input clock, input reset, input strobe_in, + input serial_strobe, input [6:0] serial_addr, input [31:0] serial_data, + input wire [15:0] sample_in, output reg [15:0] sample_out, output wire [63:0] debugbus); + + wire [3:0] coeff_addr, coeff_wr_addr; + wire [3:0] data_addr, data_wr_addr; + reg [3:0] cur_offset, data_addr_int, data_wr_addr_int; + + wire [15:0] coeff, coeff_wr_data, data, data_wr_data; + wire coeff_wr; + reg data_wr; + + wire [30:0] product; + wire [33:0] accum; + wire [15:0] scaled_accum; + + wire [7:0] shift; + reg [3:0] phase; + wire enable_mult, enable_acc, latch_out, select_input; + reg done, clear_acc; + + setting_reg #(`FR_MRFM_IIR_COEFF) sr_coeff(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({coeff_wr_addr,coeff_wr_data}),.changed(coeff_wr)); + + setting_reg #(`FR_MRFM_IIR_SHIFT) sr_shift(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(shift),.changed()); + + ram16 coeff_ram(.clock(clock),.write(coeff_wr),.wr_addr(coeff_wr_addr),.wr_data(coeff_wr_data), + .rd_addr(coeff_addr),.rd_data(coeff)); + + ram16 data_ram(.clock(clock),.write(data_wr),.wr_addr(data_wr_addr),.wr_data(data_wr_data), + .rd_addr(data_addr),.rd_data(data)); + + mult mult (.clock(clock),.x(data),.y(coeff),.product(product),.enable_in(enable_mult),.enable_out() ); + + acc acc (.clock(clock),.reset(reset),.clear(clear_acc),.enable_in(enable_acc),.enable_out(), + .addend(product),.sum(accum) ); + + shifter shifter (.in(accum),.out(scaled_accum),.shift(shift)); + + assign data_wr_data = select_input ? sample_in : scaled_accum; + assign enable_mult = 1'b1; + + always @(posedge clock) + if(reset) + cur_offset <= #1 4'd0; + else if(latch_out) + cur_offset <= #1 cur_offset + 4'd1; + + assign data_addr = data_addr_int + cur_offset; + assign data_wr_addr = data_wr_addr_int + cur_offset; + + always @(posedge clock) + if(reset) + done <= #1 1'b0; + else if(latch_out) + done <= #1 1'b1; + else if(strobe_in) + done <= #1 1'b0; + + always @(posedge clock) + if(reset) + phase <= #1 4'd0; + else if(strobe_in) + phase <= #1 4'd0; + else if(!done) + phase <= #1 phase + 4'd1; + + assign coeff_addr = phase; + + always @(phase) + case(phase) + 4'd01 : data_addr_int = 4'd00; 4'd02 : data_addr_int = 4'd01; 4'd03 : data_addr_int = 4'd02; + 4'd04 : data_addr_int = 4'd03; 4'd05 : data_addr_int = 4'd04; + + 4'd07 : data_addr_int = 4'd03; 4'd08 : data_addr_int = 4'd04; 4'd09 : data_addr_int = 4'd05; + 4'd10 : data_addr_int = 4'd06; 4'd11 : data_addr_int = 4'd07; + default : data_addr_int = 4'd00; + endcase // case(phase) + + always @(phase) + case(phase) + 4'd0 : data_wr_addr_int = 4'd2; + 4'd8 : data_wr_addr_int = 4'd5; + 4'd14 : data_wr_addr_int = 4'd8; + default : data_wr_addr_int = 4'd0; + endcase // case(phase) + + always @(phase) + case(phase) + 4'd0, 4'd8, 4'd14 : data_wr = 1'b1; + default : data_wr = 1'b0; + endcase // case(phase) + + assign select_input = (phase == 4'd0); + + always @(phase) + case(phase) + 4'd0, 4'd1, 4'd2, 4'd3, 4'd9, 4'd15 : clear_acc = 1'd1; + default : clear_acc = 1'b0; + endcase // case(phase) + + assign enable_acc = ~clear_acc; + assign latch_out = (phase == 4'd14); + + always @(posedge clock) + if(reset) + sample_out <= #1 16'd0; + else if(latch_out) + sample_out <= #1 scaled_accum; + + //////////////////////////////////////////////////////// + // Debug + + wire [3:0] debugmux; + + setting_reg #(`FR_MRFM_DEBUG) sr_debugmux(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(debugmux),.changed()); + + assign debugbus[15:0] = debugmux[0] ? {coeff_addr,data_addr,data_wr_addr,cur_offset} : {phase,data_addr_int,data_wr_addr_int,cur_offset}; + assign debugbus[31:16] = debugmux[1] ? scaled_accum : {clock, strobe_in, data_wr, enable_mult, enable_acc, clear_acc, latch_out,select_input,done, data_addr_int}; + assign debugbus[47:32] = debugmux[2] ? sample_out : coeff; + assign debugbus[63:48] = debugmux[3] ? sample_in : data; + +endmodule // biquad_2stage + diff --git a/usrp/fpga/toplevel/mrfm/biquad_6stage.v b/usrp/fpga/toplevel/mrfm/biquad_6stage.v new file mode 100644 index 00000000..2b0c511c --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/biquad_6stage.v @@ -0,0 +1,137 @@ +`include "mrfm.vh" + +module mrfm_iir (input clock, input reset, input strobe_in, + input serial_strobe, input [6:0] serial_addr, input [31:0] serial_data, + input wire [15:0] sample_in, output reg [15:0] sample_out); + + wire [5:0] coeff_addr, coeff_wr_addr; + wire [4:0] data_addr, data_wr_addr; + reg [4:0] cur_offset, data_addr_int, data_wr_addr_int; + + wire [15:0] coeff, coeff_wr_data, data, data_wr_data; + wire coeff_wr; + reg data_wr; + + wire [30:0] product; + wire [33:0] accum; + wire [15:0] scaled_accum; + + wire [7:0] shift; + reg [5:0] phase; + wire enable_mult, enable_acc, latch_out, select_input; + reg done, clear_acc; + + setting_reg #(`FR_MRFM_IIR_COEFF) sr_coeff(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({coeff_wr_addr,coeff_wr_data}),.changed(coeff_wr)); + + setting_reg #(`FR_MRFM_IIR_SHIFT) sr_shift(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(shift),.changed()); + + ram64 coeff_ram(.clock(clock),.write(coeff_wr),.wr_addr(coeff_wr_addr),.wr_data(coeff_wr_data), + .rd_addr(coeff_addr),.rd_data(coeff)); + + ram32 data_ram(.clock(clock),.write(data_wr),.wr_addr(data_wr_addr),.wr_data(data_wr_data), + .rd_addr(data_addr),.rd_data(data)); + + mult mult (.clock(clock),.x(data),.y(coeff),.product(product),.enable_in(enable_mult),.enable_out() ); + + acc acc (.clock(clock),.reset(reset),.clear(clear_acc),.enable_in(enable_acc),.enable_out(), + .addend(product),.sum(accum) ); + + shifter shifter (.in(accum),.out(scaled_accum),.shift(shift)); + + assign data_wr_data = select_input ? sample_in : scaled_accum; + assign enable_mult = 1'b1; + + always @(posedge clock) + if(reset) + cur_offset <= #1 5'd0; + else if(latch_out) + cur_offset <= #1 cur_offset + 5'd1; + + assign data_addr = data_addr_int + cur_offset; + assign data_wr_addr = data_wr_addr_int + cur_offset; + + always @(posedge clock) + if(reset) + done <= #1 1'b0; + else if(latch_out) + done <= #1 1'b1; + else if(strobe_in) + done <= #1 1'b0; + + always @(posedge clock) + if(reset) + phase <= #1 6'd0; + else if(strobe_in) + phase <= #1 6'd0; + else if(!done) + phase <= #1 phase + 6'd1; + + always @(phase) + case(phase) + 6'd0 : data_addr_int = 5'd0; + default : data_addr_int = 5'd0; + endcase // case(phase) + + assign coeff_addr = phase; + + always @(phase) + case(phase) + 6'd01 : data_addr_int = 5'd00; 6'd02 : data_addr_int = 5'd01; 6'd03 : data_addr_int = 5'd02; + 6'd04 : data_addr_int = 5'd03; 6'd05 : data_addr_int = 5'd04; + + 6'd07 : data_addr_int = 5'd03; 6'd08 : data_addr_int = 5'd04; 6'd09 : data_addr_int = 5'd05; + 6'd10 : data_addr_int = 5'd06; 6'd11 : data_addr_int = 5'd07; + + 6'd13 : data_addr_int = 5'd06; 6'd14 : data_addr_int = 5'd07; 6'd15 : data_addr_int = 5'd08; + 6'd16 : data_addr_int = 5'd09; 6'd17 : data_addr_int = 5'd10; + + 6'd19 : data_addr_int = 5'd09; 6'd20 : data_addr_int = 5'd10; 6'd21 : data_addr_int = 5'd11; + 6'd22 : data_addr_int = 5'd12; 6'd23 : data_addr_int = 5'd13; + + 6'd25 : data_addr_int = 5'd12; 6'd26 : data_addr_int = 5'd13; 6'd27 : data_addr_int = 5'd14; + 6'd28 : data_addr_int = 5'd15; 6'd29 : data_addr_int = 5'd16; + + 6'd31 : data_addr_int = 5'd15; 6'd32 : data_addr_int = 5'd16; 6'd33 : data_addr_int = 5'd17; + 6'd34 : data_addr_int = 5'd18; 6'd35 : data_addr_int = 5'd19; + + default : data_addr_int = 5'd00; + endcase // case(phase) + + always @(phase) + case(phase) + 6'd0 : data_wr_addr_int = 5'd2; + 6'd8 : data_wr_addr_int = 5'd5; + 6'd14 : data_wr_addr_int = 5'd8; + 6'd20 : data_wr_addr_int = 5'd11; + 6'd26 : data_wr_addr_int = 5'd14; + 6'd32 : data_wr_addr_int = 5'd17; + 6'd38 : data_wr_addr_int = 5'd20; + default : data_wr_addr_int = 5'd0; + endcase // case(phase) + + always @(phase) + case(phase) + 6'd0, 6'd8, 6'd14, 6'd20, 6'd26, 6'd32, 6'd38: data_wr = 1'b1; + default : data_wr = 1'b0; + endcase // case(phase) + + always @(phase) + case(phase) + 6'd0, 6'd1, 6'd2, 6'd3, 6'd9, 6'd15, 6'd21, 6'd27, 6'd33 : clear_acc = 1'd1; + default : clear_acc = 1'b0; + endcase // case(phase) + + assign enable_acc = ~clear_acc; + assign latch_out = (phase == 6'd38); + + always @(posedge clock) + if(reset) + sample_out <= #1 16'd0; + else if(latch_out) + sample_out <= #1 scaled_accum; + +endmodule // mrfm_iir diff --git a/usrp/fpga/toplevel/mrfm/mrfm.csf b/usrp/fpga/toplevel/mrfm/mrfm.csf new file mode 100644 index 00000000..2c30b996 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.csf @@ -0,0 +1,444 @@ +COMPILER_SETTINGS +{ + IO_PLACEMENT_OPTIMIZATION = OFF; + ENABLE_DRC_SETTINGS = OFF; + PHYSICAL_SYNTHESIS_REGISTER_RETIMING = OFF; + PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION = OFF; + PHYSICAL_SYNTHESIS_COMBO_LOGIC = OFF; + DRC_FANOUT_EXCEEDING = 30; + DRC_REPORT_FANOUT_EXCEEDING = OFF; + DRC_TOP_FANOUT = 50; + DRC_REPORT_TOP_FANOUT = OFF; + RUN_DRC_DURING_COMPILATION = OFF; + ADV_NETLIST_OPT_RETIME_CORE_AND_IO = ON; + ADV_NETLIST_OPT_SYNTH_USE_FITTER_INFO = OFF; + ADV_NETLIST_OPT_SYNTH_GATE_RETIME = OFF; + ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP = OFF; + SMART_COMPILE_IGNORES_TDC_FOR_STRATIX_PLL_CHANGES = OFF; + MERGE_HEX_FILE = OFF; + TRUE_WYSIWYG_FLOW = OFF; + SEED = 1; + FINAL_PLACEMENT_OPTIMIZATION = AUTOMATICALLY; + FAMILY = Cyclone; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "LOWER TO 1ESB UPPER TO 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DEEP_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_SINGLE_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_WIDE_MODE_OUTPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4ESB"; + DPRAM_DEEP_MODE_OUTPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_INPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4"; + DPRAM_DEEP_MODE_INPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_OTHER_SIGNALS_EPXA4_10 = "DEFAULT OTHER ROUTING OPTIONS"; + DPRAM_OUTPUT_EPXA4_10 = "DEFAULT OUTPUT ROUTING OPTIONS"; + DPRAM_INPUT_EPXA4_10 = "DEFAULT INPUT ROUTING OPTIONS"; + STRIPE_TO_PLD_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PLD_TO_STRIPE_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PROCESSOR_DEBUG_EXTENSIONS_EPXA4_10 = "MEGALAB COLUMN 2"; + STRIPE_TO_PLD_BRIDGE_EPXA4_10 = "MEGALAB COLUMN 1"; + FAST_FIT_COMPILATION = OFF; + SIGNALPROBE_DURING_NORMAL_COMPILATION = OFF; + OPTIMIZE_IOC_REGISTER_PLACEMENT_FOR_TIMING = ON; + OPTIMIZE_TIMING = "NORMAL COMPILATION"; + OPTIMIZE_HOLD_TIMING = OFF; + COMPILATION_LEVEL = FULL; + SAVE_DISK_SPACE = OFF; + SPEED_DISK_USAGE_TRADEOFF = NORMAL; + LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT = OFF; + SIGNALPROBE_ALLOW_OVERUSE = OFF; + FOCUS_ENTITY_NAME = |mrfm; + ROUTING_BACK_ANNOTATION_MODE = OFF; + INC_PLC_MODE = OFF; + FIT_ONLY_ONE_ATTEMPT = OFF; +} +DEFAULT_DEVICE_OPTIONS +{ + GENERATE_CONFIG_HEXOUT_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_JBC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_SVF_FILE = OFF; + RESERVE_PIN = "AS INPUT TRI-STATED"; + RESERVE_ALL_UNUSED_PINS = "AS OUTPUT DRIVING GROUND"; + HEXOUT_FILE_COUNT_DIRECTION = UP; + HEXOUT_FILE_START_ADDRESS = 0; + GENERATE_HEX_FILE = OFF; + GENERATE_RBF_FILE = OFF; + GENERATE_TTF_FILE = OFF; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + APEX20K_CONFIGURATION_DEVICE = AUTO; + USE_CONFIGURATION_DEVICE = ON; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + AUTO_RESTART_CONFIGURATION = OFF; + ENABLE_VREFB_PIN = OFF; + ENABLE_VREFA_PIN = OFF; + SECURITY_BIT = OFF; + USER_START_UP_CLOCK = OFF; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "ACTIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_UPDATE_MODE = STANDARD; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + ENABLE_JTAG_BST_SUPPORT = OFF; + CONFIGURATION_CLOCK_DIVISOR = 1; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CLOCK_SOURCE = INTERNAL; + COMPRESSION_MODE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; +} +AUTO_SLD_HUB_ENTITY +{ + AUTO_INSERT_SLD_HUB_ENTITY = ENABLE; + HUB_INSTANCE_NAME = SLD_HUB_INST; + HUB_ENTITY_NAME = SLD_HUB; +} +SIGNALTAP_LOGIC_ANALYZER_SETTINGS +{ + ENABLE_SIGNALTAP = Off; + AUTO_ENABLE_SMART_COMPILE = On; +} +CHIP(mrfm) +{ + DEVICE = EP1C12Q240C8; + DEVICE_FILTER_PACKAGE = "ANY QFP"; + DEVICE_FILTER_PIN_COUNT = 240; + DEVICE_FILTER_SPEED_GRADE = ANY; + AUTO_RESTART_CONFIGURATION = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + USER_START_UP_CLOCK = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_JTAG_BST_SUPPORT = OFF; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + USE_CONFIGURATION_DEVICE = OFF; + APEX20K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + STRATIX_UPDATE_MODE = STANDARD; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + COMPRESSION_MODE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + GENERATE_TTF_FILE = OFF; + GENERATE_RBF_FILE = ON; + GENERATE_HEX_FILE = OFF; + SECURITY_BIT = OFF; + ENABLE_VREFA_PIN = OFF; + ENABLE_VREFB_PIN = OFF; + GENERATE_SVF_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_JBC_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_HEXOUT_FILE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; + BASE_PIN_OUT_FILE_ON_SAMEFRAME_DEVICE = OFF; + HEXOUT_FILE_START_ADDRESS = 0; + HEXOUT_FILE_COUNT_DIRECTION = UP; + RESERVE_ALL_UNUSED_PINS = "AS INPUT TRI-STATED"; + STRATIX_DEVICE_IO_STANDARD = LVTTL; + CLOCK_SOURCE = INTERNAL; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CONFIGURATION_CLOCK_DIVISOR = 1; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + SCLK : LOCATION = Pin_101; + SDI : LOCATION = Pin_100; + SEN : LOCATION = Pin_98; + SLD : LOCATION = Pin_95; + adc1_data[0] : LOCATION = Pin_5; + adc1_data[10] : LOCATION = Pin_235; + adc1_data[11] : LOCATION = Pin_234; + adc1_data[1] : LOCATION = Pin_4; + adc1_data[2] : LOCATION = Pin_3; + adc1_data[3] : LOCATION = Pin_2; + adc1_data[4] : LOCATION = Pin_1; + adc1_data[4] : IO_STANDARD = LVTTL; + adc1_data[5] : LOCATION = Pin_240; + adc1_data[6] : LOCATION = Pin_239; + adc1_data[7] : LOCATION = Pin_238; + adc1_data[8] : LOCATION = Pin_237; + adc1_data[9] : LOCATION = Pin_236; + adc2_data[0] : LOCATION = Pin_20; + adc2_data[10] : LOCATION = Pin_8; + adc2_data[11] : LOCATION = Pin_7; + adc2_data[1] : LOCATION = Pin_19; + adc2_data[2] : LOCATION = Pin_18; + adc2_data[3] : LOCATION = Pin_17; + adc2_data[4] : LOCATION = Pin_16; + adc2_data[5] : LOCATION = Pin_15; + adc2_data[6] : LOCATION = Pin_14; + adc2_data[7] : LOCATION = Pin_13; + adc2_data[8] : LOCATION = Pin_12; + adc2_data[9] : LOCATION = Pin_11; + adc3_data[0] : LOCATION = Pin_200; + adc3_data[10] : LOCATION = Pin_184; + adc3_data[11] : LOCATION = Pin_183; + adc3_data[1] : LOCATION = Pin_197; + adc3_data[2] : LOCATION = Pin_196; + adc3_data[3] : LOCATION = Pin_195; + adc3_data[4] : LOCATION = Pin_194; + adc3_data[5] : LOCATION = Pin_193; + adc3_data[6] : LOCATION = Pin_188; + adc3_data[7] : LOCATION = Pin_187; + adc3_data[8] : LOCATION = Pin_186; + adc3_data[9] : LOCATION = Pin_185; + adc4_data[0] : LOCATION = Pin_222; + adc4_data[10] : LOCATION = Pin_203; + adc4_data[11] : LOCATION = Pin_202; + adc4_data[1] : LOCATION = Pin_219; + adc4_data[2] : LOCATION = Pin_217; + adc4_data[3] : LOCATION = Pin_216; + adc4_data[4] : LOCATION = Pin_215; + adc4_data[5] : LOCATION = Pin_214; + adc4_data[6] : LOCATION = Pin_213; + adc4_data[7] : LOCATION = Pin_208; + adc4_data[8] : LOCATION = Pin_207; + adc4_data[9] : LOCATION = Pin_206; + adc_oeb[0] : LOCATION = Pin_228; + adc_oeb[1] : LOCATION = Pin_21; + adc_oeb[2] : LOCATION = Pin_181; + adc_oeb[3] : LOCATION = Pin_218; + adc_otr[0] : LOCATION = Pin_233; + adc_otr[1] : LOCATION = Pin_6; + adc_otr[2] : LOCATION = Pin_182; + adc_otr[3] : LOCATION = Pin_201; + adclk0 : LOCATION = Pin_224; + adclk1 : LOCATION = Pin_226; + clk0 : LOCATION = Pin_28; + clk0 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk0 : IO_STANDARD = LVTTL; + clk1 : LOCATION = Pin_29; + clk1 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk1 : IO_STANDARD = LVTTL; + clk3 : LOCATION = Pin_152; + clk3 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk3 : IO_STANDARD = LVTTL; + clk_120mhz : LOCATION = Pin_153; + clk_120mhz : IO_STANDARD = LVTTL; + clk_out : LOCATION = Pin_63; + clk_out : IO_STANDARD = LVTTL; + dac1_data[0] : LOCATION = Pin_165; + dac1_data[10] : LOCATION = Pin_177; + dac1_data[11] : LOCATION = Pin_178; + dac1_data[12] : LOCATION = Pin_179; + dac1_data[13] : LOCATION = Pin_180; + dac1_data[1] : LOCATION = Pin_166; + dac1_data[2] : LOCATION = Pin_167; + dac1_data[3] : LOCATION = Pin_168; + dac1_data[4] : LOCATION = Pin_169; + dac1_data[5] : LOCATION = Pin_170; + dac1_data[6] : LOCATION = Pin_173; + dac1_data[7] : LOCATION = Pin_174; + dac1_data[8] : LOCATION = Pin_175; + dac1_data[9] : LOCATION = Pin_176; + dac2_data[0] : LOCATION = Pin_159; + dac2_data[10] : LOCATION = Pin_163; + dac2_data[11] : LOCATION = Pin_139; + dac2_data[12] : LOCATION = Pin_164; + dac2_data[13] : LOCATION = Pin_138; + dac2_data[1] : LOCATION = Pin_158; + dac2_data[2] : LOCATION = Pin_160; + dac2_data[3] : LOCATION = Pin_156; + dac2_data[4] : LOCATION = Pin_161; + dac2_data[5] : LOCATION = Pin_144; + dac2_data[6] : LOCATION = Pin_162; + dac2_data[7] : LOCATION = Pin_141; + dac2_data[8] : LOCATION = Pin_143; + dac2_data[9] : LOCATION = Pin_140; + dac3_data[0] : LOCATION = Pin_122; + dac3_data[10] : LOCATION = Pin_134; + dac3_data[11] : LOCATION = Pin_135; + dac3_data[12] : LOCATION = Pin_136; + dac3_data[13] : LOCATION = Pin_137; + dac3_data[1] : LOCATION = Pin_123; + dac3_data[2] : LOCATION = Pin_124; + dac3_data[3] : LOCATION = Pin_125; + dac3_data[4] : LOCATION = Pin_126; + dac3_data[5] : LOCATION = Pin_127; + dac3_data[6] : LOCATION = Pin_128; + dac3_data[7] : LOCATION = Pin_131; + dac3_data[8] : LOCATION = Pin_132; + dac3_data[9] : LOCATION = Pin_133; + dac4_data[0] : LOCATION = Pin_104; + dac4_data[10] : LOCATION = Pin_118; + dac4_data[11] : LOCATION = Pin_119; + dac4_data[12] : LOCATION = Pin_120; + dac4_data[13] : LOCATION = Pin_121; + dac4_data[1] : LOCATION = Pin_105; + dac4_data[2] : LOCATION = Pin_106; + dac4_data[3] : LOCATION = Pin_107; + dac4_data[4] : LOCATION = Pin_108; + dac4_data[5] : LOCATION = Pin_113; + dac4_data[6] : LOCATION = Pin_114; + dac4_data[7] : LOCATION = Pin_115; + dac4_data[8] : LOCATION = Pin_116; + dac4_data[9] : LOCATION = Pin_117; + enable_rx : LOCATION = Pin_88; + enable_tx : LOCATION = Pin_93; + gndbus[0] : LOCATION = Pin_223; + gndbus[0] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[0] : IO_STANDARD = LVTTL; + gndbus[1] : LOCATION = Pin_225; + gndbus[1] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[1] : IO_STANDARD = LVTTL; + gndbus[2] : LOCATION = Pin_227; + gndbus[2] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[2] : IO_STANDARD = LVTTL; + gndbus[3] : LOCATION = Pin_62; + gndbus[3] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[3] : IO_STANDARD = LVTTL; + gndbus[4] : LOCATION = Pin_64; + gndbus[4] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[4] : IO_STANDARD = LVTTL; + misc_pins[0] : LOCATION = Pin_87; + misc_pins[0] : IO_STANDARD = LVTTL; + misc_pins[10] : LOCATION = Pin_76; + misc_pins[10] : IO_STANDARD = LVTTL; + misc_pins[11] : LOCATION = Pin_74; + misc_pins[11] : IO_STANDARD = LVTTL; + misc_pins[1] : LOCATION = Pin_86; + misc_pins[1] : IO_STANDARD = LVTTL; + misc_pins[2] : LOCATION = Pin_85; + misc_pins[2] : IO_STANDARD = LVTTL; + misc_pins[3] : LOCATION = Pin_84; + misc_pins[3] : IO_STANDARD = LVTTL; + misc_pins[4] : LOCATION = Pin_83; + misc_pins[4] : IO_STANDARD = LVTTL; + misc_pins[5] : LOCATION = Pin_82; + misc_pins[5] : IO_STANDARD = LVTTL; + misc_pins[6] : LOCATION = Pin_79; + misc_pins[6] : IO_STANDARD = LVTTL; + misc_pins[7] : LOCATION = Pin_78; + misc_pins[7] : IO_STANDARD = LVTTL; + misc_pins[8] : LOCATION = Pin_77; + misc_pins[8] : IO_STANDARD = LVTTL; + misc_pins[9] : LOCATION = Pin_75; + misc_pins[9] : IO_STANDARD = LVTTL; + reset : LOCATION = Pin_94; + usbclk : LOCATION = Pin_55; + usbctl[0] : LOCATION = Pin_56; + usbctl[1] : LOCATION = Pin_54; + usbctl[2] : LOCATION = Pin_53; + usbctl[3] : LOCATION = Pin_58; + usbctl[4] : LOCATION = Pin_57; + usbctl[5] : LOCATION = Pin_44; + usbdata[0] : LOCATION = Pin_73; + usbdata[10] : LOCATION = Pin_41; + usbdata[11] : LOCATION = Pin_39; + usbdata[12] : LOCATION = Pin_38; + usbdata[12] : IO_STANDARD = LVTTL; + usbdata[13] : LOCATION = Pin_37; + usbdata[14] : LOCATION = Pin_24; + usbdata[15] : LOCATION = Pin_23; + usbdata[1] : LOCATION = Pin_68; + usbdata[2] : LOCATION = Pin_67; + usbdata[3] : LOCATION = Pin_66; + usbdata[4] : LOCATION = Pin_65; + usbdata[5] : LOCATION = Pin_61; + usbdata[6] : LOCATION = Pin_60; + usbdata[7] : LOCATION = Pin_59; + usbdata[8] : LOCATION = Pin_43; + usbdata[9] : LOCATION = Pin_42; + usbrdy[0] : LOCATION = Pin_45; + usbrdy[1] : LOCATION = Pin_46; + usbrdy[2] : LOCATION = Pin_47; + usbrdy[3] : LOCATION = Pin_48; + usbrdy[4] : LOCATION = Pin_49; + usbrdy[5] : LOCATION = Pin_50; + clear_status : LOCATION = Pin_99; +} diff --git a/usrp/fpga/toplevel/mrfm/mrfm.esf b/usrp/fpga/toplevel/mrfm/mrfm.esf new file mode 100644 index 00000000..72b84e39 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.esf @@ -0,0 +1,14 @@ +SIMULATOR_SETTINGS +{ + ESTIMATE_POWER_CONSUMPTION = OFF; + GLITCH_INTERVAL = 1NS; + GLITCH_DETECTION = OFF; + SIMULATION_COVERAGE = ON; + CHECK_OUTPUTS = OFF; + SETUP_HOLD_DETECTION = OFF; + POWER_ESTIMATION_START_TIME = "0 NS"; + ADD_DEFAULT_PINS_TO_SIMULATION_OUTPUT_WAVEFORMS = ON; + SIMULATION_MODE = TIMING; + START_TIME = 0NS; + USE_COMPILER_SETTINGS = mrfm; +} diff --git a/usrp/fpga/toplevel/mrfm/mrfm.psf b/usrp/fpga/toplevel/mrfm/mrfm.psf new file mode 100644 index 00000000..678a7faa --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.psf @@ -0,0 +1,312 @@ +DEFAULT_DESIGN_ASSISTANT_SETTINGS +{ + HCPY_ALOAD_SIGNALS = OFF; + HCPY_VREF_PINS = OFF; + HCPY_CAT = OFF; + HCPY_ILLEGAL_HC_DEV_PKG = OFF; + ACLK_RULE_IMSZER_ADOMAIN = OFF; + ACLK_RULE_SZER_BTW_ACLK_DOMAIN = OFF; + ACLK_RULE_NO_SZER_ACLK_DOMAIN = OFF; + ACLK_CAT = OFF; + SIGNALRACE_RULE_ASYNCHPIN_SYNCH_CLKPIN = OFF; + SIGNALRACE_CAT = OFF; + NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED = OFF; + NONSYNCHSTRUCT_RULE_SRLATCH = OFF; + NONSYNCHSTRUCT_RULE_DLATCH = OFF; + NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR = OFF; + NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN = OFF; + NONSYNCHSTRUCT_RULE_RIPPLE_CLK = OFF; + NONSYNCHSTRUCT_RULE_DELAY_CHAIN = OFF; + NONSYNCHSTRUCT_RULE_REG_LOOP = OFF; + NONSYNCHSTRUCT_RULE_COMBLOOP = OFF; + NONSYNCHSTRUCT_CAT = OFF; + NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE = OFF; + TIMING_RULE_COIN_CLKEDGE = OFF; + TIMING_RULE_SHIFT_REG = OFF; + TIMING_RULE_HIGH_FANOUTS = OFF; + TIMING_CAT = OFF; + RESET_RULE_ALL = OFF; + RESET_RULE_IMSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_UNSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_REG_ASNYCH = OFF; + RESET_RULE_COMB_ASYNCH_RESET = OFF; + RESET_RULE_IMSYNCH_EXRESET = OFF; + RESET_RULE_UNSYNCH_EXRESET = OFF; + RESET_RULE_INPINS_RESETNET = OFF; + RESET_CAT = OFF; + CLK_RULE_ALL = OFF; + CLK_RULE_MIX_EDGES = OFF; + CLK_RULE_CLKNET_CLKSPINES = OFF; + CLK_RULE_INPINS_CLKNET = OFF; + CLK_RULE_GATING_SCHEME = OFF; + CLK_RULE_INV_CLOCK = OFF; + CLK_RULE_COMB_CLOCK = OFF; + CLK_CAT = OFF; + HCPY_EXCEED_USER_IO_USAGE = OFF; + HCPY_EXCEED_RAM_USAGE = OFF; + NONSYNCHSTRUCT_RULE_ASYN_RAM = OFF; + SIGNALRACE_RULE_TRISTATE = OFF; + ASSG_RULE_MISSING_TIMING = OFF; + ASSG_RULE_MISSING_FMAX = OFF; + ASSG_CAT = OFF; +} +SYNTHESIS_FITTING_SETTINGS +{ + AUTO_SHIFT_REGISTER_RECOGNITION = ON; + AUTO_DSP_RECOGNITION = ON; + AUTO_RAM_RECOGNITION = ON; + REMOVE_DUPLICATE_LOGIC = ON; + AUTO_TURBO_BIT = ON; + AUTO_MERGE_PLLS = ON; + AUTO_OPEN_DRAIN_PINS = ON; + AUTO_PARALLEL_EXPANDERS = ON; + AUTO_FAST_OUTPUT_ENABLE_REGISTERS = OFF; + AUTO_FAST_OUTPUT_REGISTERS = OFF; + AUTO_FAST_INPUT_REGISTERS = OFF; + AUTO_CASCADE_CHAINS = ON; + AUTO_CARRY_CHAINS = ON; + AUTO_DELAY_CHAINS = ON; + MAX7000_PARALLEL_EXPANDER_CHAIN_LENGTH = 4; + PARALLEL_EXPANDER_CHAIN_LENGTH = 16; + CASCADE_CHAIN_LENGTH = 2; + STRATIX_CARRY_CHAIN_LENGTH = 70; + MERCURY_CARRY_CHAIN_LENGTH = 48; + FLEX10K_CARRY_CHAIN_LENGTH = 32; + FLEX6K_CARRY_CHAIN_LENGTH = 32; + CARRY_CHAIN_LENGTH = 48; + CARRY_OUT_PINS_LCELL_INSERT = ON; + NORMAL_LCELL_INSERT = ON; + AUTO_LCELL_INSERTION = ON; + ALLOW_XOR_GATE_USAGE = ON; + AUTO_PACKED_REGISTERS_STRATIX = NORMAL; + AUTO_PACKED_REGISTERS = OFF; + AUTO_PACKED_REG_CYCLONE = NORMAL; + FLEX10K_OPTIMIZATION_TECHNIQUE = AREA; + FLEX6K_OPTIMIZATION_TECHNIQUE = AREA; + MERCURY_OPTIMIZATION_TECHNIQUE = AREA; + APEX20K_OPTIMIZATION_TECHNIQUE = SPEED; + MAX7000_OPTIMIZATION_TECHNIQUE = SPEED; + STRATIX_OPTIMIZATION_TECHNIQUE = SPEED; + CYCLONE_OPTIMIZATION_TECHNIQUE = AREA; + FLEX10K_TECHNOLOGY_MAPPER = LUT; + FLEX6K_TECHNOLOGY_MAPPER = LUT; + MERCURY_TECHNOLOGY_MAPPER = LUT; + APEX20K_TECHNOLOGY_MAPPER = LUT; + MAX7000_TECHNOLOGY_MAPPER = "PRODUCT TERM"; + STRATIX_TECHNOLOGY_MAPPER = LUT; + AUTO_IMPLEMENT_IN_ROM = OFF; + AUTO_GLOBAL_MEMORY_CONTROLS = OFF; + AUTO_GLOBAL_REGISTER_CONTROLS = ON; + AUTO_GLOBAL_OE = ON; + AUTO_GLOBAL_CLOCK = ON; + USE_LPM_FOR_AHDL_OPERATORS = ON; + LIMIT_AHDL_INTEGERS_TO_32_BITS = OFF; + ENABLE_BUS_HOLD_CIRCUITRY = OFF; + WEAK_PULL_UP_RESISTOR = OFF; + TURBO_BIT = ON; + MAX7000_IGNORE_SOFT_BUFFERS = OFF; + IGNORE_SOFT_BUFFERS = ON; + MAX7000_IGNORE_LCELL_BUFFERS = AUTO; + IGNORE_LCELL_BUFFERS = OFF; + IGNORE_ROW_GLOBAL_BUFFERS = OFF; + IGNORE_GLOBAL_BUFFERS = OFF; + IGNORE_CASCADE_BUFFERS = OFF; + IGNORE_CARRY_BUFFERS = OFF; + REMOVE_DUPLICATE_REGISTERS = ON; + REMOVE_REDUNDANT_LOGIC_CELLS = OFF; + ALLOW_POWER_UP_DONT_CARE = ON; + PCI_IO = OFF; + NOT_GATE_PUSH_BACK = ON; + SLOW_SLEW_RATE = OFF; + DSP_BLOCK_BALANCING = AUTO; + STATE_MACHINE_PROCESSING = AUTO; +} +DEFAULT_HARDCOPY_SETTINGS +{ + HARDCOPY_EXTERNAL_CLOCK_JITTER = "0.0 NS"; +} +DEFAULT_TIMING_REQUIREMENTS +{ + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + RUN_ALL_TIMING_ANALYSES = ON; + IGNORE_CLOCK_SETTINGS = OFF; + DEFAULT_HOLD_MULTICYCLE = "SAME AS MULTICYCLE"; + CUT_OFF_IO_PIN_FEEDBACK = ON; + CUT_OFF_CLEAR_AND_PRESET_PATHS = ON; + CUT_OFF_READ_DURING_WRITE_PATHS = ON; + CUT_OFF_PATHS_BETWEEN_CLOCK_DOMAINS = ON; + DO_MIN_ANALYSIS = ON; + DO_MIN_TIMING = OFF; + NUMBER_OF_PATHS_TO_REPORT = 200; + NUMBER_OF_DESTINATION_TO_REPORT = 10; + NUMBER_OF_SOURCES_PER_DESTINATION_TO_REPORT = 10; + MAX_SCC_SIZE = 50; +} +HDL_SETTINGS +{ + VERILOG_INPUT_VERSION = VERILOG_2001; + ENABLE_IP_DEBUG = OFF; + VHDL_INPUT_VERSION = VHDL93; + VHDL_SHOW_LMF_MAPPING_MESSAGES = OFF; +} +PROJECT_INFO(mrfm) +{ + ORIGINAL_QUARTUS_VERSION = 3.0; + PROJECT_CREATION_TIME_DATE = "00:14:04 JULY 13, 2003"; + LAST_QUARTUS_VERSION = 3.0; + SHOW_REGISTRATION_MESSAGE = ON; + USER_LIBRARIES = "e:\usrp\fpga\megacells"; +} +THIRD_PARTY_EDA_TOOLS(mrfm) +{ + EDA_DESIGN_ENTRY_SYNTHESIS_TOOL = ""; + EDA_SIMULATION_TOOL = ""; + EDA_TIMING_ANALYSIS_TOOL = ""; + EDA_BOARD_DESIGN_TOOL = ""; + EDA_FORMAL_VERIFICATION_TOOL = ""; + EDA_RESYNTHESIS_TOOL = ""; +} +EDA_TOOL_SETTINGS(eda_design_synthesis) +{ + EDA_INPUT_GND_NAME = GND; + EDA_INPUT_VCC_NAME = VCC; + EDA_SHOW_LMF_MAPPING_MESSAGES = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_INPUT_DATA_FORMAT = EDIF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_simulation) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_timing_analysis) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + EDA_LAUNCH_CMD_LINE_TOOL = OFF; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_board_design) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_formal_verification) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_palace) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + RESYNTHESIS_RETIMING = FULL; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; +} +CLOCK(clk_120mhz) +{ + FMAX_REQUIREMENT = "120.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(usbclk) +{ + FMAX_REQUIREMENT = "48.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(SCLK) +{ + FMAX_REQUIREMENT = "1.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(adclk0) +{ + FMAX_REQUIREMENT = "60.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(adclk1) +{ + FMAX_REQUIREMENT = "60.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} diff --git a/usrp/fpga/toplevel/mrfm/mrfm.py b/usrp/fpga/toplevel/mrfm/mrfm.py new file mode 100644 index 00000000..0ce46012 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# This is mrfm_fft_sos.py +# Modification of Matt's mrfm_fft.py that reads filter coefs from file +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import usrp + +class source_c(usrp.source_c): + def __init__(self,fpga_filename): + usrp.source_c.__init__(self,which=0, decim_rate=64, nchan=2, mux=0x32103210, mode=0, + fpga_filename=fpga_filename) + + self._write_9862(0,2,0x80) # Bypass ADC buffer, minimum gain + self._write_9862(0,3,0x80) # Bypass ADC buffer, minimum gain + + self._write_9862(0,8,0) # TX PWR Down + self._write_9862(0,10,0) # DAC offset + self._write_9862(0,11,0) # DAC offset + self._write_9862(0,14,0x80) # gain + self._write_9862(0,16,0xff) # pga + self._write_9862(0,18,0x0c) # TX IF + self._write_9862(0,19,0x01) # TX Digital + self._write_9862(0,20,0x00) # TX Mod + + # max/min values are +/-2, so scale is set to make 2 = 32767 + + self._write_fpga_reg(69,0x0e) # debug mux + self._write_fpga_reg(5,-1) + self._write_fpga_reg(7,-1) + self._write_oe(0,0xffff, 0xffff) + self._write_oe(1,0xffff, 0xffff) + self._write_fpga_reg(14,0xf) + + self.decim = None + + def set_coeffs(self,frac_bits,b20,b10,b00,a20,a10,b21,b11,b01,a21,a11): + def make_val(address,value): + return (address << 16) | (value & 0xffff) + + # gain, scale already included in a's and b's from file + + self._write_fpga_reg(67,make_val(1,b20)) + self._write_fpga_reg(67,make_val(2,b10)) + self._write_fpga_reg(67,make_val(3,b00)) + self._write_fpga_reg(67,make_val(4,a20)) + self._write_fpga_reg(67,make_val(5,a10)) + + self._write_fpga_reg(67,make_val(7,b21)) + self._write_fpga_reg(67,make_val(8,b11)) + self._write_fpga_reg(67,make_val(9,b01)) + self._write_fpga_reg(67,make_val(10,a21)) + self._write_fpga_reg(67,make_val(11,a11)) + + self._write_fpga_reg(68,frac_bits) # Shift + + print "Biquad 0 : b2=%d b1=%d b0=%d a2=%d a1=%d" % (b20,b10,b00,a20,a10) + print "Biquad 1 : b2=%d b1=%d b0=%d a2=%d a1=%d" % (b21,b11,b01,a21,a11) + + def set_decim_rate(self,rate=None): + i=2 + turn=1 + a=1 + b=1 + while (rate>1) and (i<257): + if (rate/i) * i == rate: + if turn == 1: + if a*i<257: + a = a * i + turn = 0 + elif b*i<257: + b = b * i + turn = 0 + else: + print "Failed to set DECIMATOR" + return self.decim + elif b*i<257: + b = b * i + turn = 1 + elif a*i<257: + a = a * i + turn = 1 + else: + print "Failed to set DECIMATOR" + return self.decim + rate=rate/i + continue + i = i + 1 + if rate > 1: + print "Failed to set DECIMATOR" + return self.decim + else: + self.decim = a*b + print "a = %d b = %d" % (a,b) + self._write_fpga_reg(64,(a-1)*256+(b-1)) # Set actual decimation + + def decim_rate(self): + return self.decim + + def set_center_freq(self,freq): + self._write_fpga_reg(65,int(-freq/64e6*65536*65536)) # set center freq + + def set_compensator(self,a11,a12,a21,a22,shift): + self._write_fpga_reg(70,a11) + self._write_fpga_reg(71,a12) + self._write_fpga_reg(72,a21) + self._write_fpga_reg(73,a22) + self._write_fpga_reg(74,shift) # comp shift + diff --git a/usrp/fpga/toplevel/mrfm/mrfm.qpf b/usrp/fpga/toplevel/mrfm/mrfm.qpf new file mode 100644 index 00000000..95914087 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.qpf @@ -0,0 +1,29 @@ +# Copyright (C) 1991-2004 Altera Corporation +# Any megafunction design, and related netlist (encrypted or decrypted), +# support information, device programming or simulation file, and any other +# associated documentation or information provided by Altera or a partner +# under Altera's Megafunction Partnership Program may be used only +# to program PLD devices (but not masked PLD devices) from Altera. Any +# other use of such megafunction design, netlist, support information, +# device programming or simulation file, or any other related documentation +# or information is prohibited for any other purpose, including, but not +# limited to modification, reverse engineering, de-compiling, or use with +# any other silicon devices, unless such use is explicitly licensed under +# a separate agreement with Altera or a megafunction partner. Title to the +# intellectual property, including patents, copyrights, trademarks, trade +# secrets, or maskworks, embodied in any such megafunction design, netlist, +# support information, device programming or simulation file, or any other +# related documentation or information provided by Altera or a megafunction +# partner, remains with Altera, the megafunction partner, or their respective +# licensors. No other licenses, including any licenses needed under any third +# party's intellectual property, are provided herein. + + + +QUARTUS_VERSION = "4.0" +DATE = "17:10:11 December 20, 2004" + + +# Active Revisions + +PROJECT_REVISION = "mrfm" diff --git a/usrp/fpga/toplevel/mrfm/mrfm.qsf b/usrp/fpga/toplevel/mrfm/mrfm.qsf new file mode 100644 index 00000000..ba1ae022 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.qsf @@ -0,0 +1,411 @@ +# Copyright (C) 1991-2005 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. + + +# The default values for assignments are stored in the file +# mrfm_assignment_defaults.qdf +# If this file doesn't exist, and for assignments not listed, see file +# assignment_defaults.qdf + +# Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 3.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "00:14:04 JULY 13, 2003" +set_global_assignment -name LAST_QUARTUS_VERSION "5.1 SP2" + +# Pin & Location Assignments +# ========================== +set_global_assignment -name RESERVE_PIN "AS INPUT TRI-STATED" +set_location_assignment PIN_29 -to SCLK +set_location_assignment PIN_117 -to SDI +set_location_assignment PIN_28 -to usbclk +set_location_assignment PIN_107 -to usbctl[0] +set_location_assignment PIN_106 -to usbctl[1] +set_location_assignment PIN_105 -to usbctl[2] +set_location_assignment PIN_100 -to usbdata[0] +set_location_assignment PIN_84 -to usbdata[10] +set_location_assignment PIN_83 -to usbdata[11] +set_location_assignment PIN_82 -to usbdata[12] +set_location_assignment PIN_79 -to usbdata[13] +set_location_assignment PIN_78 -to usbdata[14] +set_location_assignment PIN_77 -to usbdata[15] +set_location_assignment PIN_99 -to usbdata[1] +set_location_assignment PIN_98 -to usbdata[2] +set_location_assignment PIN_95 -to usbdata[3] +set_location_assignment PIN_94 -to usbdata[4] +set_location_assignment PIN_93 -to usbdata[5] +set_location_assignment PIN_88 -to usbdata[6] +set_location_assignment PIN_87 -to usbdata[7] +set_location_assignment PIN_86 -to usbdata[8] +set_location_assignment PIN_85 -to usbdata[9] +set_location_assignment PIN_104 -to usbrdy[0] +set_location_assignment PIN_101 -to usbrdy[1] +set_location_assignment PIN_76 -to FX2_1 +set_location_assignment PIN_75 -to FX2_2 +set_location_assignment PIN_74 -to FX2_3 +set_location_assignment PIN_116 -to io_rx_a[0] +set_location_assignment PIN_115 -to io_rx_a[1] +set_location_assignment PIN_114 -to io_rx_a[2] +set_location_assignment PIN_113 -to io_rx_a[3] +set_location_assignment PIN_108 -to io_rx_a[4] +set_location_assignment PIN_195 -to io_rx_a[5] +set_location_assignment PIN_196 -to io_rx_a[6] +set_location_assignment PIN_197 -to io_rx_a[7] +set_location_assignment PIN_200 -to io_rx_a[8] +set_location_assignment PIN_201 -to io_rx_a[9] +set_location_assignment PIN_202 -to io_rx_a[10] +set_location_assignment PIN_203 -to io_rx_a[11] +set_location_assignment PIN_206 -to io_rx_a[12] +set_location_assignment PIN_207 -to io_rx_a[13] +set_location_assignment PIN_208 -to io_rx_a[14] +set_location_assignment PIN_214 -to io_rx_b[0] +set_location_assignment PIN_215 -to io_rx_b[1] +set_location_assignment PIN_216 -to io_rx_b[2] +set_location_assignment PIN_217 -to io_rx_b[3] +set_location_assignment PIN_218 -to io_rx_b[4] +set_location_assignment PIN_219 -to io_rx_b[5] +set_location_assignment PIN_222 -to io_rx_b[6] +set_location_assignment PIN_223 -to io_rx_b[7] +set_location_assignment PIN_224 -to io_rx_b[8] +set_location_assignment PIN_225 -to io_rx_b[9] +set_location_assignment PIN_226 -to io_rx_b[10] +set_location_assignment PIN_227 -to io_rx_b[11] +set_location_assignment PIN_228 -to io_rx_b[12] +set_location_assignment PIN_233 -to io_rx_b[13] +set_location_assignment PIN_234 -to io_rx_b[14] +set_location_assignment PIN_175 -to io_tx_a[0] +set_location_assignment PIN_176 -to io_tx_a[1] +set_location_assignment PIN_177 -to io_tx_a[2] +set_location_assignment PIN_178 -to io_tx_a[3] +set_location_assignment PIN_179 -to io_tx_a[4] +set_location_assignment PIN_180 -to io_tx_a[5] +set_location_assignment PIN_181 -to io_tx_a[6] +set_location_assignment PIN_182 -to io_tx_a[7] +set_location_assignment PIN_183 -to io_tx_a[8] +set_location_assignment PIN_184 -to io_tx_a[9] +set_location_assignment PIN_185 -to io_tx_a[10] +set_location_assignment PIN_186 -to io_tx_a[11] +set_location_assignment PIN_187 -to io_tx_a[12] +set_location_assignment PIN_188 -to io_tx_a[13] +set_location_assignment PIN_193 -to io_tx_a[14] +set_location_assignment PIN_73 -to io_tx_b[0] +set_location_assignment PIN_68 -to io_tx_b[1] +set_location_assignment PIN_67 -to io_tx_b[2] +set_location_assignment PIN_66 -to io_tx_b[3] +set_location_assignment PIN_65 -to io_tx_b[4] +set_location_assignment PIN_64 -to io_tx_b[5] +set_location_assignment PIN_63 -to io_tx_b[6] +set_location_assignment PIN_62 -to io_tx_b[7] +set_location_assignment PIN_61 -to io_tx_b[8] +set_location_assignment PIN_60 -to io_tx_b[9] +set_location_assignment PIN_59 -to io_tx_b[10] +set_location_assignment PIN_58 -to io_tx_b[11] +set_location_assignment PIN_57 -to io_tx_b[12] +set_location_assignment PIN_56 -to io_tx_b[13] +set_location_assignment PIN_55 -to io_tx_b[14] +set_location_assignment PIN_152 -to master_clk +set_location_assignment PIN_144 -to rx_a_a[0] +set_location_assignment PIN_143 -to rx_a_a[1] +set_location_assignment PIN_141 -to rx_a_a[2] +set_location_assignment PIN_140 -to rx_a_a[3] +set_location_assignment PIN_139 -to rx_a_a[4] +set_location_assignment PIN_138 -to rx_a_a[5] +set_location_assignment PIN_137 -to rx_a_a[6] +set_location_assignment PIN_136 -to rx_a_a[7] +set_location_assignment PIN_135 -to rx_a_a[8] +set_location_assignment PIN_134 -to rx_a_a[9] +set_location_assignment PIN_133 -to rx_a_a[10] +set_location_assignment PIN_132 -to rx_a_a[11] +set_location_assignment PIN_23 -to rx_a_b[0] +set_location_assignment PIN_21 -to rx_a_b[1] +set_location_assignment PIN_20 -to rx_a_b[2] +set_location_assignment PIN_19 -to rx_a_b[3] +set_location_assignment PIN_18 -to rx_a_b[4] +set_location_assignment PIN_17 -to rx_a_b[5] +set_location_assignment PIN_16 -to rx_a_b[6] +set_location_assignment PIN_15 -to rx_a_b[7] +set_location_assignment PIN_14 -to rx_a_b[8] +set_location_assignment PIN_13 -to rx_a_b[9] +set_location_assignment PIN_12 -to rx_a_b[10] +set_location_assignment PIN_11 -to rx_a_b[11] +set_location_assignment PIN_131 -to rx_b_a[0] +set_location_assignment PIN_128 -to rx_b_a[1] +set_location_assignment PIN_127 -to rx_b_a[2] +set_location_assignment PIN_126 -to rx_b_a[3] +set_location_assignment PIN_125 -to rx_b_a[4] +set_location_assignment PIN_124 -to rx_b_a[5] +set_location_assignment PIN_123 -to rx_b_a[6] +set_location_assignment PIN_122 -to rx_b_a[7] +set_location_assignment PIN_121 -to rx_b_a[8] +set_location_assignment PIN_120 -to rx_b_a[9] +set_location_assignment PIN_119 -to rx_b_a[10] +set_location_assignment PIN_118 -to rx_b_a[11] +set_location_assignment PIN_8 -to rx_b_b[0] +set_location_assignment PIN_7 -to rx_b_b[1] +set_location_assignment PIN_6 -to rx_b_b[2] +set_location_assignment PIN_5 -to rx_b_b[3] +set_location_assignment PIN_4 -to rx_b_b[4] +set_location_assignment PIN_3 -to rx_b_b[5] +set_location_assignment PIN_2 -to rx_b_b[6] +set_location_assignment PIN_240 -to rx_b_b[7] +set_location_assignment PIN_239 -to rx_b_b[8] +set_location_assignment PIN_238 -to rx_b_b[9] +set_location_assignment PIN_237 -to rx_b_b[10] +set_location_assignment PIN_236 -to rx_b_b[11] +set_location_assignment PIN_156 -to SDO +set_location_assignment PIN_153 -to SEN_FPGA +set_location_assignment PIN_159 -to tx_a[0] +set_location_assignment PIN_160 -to tx_a[1] +set_location_assignment PIN_161 -to tx_a[2] +set_location_assignment PIN_162 -to tx_a[3] +set_location_assignment PIN_163 -to tx_a[4] +set_location_assignment PIN_164 -to tx_a[5] +set_location_assignment PIN_165 -to tx_a[6] +set_location_assignment PIN_166 -to tx_a[7] +set_location_assignment PIN_167 -to tx_a[8] +set_location_assignment PIN_168 -to tx_a[9] +set_location_assignment PIN_169 -to tx_a[10] +set_location_assignment PIN_170 -to tx_a[11] +set_location_assignment PIN_173 -to tx_a[12] +set_location_assignment PIN_174 -to tx_a[13] +set_location_assignment PIN_38 -to tx_b[0] +set_location_assignment PIN_39 -to tx_b[1] +set_location_assignment PIN_41 -to tx_b[2] +set_location_assignment PIN_42 -to tx_b[3] +set_location_assignment PIN_43 -to tx_b[4] +set_location_assignment PIN_44 -to tx_b[5] +set_location_assignment PIN_45 -to tx_b[6] +set_location_assignment PIN_46 -to tx_b[7] +set_location_assignment PIN_47 -to tx_b[8] +set_location_assignment PIN_48 -to tx_b[9] +set_location_assignment PIN_49 -to tx_b[10] +set_location_assignment PIN_50 -to tx_b[11] +set_location_assignment PIN_53 -to tx_b[12] +set_location_assignment PIN_54 -to tx_b[13] +set_location_assignment PIN_158 -to TXSYNC_A +set_location_assignment PIN_37 -to TXSYNC_B +set_location_assignment PIN_235 -to io_rx_b[15] +set_location_assignment PIN_24 -to io_tx_b[15] +set_location_assignment PIN_213 -to io_rx_a[15] +set_location_assignment PIN_194 -to io_tx_a[15] +set_location_assignment PIN_1 -to MYSTERY_SIGNAL + +# Timing Assignments +# ================== +set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 240 +set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "" +set_global_assignment -name FAMILY Cyclone +set_global_assignment -name CYCLONE_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name STRATIX_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name APEX20K_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name TOP_LEVEL_ENTITY mrfm +set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name USER_LIBRARIES "e:\\usrp\\fpga\\megacells" +set_global_assignment -name AUTO_ENABLE_SMART_COMPILE ON + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP1C12Q240C8 +set_global_assignment -name CYCLONE_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" +set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF +set_global_assignment -name OPTIMIZE_TIMING "NORMAL COMPILATION" +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name IO_PLACEMENT_OPTIMIZATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA +set_global_assignment -name INC_PLC_MODE OFF +set_global_assignment -name ROUTING_BACK_ANNOTATION_MODE OFF +set_instance_assignment -name IO_STANDARD LVTTL -to usbdata[12] +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD LVTTL +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 + +# Timing Analysis Assignments +# =========================== +set_global_assignment -name MAX_SCC_SIZE 50 + +# EDA Netlist Writer Assignments +# ============================== +set_global_assignment -name EDA_SIMULATION_TOOL "" +set_global_assignment -name EDA_TIMING_ANALYSIS_TOOL "" +set_global_assignment -name EDA_BOARD_DESIGN_TOOL "" +set_global_assignment -name EDA_FORMAL_VERIFICATION_TOOL "" +set_global_assignment -name EDA_RESYNTHESIS_TOOL "" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "AS INPUT TRI-STATED" +set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF + +# Simulator Assignments +# ===================== +set_global_assignment -name START_TIME "0 ns" +set_global_assignment -name GLITCH_INTERVAL "1 ns" + +# Design Assistant Assignments +# ============================ +set_global_assignment -name DRC_REPORT_TOP_FANOUT OFF +set_global_assignment -name DRC_REPORT_FANOUT_EXCEEDING OFF +set_global_assignment -name ASSG_CAT OFF +set_global_assignment -name ASSG_RULE_MISSING_FMAX OFF +set_global_assignment -name ASSG_RULE_MISSING_TIMING OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ASYN_RAM OFF +set_global_assignment -name CLK_CAT OFF +set_global_assignment -name CLK_RULE_COMB_CLOCK OFF +set_global_assignment -name CLK_RULE_INV_CLOCK OFF +set_global_assignment -name CLK_RULE_GATING_SCHEME OFF +set_global_assignment -name CLK_RULE_INPINS_CLKNET OFF +set_global_assignment -name CLK_RULE_CLKNET_CLKSPINES OFF +set_global_assignment -name CLK_RULE_MIX_EDGES OFF +set_global_assignment -name RESET_CAT OFF +set_global_assignment -name RESET_RULE_INPINS_RESETNET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_IMSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_COMB_ASYNCH_RESET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name RESET_RULE_IMSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name TIMING_CAT OFF +set_global_assignment -name TIMING_RULE_SHIFT_REG OFF +set_global_assignment -name TIMING_RULE_COIN_CLKEDGE OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE OFF +set_global_assignment -name NONSYNCHSTRUCT_CAT OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMBLOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_REG_LOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_DELAY_CHAIN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_RIPPLE_CLK OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_SRLATCH OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED OFF +set_global_assignment -name SIGNALRACE_CAT OFF +set_global_assignment -name ACLK_CAT OFF +set_global_assignment -name ACLK_RULE_NO_SZER_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_SZER_BTW_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_IMSZER_ADOMAIN OFF +set_global_assignment -name HCPY_CAT OFF +set_global_assignment -name HCPY_VREF_PINS OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name HUB_ENTITY_NAME SLD_HUB +set_global_assignment -name HUB_INSTANCE_NAME SLD_HUB_INST +set_global_assignment -name ENABLE_SIGNALTAP OFF + +# LogicLock Region Assignments +# ============================ +set_global_assignment -name LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT OFF + +# ----------------- +# start CLOCK(SCLK) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id SCLK +set_global_assignment -name FMAX_REQUIREMENT "1 MHz" -section_id SCLK +set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id SCLK + +# end CLOCK(SCLK) +# --------------- + +# ----------------------- +# start CLOCK(master_clk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id master_clk +set_global_assignment -name FMAX_REQUIREMENT "64 MHz" -section_id master_clk +set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id master_clk + +# end CLOCK(master_clk) +# --------------------- + +# ------------------- +# start CLOCK(usbclk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id usbclk +set_global_assignment -name FMAX_REQUIREMENT "48 MHz" -section_id usbclk +set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id usbclk + +# end CLOCK(usbclk) +# ----------------- + +# ---------------------- +# start ENTITY(mrfm) + + # Timing Assignments + # ================== +set_instance_assignment -name CLOCK_SETTINGS SCLK -to SCLK +set_instance_assignment -name CLOCK_SETTINGS usbclk -to usbclk +set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk + +# end ENTITY(mrfm) +# -------------------- + + +set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name VERILOG_FILE mrfm.vh +set_global_assignment -name VERILOG_FILE biquad_2stage.v +set_global_assignment -name VERILOG_FILE mrfm_compensator.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/ram16.v +set_global_assignment -name VERILOG_FILE mrfm_proc.v +set_global_assignment -name VERILOG_FILE ../../megacells/fifo_4k.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/acc.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mult.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/ram16_2sum.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_rom.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/halfband_decim.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mac.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_ram.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_chain.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_dcoffset.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/adc_interface.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/io_pins.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/setting_reg.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/bidir_reg.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_int_shifter.v +set_global_assignment -name VERILOG_FILE ../../megacells/clk_doubler.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/gen_sync.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/master_control.v +set_global_assignment -name VERILOG_FILE ../../megacells/fifo_2k.v +set_global_assignment -name VERILOG_FILE ../../megacells/bustri.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_buffer.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_buffer.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/phase_acc.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_interp.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_decim.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cordic_stage.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cordic.v +set_global_assignment -name VERILOG_FILE mrfm.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/clk_divider.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/serial_io.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/strobe_gen.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" \ No newline at end of file diff --git a/usrp/fpga/toplevel/mrfm/mrfm.v b/usrp/fpga/toplevel/mrfm/mrfm.v new file mode 100644 index 00000000..cf9d1119 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.v @@ -0,0 +1,199 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Top level module for a full setup with DUCs and DDCs + +// Uncomment the following to include optional circuitry + +`include "mrfm.vh" +`include "../../../firmware/include/fpga_regs_common.v" +`include "../../../firmware/include/fpga_regs_standard.v" + +module mrfm +(output MYSTERY_SIGNAL, + input master_clk, + input SCLK, + input SDI, + inout SDO, + input SEN_FPGA, + + input FX2_1, + output FX2_2, + output FX2_3, + + input wire [11:0] rx_a_a, + input wire [11:0] rx_b_a, + input wire [11:0] rx_a_b, + input wire [11:0] rx_b_b, + + output wire [13:0] tx_a, + output wire [13:0] tx_b, + + output wire TXSYNC_A, + output wire TXSYNC_B, + + // USB interface + input usbclk, + input wire [2:0] usbctl, + output wire [1:0] usbrdy, + inout [15:0] usbdata, // NB Careful, inout + + // These are the general purpose i/o's that go to the daughterboard slots + inout wire [15:0] io_tx_a, + inout wire [15:0] io_tx_b, + inout wire [15:0] io_rx_a, + inout wire [15:0] io_rx_b + ); + wire [15:0] debugdata,debugctrl; + assign MYSTERY_SIGNAL = 1'b0; + + wire clk64; + + wire WR = usbctl[0]; + wire RD = usbctl[1]; + wire OE = usbctl[2]; + + wire have_space, have_pkt_rdy; + assign usbrdy[0] = have_space; + assign usbrdy[1] = have_pkt_rdy; + + wire tx_underrun, rx_overrun; + wire clear_status = FX2_1; + assign FX2_2 = rx_overrun; + assign FX2_3 = tx_underrun; + + wire [15:0] usbdata_out; + + wire [3:0] dac0mux,dac1mux,dac2mux,dac3mux; + + wire tx_realsignals; + wire [3:0] rx_numchan; + + wire [15:0] tx_debugbus, rx_debugbus; + + wire enable_tx, enable_rx; + wire tx_dsp_reset, rx_dsp_reset, tx_bus_reset, rx_bus_reset; + wire [7:0] settings; + + // Tri-state bus macro + bustri bustri( .data(usbdata_out),.enabledt(OE),.tridata(usbdata) ); + + assign clk64 = master_clk; + + wire [15:0] ch0tx,ch1tx,ch2tx,ch3tx; + wire [15:0] ch0rx,ch1rx,ch2rx,ch3rx,ch4rx,ch5rx,ch6rx,ch7rx; + + wire serial_strobe; + wire [6:0] serial_addr; + wire [31:0] serial_data; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + setting_reg #(`FR_TX_MUX) + sr_txmux(.clock(clk64),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({dac3mux,dac2mux,dac1mux,dac0mux,tx_realsignals,tx_numchan})); + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Signal Processing Chain + + reg [15:0] adc0; + wire [15:0] dac0; + wire [15:0] i,q,ip,qp; + wire strobe_out; + wire sync_out; + + always @(posedge clk64) + adc0 <= #1 {rx_a_a[11],rx_a_a[11:0],3'b0}; + + wire [15:0] adc0_corr; + rx_dcoffset #(0)rx_dcoffset0(.clock(clk64),.enable(1'b1),.reset(reset),.adc_in(adc0),.adc_out(adc0_corr), + .serial_addr(7'd0),.serial_data(32'd0),.serial_strobe(1'b0)); + + //wire [63:0] filt_debug = 64'd0; + + mrfm_proc mrfm_proc(.clock(clk64),.reset(rx_dsp_reset),.enable(enable_rx), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .signal_in(adc0_corr),.signal_out(dac0),.sync_out(sync_out), + .i(i),.q(q),.ip(ip),.qp(qp),.strobe_out(strobe_out), + .debugbus( /* filt_debug */ )); + + wire txsync = 1'b0; + assign TXSYNC_A = txsync; + assign TXSYNC_B = txsync; + + assign tx_a = dac0[15:2]; + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Data Collection on RX Buffer + + assign rx_numchan[0] = 1'b0; + setting_reg #(`FR_RX_MUX) sr_rxmux(.clock(clk64),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr), + .in(serial_data),.out(rx_numchan[3:1])); + + rx_buffer rx_buffer + ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset), + .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun), + .channels(rx_numchan), + .ch_0(i),.ch_1(q), + .ch_2(ip),.ch_3(qp), + .ch_4(16'd0),.ch_5(16'd0), + .ch_6(16'd0),.ch_7(16'd0), + .rxclk(clk64),.rxstrobe(strobe_out), + .clear_status(clear_status), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .debugbus(rx_debugbus) ); + + ////////////////////////////////////////////////////////////////////////////// + // Control Functions + + wire [31:0] capabilities = 32'd2; + + serial_io serial_io + ( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI), + .enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .readback_0({io_rx_a,io_tx_a}),.readback_1({io_rx_b,io_tx_b}),.readback_2(capabilities),.readback_3(32'hf0f0931a) ); + + wire [15:0] reg_0,reg_1,reg_2,reg_3; + master_control master_control + ( .master_clk(clk64),.usbclk(usbclk), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .tx_bus_reset(tx_bus_reset),.rx_bus_reset(rx_bus_reset), + .tx_dsp_reset(tx_dsp_reset),.rx_dsp_reset(rx_dsp_reset), + .enable_tx(enable_tx),.enable_rx(enable_rx), + .interp_rate(interp_rate),.decim_rate(decim_rate), + .tx_sample_strobe(tx_sample_strobe),.strobe_interp(strobe_interp), + .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim), + .tx_empty(tx_empty), + .debug_0({15'd0,sync_out}), //filt_debug[63:48]), + .debug_1({15'd0,sync_out}), //filt_debug[47:32]), + .debug_2({15'd0,sync_out}), //filt_debug[31:16]), + .debug_3({15'd0,sync_out}), //filt_debug[15:0]), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) ); + + io_pins io_pins + (.io_0(io_tx_a),.io_1(io_rx_a),.io_2(io_tx_b),.io_3(io_rx_b), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3), + .clock(clk64),.rx_reset(rx_dsp_reset),.tx_reset(tx_dsp_reset), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe)); + +endmodule // mrfm + diff --git a/usrp/fpga/toplevel/mrfm/mrfm.vh b/usrp/fpga/toplevel/mrfm/mrfm.vh new file mode 100644 index 00000000..808342d8 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm.vh @@ -0,0 +1,21 @@ + + +// MRFM Register defines + +`define FR_MRFM_DECIM 7'd64 +`define FR_MRFM_FREQ 7'd65 +`define FR_MRFM_PHASE 7'd66 +`define FR_MRFM_IIR_COEFF 7'd67 +`define FR_MRFM_IIR_SHIFT 7'd68 +`define FR_MRFM_DEBUG 7'd69 +`define FR_MRFM_COMP_A11 7'd70 +`define FR_MRFM_COMP_A12 7'd71 +`define FR_MRFM_COMP_A21 7'd72 +`define FR_MRFM_COMP_A22 7'd73 +`define FR_MRFM_COMP_SHIFT 7'd74 +`define FR_USER_11 7'd75 +`define FR_USER_12 7'd76 +`define FR_USER_13 7'd77 +`define FR_USER_14 7'd78 +`define FR_USER_15 7'd79 + diff --git a/usrp/fpga/toplevel/mrfm/mrfm_compensator.v b/usrp/fpga/toplevel/mrfm/mrfm_compensator.v new file mode 100644 index 00000000..f44b73b2 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm_compensator.v @@ -0,0 +1,80 @@ + + +module mrfm_compensator (input clock, input reset, input strobe_in, + input serial_strobe, input [6:0] serial_addr, input [31:0] serial_data, + input [15:0] i_in, input [15:0] q_in, output reg [15:0] i_out, output reg [15:0] q_out); + + wire [15:0] a11,a12,a21,a22; + reg [15:0] i_in_reg, q_in_reg; + wire [30:0] product; + reg [3:0] phase; + wire [15:0] data,coeff; + wire [7:0] shift; + wire [33:0] accum; + wire [15:0] scaled_accum; + wire enable_acc; + + setting_reg #(`FR_MRFM_COMP_A11) sr_a11(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(a11),.changed()); + setting_reg #(`FR_MRFM_COMP_A12) sr_a12(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(a12),.changed()); + setting_reg #(`FR_MRFM_COMP_A21) sr_a21(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(a21),.changed()); + setting_reg #(`FR_MRFM_COMP_A22) sr_a22(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(a22),.changed()); + setting_reg #(`FR_MRFM_COMP_SHIFT) sr_cshift(.clock(clock),.reset(reset), + .strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out(shift),.changed()); + + mult mult (.clock(clock),.x(data),.y(coeff),.product(product),.enable_in(1'b1),.enable_out() ); + acc acc (.clock(clock),.reset(reset),.clear(clear_acc),.enable_in(enable_acc),.enable_out(), + .addend(product),.sum(accum) ); + shifter shifter (.in(accum),.out(scaled_accum),.shift(shift)); + + always @(posedge clock) + if(reset) + begin + i_in_reg <= #1 16'd0; + q_in_reg <= #1 16'd0; + end + else if(strobe_in) + begin + i_in_reg <= #1 i_in; + q_in_reg <= #1 q_in; + end + + always @(posedge clock) + if(reset) + phase <= #1 4'd0; + else if(strobe_in) + phase <= #1 4'd1; + else if(strobe_in != 4'd8) + phase <= #1 phase + 4'd1; + + assign data = ((phase == 4'd1)||(phase === 4'd4)) ? i_in_reg : + ((phase == 4'd2)||(phase == 4'd5)) ? q_in_reg : 16'd0; + + assign coeff = (phase == 4'd1) ? a11 : (phase == 4'd2) ? a12 : + (phase == 4'd4) ? a21 : (phase == 4'd5) ? a22 : 16'd0; + + assign clear_acc = (phase == 4'd0) || (phase == 4'd1) || (phase == 4'd4) || (phase==4'd8); + assign enable_acc = ~clear_acc; + + always @(posedge clock) + if(reset) + i_out <= #1 16'd0; + else if(phase == 4'd4) + i_out <= #1 scaled_accum; + + always @(posedge clock) + if(reset) + q_out <= #1 16'd0; + else if(phase == 4'd7) + q_out <= #1 scaled_accum; + + +endmodule // mrfm_compensator diff --git a/usrp/fpga/toplevel/mrfm/mrfm_fft.py b/usrp/fpga/toplevel/mrfm/mrfm_fft.py new file mode 100755 index 00000000..343ab019 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm_fft.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python +# +# This is mrfm_fft_sos.py +# Modification of Matt's mrfm_fft.py that reads filter coefs from file +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gru +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +from optparse import OptionParser +import wx +import sys +import mrfm + + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + If there's a daughterboard on A, select A. + If there's a daughterboard on B, select B. + Otherwise, select A. + """ + if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + +def read_ints(filename): + try: + f = open(filename) + ints = [ int(i) for i in f.read().split() ] + f.close() + return ints + except: + return [] + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=first one with a daughterboard)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-W", "--waterfall", action="store_true", default=False, + help="Enable waterfall display") + parser.add_option("-8", "--width-8", action="store_true", default=False, + help="Enable 8-bit samples across USB") + parser.add_option("-S", "--oscilloscope", action="store_true", default=False, + help="Enable oscilloscope display") + parser.add_option("-F", "--filename", default=None, + help="Name of file with filter coefficients") + parser.add_option("-C", "--cfilename", default=None, + help="Name of file with compensator coefficients") + parser.add_option("-B", "--bitstream", default="mrfm.rbf", + help="Name of FPGA Bitstream file (.rbf)") + parser.add_option("-n", "--frame-decim", type="int", default=20, + help="set oscope frame decimation factor to n [default=12]") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + # default filter coefs + b00 = b01 = 16384 + b10 = b20 = a10 = a20 = b11 = b21 = a11 = a21 = 0 + + ba = read_ints(options.filename) + if len(ba) >= 6: + b00 = ba[0]; b10 = ba[1]; b20 = ba[2]; a10 = ba[4]; a20 = ba[5] + if len(ba) >= 12: + b01 = ba[6]; b11 = ba[7]; b21 = ba[8]; a11 = ba[10]; a21=ba[11] + print b00, b10, b20, a10, a20, b01, b11, b21, a11, a21 + + # default compensator coefficients + c11 = c22 = 1 + c12 = c21 = cscale = 0 + + cs = read_ints(options.cfilename) + if len(cs) >= 5: + c11 = cs[0]; c12 = cs[1]; c21 = cs[2]; c22 = cs[3]; cscale = cs[4] + print c11, c12, c21, c22, cscale + + # build the graph + self.u = mrfm.source_c(options.bitstream) + + self.u.set_decim_rate(options.decim) + self.u.set_center_freq(options.freq) + + frac_bits = 14 + self.u.set_coeffs(frac_bits,b20,b10,b00,a20,a10,b21,b11,b01,a21,a11) + + self.u.set_compensator(c11,c12,c21,c22,cscale) + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.u) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + + if options.width_8: + width = 8 + shift = 8 + format = self.u.make_format(width, shift) + print "format =", hex(format) + r = self.u.set_format(format) + print "set_format =", r + + # determine the daughterboard subdevice we're using + self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) + + #input_rate = self.u.adc_freq() / self.u.decim_rate() + input_rate = self.u.adc_freq() / options.decim + + # fft_rate = 15 + fft_rate = 5 + + self.deint = gr.deinterleave(gr.sizeof_gr_complex) + self.connect(self.u,self.deint) + + if options.waterfall: + self.scope1=waterfallsink.waterfall_sink_c (self, panel, fft_size=1024, sample_rate=input_rate, + fft_rate=fft_rate) + self.scope2=waterfallsink.waterfall_sink_c (self, panel, fft_size=1024, sample_rate=input_rate, + fft_rate=fft_rate) + + elif options.oscilloscope: + self.scope1 = scopesink.scope_sink_c(self, panel, sample_rate=input_rate,frame_decim=options.frame_decim) # added option JPJ 4/21/2006 + self.scope2 = scopesink.scope_sink_c(self, panel, sample_rate=input_rate,frame_decim=options.frame_decim) + + else: + self.scope1 = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate, + fft_rate=fft_rate) + self.scope2 = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate, + fft_rate=fft_rate) + + # Show I, I' on top scope panel, Q, Q' on bottom + #self.fin = gr.complex_to_float() + #self.fout = gr.complex_to_float() + + #self.connect((self.deint,0), self.fin) + #self.connect((self.deint,1), self.fout) + + #self.ii = gr.float_to_complex() + #self.qq = gr.float_to_complex() + + #self.connect((self.fin,0), (self.ii,0)) + #self.connect((self.fout,0), (self.ii,1)) + #self.connect((self.fin,1), (self.qq,0)) + #self.connect((self.fout,1), (self.qq,1)) + + #self.connect(self.ii, self.scope1) + #self.connect(self.qq, self.scope2) + + self.connect ((self.deint,0),self.scope1) + self.connect ((self.deint,1),self.scope2) + + self._build_gui(vbox) + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdev.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdev.freq_range() + options.freq = float(r[0]+r[1])/2 + + self.set_gain(options.gain) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + if self.show_debug_info: + self.myform['decim'].set_value(self.u.decim_rate()) + self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) + self.myform['dbname'].set_value(self.subdev.name()) + + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + vbox.Add(self.scope1.win, 10, wx.EXPAND) + vbox.Add(self.scope2.win, 10, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0, 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0, 0) + g = self.subdev.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + hbox.Add((5,0), 0, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['decim'] = form.static_float_field( + parent=panel, sizer=hbox, label="Decim") + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = self.u.tune(0, self.subdev, target_freq) + + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + return True + + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdev.set_gain(gain) + + +def main (): + app = stdgui.stdapp(app_flow_graph, "USRP FFT", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/usrp/fpga/toplevel/mrfm/mrfm_proc.v b/usrp/fpga/toplevel/mrfm/mrfm_proc.v new file mode 100644 index 00000000..80de9fc9 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/mrfm_proc.v @@ -0,0 +1,96 @@ + +`include "mrfm.vh" +`include "../../../firmware/include/fpga_regs_common.v" +`include "../../../firmware/include/fpga_regs_standard.v" + +module mrfm_proc (input clock, input reset, input enable, + input [6:0] serial_addr, input [31:0] serial_data, input serial_strobe, + input [15:0] signal_in, output wire [15:0] signal_out, output wire sync_out, + output wire [15:0] i, output wire [15:0] q, + output wire [15:0] ip, output wire [15:0] qp, + output wire strobe_out, output wire [63:0] debugbus); + + // Strobes + wire sample_strobe, strobe_0, strobe_1, strobe_2; + assign sample_strobe = 1'b1; + wire [7:0] rate_0, rate_1, rate_2; + + setting_reg #(`FR_MRFM_DECIM) sr_decim(.clock(clock),.reset(reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out({rate_2,rate_1,rate_0})); + + strobe_gen strobe_gen_0 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(rate_0),.strobe_in(sample_strobe),.strobe(strobe_0) ); + strobe_gen strobe_gen_1 + ( .clock(clock),.reset(reset),.enable(enable), + .rate(rate_1),.strobe_in(strobe_0),.strobe(strobe_1) ); + + wire [31:0] phase; + + assign sync_out = phase[31]; + wire [15:0] i_decim_0, i_decim_1, i_decim_2; + wire [15:0] q_decim_0, q_decim_1, q_decim_2; + + wire [15:0] i_interp_0, i_interp_1, i_interp_2; + wire [15:0] q_interp_0, q_interp_1, q_interp_2; + + wire [15:0] i_filt, q_filt, i_comp, q_comp; + + assign ip=i_comp; + assign qp=q_comp; + + phase_acc #(`FR_MRFM_FREQ,`FR_MRFM_PHASE,32) rx_phase_acc + (.clk(clock),.reset(reset),.enable(enable), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .strobe(sample_strobe),.phase(phase) ); + + cordic rx_cordic (.clock(clock),.reset(reset),.enable(enable), + .xi(signal_in),.yi(16'd0),.zi(phase[31:16]), + .xo(i_decim_0),.yo(q_decim_0),.zo() ); + + cic_decim cic_decim_i_0 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_0),.strobe_in(sample_strobe),.strobe_out(strobe_0), + .signal_in(i_decim_0),.signal_out(i_decim_1)); + cic_decim cic_decim_i_1 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_1),.strobe_in(strobe_0),.strobe_out(strobe_1), + .signal_in(i_decim_1),.signal_out(i)); + + cic_decim cic_decim_q_0 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_0),.strobe_in(sample_strobe),.strobe_out(strobe_0), + .signal_in(q_decim_0),.signal_out(q_decim_1)); + cic_decim cic_decim_q_1 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_1),.strobe_in(strobe_0),.strobe_out(strobe_1), + .signal_in(q_decim_1),.signal_out(q)); + + assign strobe_out = strobe_1; + + biquad_2stage iir_i (.clock(clock),.reset(reset),.strobe_in(strobe_1), + .serial_strobe(serial_strobe),.serial_addr(serial_addr),.serial_data(serial_data), + .sample_in(i),.sample_out(i_filt),.debugbus(debugbus)); + + biquad_2stage iir_q (.clock(clock),.reset(reset),.strobe_in(strobe_1), + .serial_strobe(serial_strobe),.serial_addr(serial_addr),.serial_data(serial_data), + .sample_in(q),.sample_out(q_filt),.debugbus()); + + mrfm_compensator compensator (.clock(clock),.reset(reset),.strobe_in(strobe_1), + .serial_strobe(serial_strobe),.serial_addr(serial_addr),.serial_data(serial_data), + .i_in(i_filt),.q_in(q_filt),.i_out(i_comp),.q_out(q_comp)); + + cic_interp cic_interp_i_0 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_1),.strobe_in(strobe_1),.strobe_out(strobe_0), + .signal_in(i_comp),.signal_out(i_interp_0)); + cic_interp cic_interp_i_1 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_0),.strobe_in(strobe_0),.strobe_out(sample_strobe), + .signal_in(i_interp_0),.signal_out(i_interp_1)); + + cic_interp cic_interp_q_0 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_1),.strobe_in(strobe_1),.strobe_out(strobe_0), + .signal_in(q_comp),.signal_out(q_interp_0)); + cic_interp cic_interp_q_1 (.clock(clock),.reset(reset),.enable(enable), + .rate(rate_0),.strobe_in(strobe_0),.strobe_out(sample_strobe), + .signal_in(q_interp_0),.signal_out(q_interp_1)); + + cordic tx_cordic (.clock(clock),.reset(reset),.enable(enable), + .xi(i_interp_1),.yi(q_interp_1),.zi(-phase[31:16]), + .xo(signal_out),.yo(),.zo() ); + +endmodule // mrfm_proc diff --git a/usrp/fpga/toplevel/mrfm/shifter.v b/usrp/fpga/toplevel/mrfm/shifter.v new file mode 100644 index 00000000..08d49db6 --- /dev/null +++ b/usrp/fpga/toplevel/mrfm/shifter.v @@ -0,0 +1,106 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2005,2006 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +module shifter(input wire [33:0] in, output wire [15:0] out, input wire [7:0] shift); + // Wish we could do assign out = in[15+shift:shift]; + + reg [15:0] quotient, remainder; + wire [15:0] out_unclipped; + reg [18:0] msbs; + wire in_range; + + always @* + case(shift) + 0 : quotient = in[15:0]; + 1 : quotient = in[16:1]; + 2 : quotient = in[17:2]; + 3 : quotient = in[18:3]; + 4 : quotient = in[19:4]; + 5 : quotient = in[20:5]; + 6 : quotient = in[21:6]; + 7 : quotient = in[22:7]; + 8 : quotient = in[23:8]; + 9 : quotient = in[24:9]; + 10 : quotient = in[25:10]; + 11 : quotient = in[26:11]; + 12 : quotient = in[27:12]; + 13 : quotient = in[28:13]; + 14 : quotient = in[29:14]; + 15 : quotient = in[30:15]; + 16 : quotient = in[31:16]; + 17 : quotient = in[32:17]; + 18 : quotient = in[33:18]; + default : quotient = in[15:0]; + endcase // case(shift) + + always @* + case(shift) + 0 : remainder = 16'b0; + 1 : remainder = {in[0],15'b0}; + 2 : remainder = {in[1:0],14'b0}; + 3 : remainder = {in[2:0],13'b0}; + 4 : remainder = {in[3:0],12'b0}; + 5 : remainder = {in[4:0],11'b0}; + 6 : remainder = {in[5:0],10'b0}; + 7 : remainder = {in[6:0],9'b0}; + 8 : remainder = {in[7:0],8'b0}; + 9 : remainder = {in[8:0],7'b0}; + 10 : remainder = {in[9:0],6'b0}; + 11 : remainder = {in[10:0],5'b0}; + 12 : remainder = {in[11:0],4'b0}; + 13 : remainder = {in[12:0],3'b0}; + 14 : remainder = {in[13:0],2'b0}; + 15 : remainder = {in[14:0],1'b0}; + 16 : remainder = in[15:0]; + 17 : remainder = in[16:1]; + 18 : remainder = in[17:2]; + default : remainder = 16'b0; + endcase // case(shift) + + always @* + case(shift) + 0 : msbs = in[33:15]; + 1 : msbs = {in[33],in[33:16]}; + 2 : msbs = {{2{in[33]}},in[33:17]}; + 3 : msbs = {{3{in[33]}},in[33:18]}; + 4 : msbs = {{4{in[33]}},in[33:19]}; + 5 : msbs = {{5{in[33]}},in[33:20]}; + 6 : msbs = {{6{in[33]}},in[33:21]}; + 7 : msbs = {{7{in[33]}},in[33:22]}; + 8 : msbs = {{8{in[33]}},in[33:23]}; + 9 : msbs = {{9{in[33]}},in[33:24]}; + 10 : msbs = {{10{in[33]}},in[33:25]}; + 11 : msbs = {{11{in[33]}},in[33:26]}; + 12 : msbs = {{12{in[33]}},in[33:27]}; + 13 : msbs = {{13{in[33]}},in[33:28]}; + 14 : msbs = {{14{in[33]}},in[33:29]}; + 15 : msbs = {{15{in[33]}},in[33:30]}; + 16 : msbs = {{16{in[33]}},in[33:31]}; + 17 : msbs = {{17{in[33]}},in[33:32]}; + 18 : msbs = {{18{in[33]}},in[33]}; + default : msbs = in[33:15]; + endcase // case(shift) + + assign in_range = &msbs | ~(|msbs); + assign out_unclipped = quotient + (in[33] & |remainder); + assign out = in_range ? out_unclipped : {in[33],{15{~in[33]}}}; + +endmodule // shifter diff --git a/usrp/fpga/toplevel/sizetest/sizetest.csf b/usrp/fpga/toplevel/sizetest/sizetest.csf new file mode 100644 index 00000000..4b724e7f --- /dev/null +++ b/usrp/fpga/toplevel/sizetest/sizetest.csf @@ -0,0 +1,160 @@ +COMPILER_SETTINGS +{ + IO_PLACEMENT_OPTIMIZATION = OFF; + ENABLE_DRC_SETTINGS = OFF; + PHYSICAL_SYNTHESIS_REGISTER_RETIMING = OFF; + PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION = OFF; + PHYSICAL_SYNTHESIS_COMBO_LOGIC = OFF; + DRC_FANOUT_EXCEEDING = 30; + DRC_REPORT_FANOUT_EXCEEDING = OFF; + DRC_TOP_FANOUT = 50; + DRC_REPORT_TOP_FANOUT = OFF; + RUN_DRC_DURING_COMPILATION = OFF; + ADV_NETLIST_OPT_RETIME_CORE_AND_IO = ON; + ADV_NETLIST_OPT_SYNTH_USE_FITTER_INFO = OFF; + ADV_NETLIST_OPT_SYNTH_GATE_RETIME = OFF; + ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP = OFF; + SMART_COMPILE_IGNORES_TDC_FOR_STRATIX_PLL_CHANGES = OFF; + MERGE_HEX_FILE = OFF; + TRUE_WYSIWYG_FLOW = OFF; + SEED = 1; + FINAL_PLACEMENT_OPTIMIZATION = AUTOMATICALLY; + FAMILY = Cyclone; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "LOWER TO 1ESB UPPER TO 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DEEP_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_SINGLE_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_WIDE_MODE_OUTPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4ESB"; + DPRAM_DEEP_MODE_OUTPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_INPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4"; + DPRAM_DEEP_MODE_INPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_OTHER_SIGNALS_EPXA4_10 = "DEFAULT OTHER ROUTING OPTIONS"; + DPRAM_OUTPUT_EPXA4_10 = "DEFAULT OUTPUT ROUTING OPTIONS"; + DPRAM_INPUT_EPXA4_10 = "DEFAULT INPUT ROUTING OPTIONS"; + STRIPE_TO_PLD_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PLD_TO_STRIPE_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PROCESSOR_DEBUG_EXTENSIONS_EPXA4_10 = "MEGALAB COLUMN 2"; + STRIPE_TO_PLD_BRIDGE_EPXA4_10 = "MEGALAB COLUMN 1"; + FAST_FIT_COMPILATION = OFF; + SIGNALPROBE_DURING_NORMAL_COMPILATION = OFF; + OPTIMIZE_IOC_REGISTER_PLACEMENT_FOR_TIMING = OFF; + OPTIMIZE_TIMING = OFF; + OPTIMIZE_HOLD_TIMING = OFF; + COMPILATION_LEVEL = FULL; + SAVE_DISK_SPACE = ON; + SPEED_DISK_USAGE_TRADEOFF = NORMAL; + LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT = OFF; + SIGNALPROBE_ALLOW_OVERUSE = OFF; + FOCUS_ENTITY_NAME = |sizetest; + FIT_ONLY_ONE_ATTEMPT = OFF; +} +DEFAULT_DEVICE_OPTIONS +{ + GENERATE_CONFIG_HEXOUT_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_JBC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_SVF_FILE = OFF; + RESERVE_PIN = "AS INPUT TRI-STATED"; + RESERVE_ALL_UNUSED_PINS = "AS OUTPUT DRIVING GROUND"; + HEXOUT_FILE_COUNT_DIRECTION = UP; + HEXOUT_FILE_START_ADDRESS = 0; + GENERATE_HEX_FILE = OFF; + GENERATE_RBF_FILE = OFF; + GENERATE_TTF_FILE = OFF; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + APEX20K_CONFIGURATION_DEVICE = AUTO; + USE_CONFIGURATION_DEVICE = ON; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + AUTO_RESTART_CONFIGURATION = OFF; + ENABLE_VREFB_PIN = OFF; + ENABLE_VREFA_PIN = OFF; + SECURITY_BIT = OFF; + USER_START_UP_CLOCK = OFF; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "ACTIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_UPDATE_MODE = STANDARD; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + ENABLE_JTAG_BST_SUPPORT = OFF; + CONFIGURATION_CLOCK_DIVISOR = 1; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CLOCK_SOURCE = INTERNAL; + COMPRESSION_MODE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; +} +AUTO_SLD_HUB_ENTITY +{ + AUTO_INSERT_SLD_HUB_ENTITY = ENABLE; + HUB_INSTANCE_NAME = SLD_HUB_INST; + HUB_ENTITY_NAME = SLD_HUB; +} +CHIP(sizetest) +{ + DEVICE = EP1C12Q240C8; + DEVICE_FILTER_PACKAGE = "ANY QFP"; + DEVICE_FILTER_PIN_COUNT = 240; + DEVICE_FILTER_SPEED_GRADE = ANY; +} +SIGNALTAP_LOGIC_ANALYZER_SETTINGS +{ + ENABLE_SIGNALTAP = Off; + AUTO_ENABLE_SMART_COMPILE = On; +} diff --git a/usrp/fpga/toplevel/sizetest/sizetest.psf b/usrp/fpga/toplevel/sizetest/sizetest.psf new file mode 100644 index 00000000..e4fc6aa2 --- /dev/null +++ b/usrp/fpga/toplevel/sizetest/sizetest.psf @@ -0,0 +1,228 @@ +DEFAULT_DESIGN_ASSISTANT_SETTINGS +{ + HCPY_ALOAD_SIGNALS = OFF; + HCPY_VREF_PINS = OFF; + HCPY_CAT = OFF; + HCPY_ILLEGAL_HC_DEV_PKG = OFF; + ACLK_RULE_IMSZER_ADOMAIN = OFF; + ACLK_RULE_SZER_BTW_ACLK_DOMAIN = OFF; + ACLK_RULE_NO_SZER_ACLK_DOMAIN = OFF; + ACLK_CAT = OFF; + SIGNALRACE_RULE_ASYNCHPIN_SYNCH_CLKPIN = OFF; + SIGNALRACE_CAT = OFF; + NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED = OFF; + NONSYNCHSTRUCT_RULE_SRLATCH = OFF; + NONSYNCHSTRUCT_RULE_DLATCH = OFF; + NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR = OFF; + NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN = OFF; + NONSYNCHSTRUCT_RULE_RIPPLE_CLK = OFF; + NONSYNCHSTRUCT_RULE_DELAY_CHAIN = OFF; + NONSYNCHSTRUCT_RULE_REG_LOOP = OFF; + NONSYNCHSTRUCT_RULE_COMBLOOP = OFF; + NONSYNCHSTRUCT_CAT = OFF; + NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE = OFF; + TIMING_RULE_COIN_CLKEDGE = OFF; + TIMING_RULE_SHIFT_REG = OFF; + TIMING_RULE_HIGH_FANOUTS = OFF; + TIMING_CAT = OFF; + RESET_RULE_ALL = OFF; + RESET_RULE_IMSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_UNSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_REG_ASNYCH = OFF; + RESET_RULE_COMB_ASYNCH_RESET = OFF; + RESET_RULE_IMSYNCH_EXRESET = OFF; + RESET_RULE_UNSYNCH_EXRESET = OFF; + RESET_RULE_INPINS_RESETNET = OFF; + RESET_CAT = OFF; + CLK_RULE_ALL = OFF; + CLK_RULE_MIX_EDGES = OFF; + CLK_RULE_CLKNET_CLKSPINES = OFF; + CLK_RULE_INPINS_CLKNET = OFF; + CLK_RULE_GATING_SCHEME = OFF; + CLK_RULE_INV_CLOCK = OFF; + CLK_RULE_COMB_CLOCK = OFF; + CLK_CAT = OFF; + HCPY_EXCEED_USER_IO_USAGE = OFF; + HCPY_EXCEED_RAM_USAGE = OFF; + NONSYNCHSTRUCT_RULE_ASYN_RAM = OFF; + SIGNALRACE_RULE_TRISTATE = OFF; + ASSG_RULE_MISSING_TIMING = OFF; + ASSG_RULE_MISSING_FMAX = OFF; + ASSG_CAT = OFF; +} +SYNTHESIS_FITTING_SETTINGS +{ + AUTO_SHIFT_REGISTER_RECOGNITION = ON; + AUTO_RAM_RECOGNITION = ON; + REMOVE_DUPLICATE_LOGIC = ON; + AUTO_MERGE_PLLS = ON; + AUTO_OPEN_DRAIN_PINS = ON; + AUTO_CARRY_CHAINS = ON; + AUTO_DELAY_CHAINS = ON; + STRATIX_CARRY_CHAIN_LENGTH = 70; + AUTO_PACKED_REG_CYCLONE = "MINIMIZE AREA WITH CHAINS"; + CYCLONE_OPTIMIZATION_TECHNIQUE = SPEED; + AUTO_GLOBAL_MEMORY_CONTROLS = OFF; + AUTO_GLOBAL_REGISTER_CONTROLS = ON; + AUTO_GLOBAL_CLOCK = ON; + LIMIT_AHDL_INTEGERS_TO_32_BITS = OFF; + ENABLE_BUS_HOLD_CIRCUITRY = OFF; + WEAK_PULL_UP_RESISTOR = OFF; + IGNORE_SOFT_BUFFERS = ON; + IGNORE_LCELL_BUFFERS = OFF; + IGNORE_ROW_GLOBAL_BUFFERS = OFF; + IGNORE_GLOBAL_BUFFERS = OFF; + IGNORE_CASCADE_BUFFERS = OFF; + IGNORE_CARRY_BUFFERS = OFF; + REMOVE_DUPLICATE_REGISTERS = ON; + REMOVE_REDUNDANT_LOGIC_CELLS = OFF; + ALLOW_POWER_UP_DONT_CARE = ON; + PCI_IO = OFF; + NOT_GATE_PUSH_BACK = ON; + SLOW_SLEW_RATE = OFF; + STATE_MACHINE_PROCESSING = AUTO; +} +DEFAULT_HARDCOPY_SETTINGS +{ + HARDCOPY_EXTERNAL_CLOCK_JITTER = "0.0 NS"; +} +DEFAULT_TIMING_REQUIREMENTS +{ + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + RUN_ALL_TIMING_ANALYSES = ON; + IGNORE_CLOCK_SETTINGS = OFF; + DEFAULT_HOLD_MULTICYCLE = "SAME AS MULTICYCLE"; + CUT_OFF_IO_PIN_FEEDBACK = ON; + CUT_OFF_CLEAR_AND_PRESET_PATHS = ON; + CUT_OFF_READ_DURING_WRITE_PATHS = ON; + CUT_OFF_PATHS_BETWEEN_CLOCK_DOMAINS = ON; + DO_MIN_ANALYSIS = ON; + DO_MIN_TIMING = OFF; + NUMBER_OF_PATHS_TO_REPORT = 200; + NUMBER_OF_DESTINATION_TO_REPORT = 10; + NUMBER_OF_SOURCES_PER_DESTINATION_TO_REPORT = 10; + MAX_SCC_SIZE = 50; +} +HDL_SETTINGS +{ + VERILOG_INPUT_VERSION = VERILOG_2001; + ENABLE_IP_DEBUG = OFF; + VHDL_INPUT_VERSION = VHDL93; + VHDL_SHOW_LMF_MAPPING_MESSAGES = OFF; +} +PROJECT_INFO(sizetest) +{ + USER_LIBRARIES = "e:\fpga\megacells\"; + ORIGINAL_QUARTUS_VERSION = 3.0; + PROJECT_CREATION_TIME_DATE = "22:00:25 SEPTEMBER 28, 2003"; + LAST_QUARTUS_VERSION = 3.0; + SHOW_REGISTRATION_MESSAGE = ON; +} +THIRD_PARTY_EDA_TOOLS(sizetest) +{ + EDA_DESIGN_ENTRY_SYNTHESIS_TOOL = ""; + EDA_SIMULATION_TOOL = ""; + EDA_TIMING_ANALYSIS_TOOL = ""; + EDA_BOARD_DESIGN_TOOL = ""; + EDA_FORMAL_VERIFICATION_TOOL = ""; + EDA_RESYNTHESIS_TOOL = ""; +} +EDA_TOOL_SETTINGS(eda_design_synthesis) +{ + EDA_INPUT_GND_NAME = GND; + EDA_INPUT_VCC_NAME = VCC; + EDA_SHOW_LMF_MAPPING_MESSAGES = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_INPUT_DATA_FORMAT = EDIF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_simulation) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_timing_analysis) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + EDA_LAUNCH_CMD_LINE_TOOL = OFF; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_board_design) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_formal_verification) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_palace) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + RESYNTHESIS_RETIMING = FULL; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; +} diff --git a/usrp/fpga/toplevel/sizetest/sizetest.quartus b/usrp/fpga/toplevel/sizetest/sizetest.quartus new file mode 100644 index 00000000..d1eaf227 --- /dev/null +++ b/usrp/fpga/toplevel/sizetest/sizetest.quartus @@ -0,0 +1,19 @@ +COMPILER_SETTINGS_LIST +{ + COMPILER_SETTINGS = sizetest; +} +SIMULATOR_SETTINGS_LIST +{ + SIMULATOR_SETTINGS = sizetest; +} +SOFTWARE_SETTINGS_LIST +{ + SOFTWARE_SETTINGS = Debug; + SOFTWARE_SETTINGS = Release; +} +FILES +{ + VERILOG_FILE = ..\..\sdr_lib\cordic_stage.v; + VERILOG_FILE = ..\..\sdr_lib\cordic.v; + VERILOG_FILE = sizetest.v; +} diff --git a/usrp/fpga/toplevel/sizetest/sizetest.ssf b/usrp/fpga/toplevel/sizetest/sizetest.ssf new file mode 100644 index 00000000..1aceab1f --- /dev/null +++ b/usrp/fpga/toplevel/sizetest/sizetest.ssf @@ -0,0 +1,14 @@ +SIMULATOR_SETTINGS +{ + ESTIMATE_POWER_CONSUMPTION = OFF; + GLITCH_INTERVAL = 1NS; + GLITCH_DETECTION = OFF; + SIMULATION_COVERAGE = ON; + CHECK_OUTPUTS = OFF; + SETUP_HOLD_DETECTION = OFF; + POWER_ESTIMATION_START_TIME = "0 NS"; + ADD_DEFAULT_PINS_TO_SIMULATION_OUTPUT_WAVEFORMS = ON; + SIMULATION_MODE = TIMING; + START_TIME = 0NS; + USE_COMPILER_SETTINGS = sizetest; +} diff --git a/usrp/fpga/toplevel/sizetest/sizetest.v b/usrp/fpga/toplevel/sizetest/sizetest.v new file mode 100644 index 00000000..cdbd0861 --- /dev/null +++ b/usrp/fpga/toplevel/sizetest/sizetest.v @@ -0,0 +1,39 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +module sizetest(input clock, + input reset, + input enable, + input [15:0]xi, + input [15:0] yi, + input [15:0] zi, + output [15:0] xo, + output [15:0] yo, + output [15:0] zo +// input [15:0] constant + ); + +wire [16:0] zo; + +cordic_stage cordic_stage(clock, reset, enable, xi, yi, zi, 16'd16383, xo, yo, zo ); + +endmodule diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.csf b/usrp/fpga/toplevel/usrp_multi/usrp_multi.csf new file mode 100644 index 00000000..2f5df2bc --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.csf @@ -0,0 +1,444 @@ +COMPILER_SETTINGS +{ + IO_PLACEMENT_OPTIMIZATION = OFF; + ENABLE_DRC_SETTINGS = OFF; + PHYSICAL_SYNTHESIS_REGISTER_RETIMING = OFF; + PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION = OFF; + PHYSICAL_SYNTHESIS_COMBO_LOGIC = OFF; + DRC_FANOUT_EXCEEDING = 30; + DRC_REPORT_FANOUT_EXCEEDING = OFF; + DRC_TOP_FANOUT = 50; + DRC_REPORT_TOP_FANOUT = OFF; + RUN_DRC_DURING_COMPILATION = OFF; + ADV_NETLIST_OPT_RETIME_CORE_AND_IO = ON; + ADV_NETLIST_OPT_SYNTH_USE_FITTER_INFO = OFF; + ADV_NETLIST_OPT_SYNTH_GATE_RETIME = OFF; + ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP = OFF; + SMART_COMPILE_IGNORES_TDC_FOR_STRATIX_PLL_CHANGES = OFF; + MERGE_HEX_FILE = OFF; + TRUE_WYSIWYG_FLOW = OFF; + SEED = 1; + FINAL_PLACEMENT_OPTIMIZATION = AUTOMATICALLY; + FAMILY = Cyclone; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "LOWER TO 1ESB UPPER TO 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DEEP_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_SINGLE_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_WIDE_MODE_OUTPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4ESB"; + DPRAM_DEEP_MODE_OUTPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_INPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4"; + DPRAM_DEEP_MODE_INPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_OTHER_SIGNALS_EPXA4_10 = "DEFAULT OTHER ROUTING OPTIONS"; + DPRAM_OUTPUT_EPXA4_10 = "DEFAULT OUTPUT ROUTING OPTIONS"; + DPRAM_INPUT_EPXA4_10 = "DEFAULT INPUT ROUTING OPTIONS"; + STRIPE_TO_PLD_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PLD_TO_STRIPE_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PROCESSOR_DEBUG_EXTENSIONS_EPXA4_10 = "MEGALAB COLUMN 2"; + STRIPE_TO_PLD_BRIDGE_EPXA4_10 = "MEGALAB COLUMN 1"; + FAST_FIT_COMPILATION = OFF; + SIGNALPROBE_DURING_NORMAL_COMPILATION = OFF; + OPTIMIZE_IOC_REGISTER_PLACEMENT_FOR_TIMING = ON; + OPTIMIZE_TIMING = "NORMAL COMPILATION"; + OPTIMIZE_HOLD_TIMING = OFF; + COMPILATION_LEVEL = FULL; + SAVE_DISK_SPACE = OFF; + SPEED_DISK_USAGE_TRADEOFF = NORMAL; + LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT = OFF; + SIGNALPROBE_ALLOW_OVERUSE = OFF; + FOCUS_ENTITY_NAME = |usrp_multi; + ROUTING_BACK_ANNOTATION_MODE = OFF; + INC_PLC_MODE = OFF; + FIT_ONLY_ONE_ATTEMPT = OFF; +} +DEFAULT_DEVICE_OPTIONS +{ + GENERATE_CONFIG_HEXOUT_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_JBC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_SVF_FILE = OFF; + RESERVE_PIN = "AS INPUT TRI-STATED"; + RESERVE_ALL_UNUSED_PINS = "AS OUTPUT DRIVING GROUND"; + HEXOUT_FILE_COUNT_DIRECTION = UP; + HEXOUT_FILE_START_ADDRESS = 0; + GENERATE_HEX_FILE = OFF; + GENERATE_RBF_FILE = OFF; + GENERATE_TTF_FILE = OFF; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + APEX20K_CONFIGURATION_DEVICE = AUTO; + USE_CONFIGURATION_DEVICE = ON; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + AUTO_RESTART_CONFIGURATION = OFF; + ENABLE_VREFB_PIN = OFF; + ENABLE_VREFA_PIN = OFF; + SECURITY_BIT = OFF; + USER_START_UP_CLOCK = OFF; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "ACTIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_UPDATE_MODE = STANDARD; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + ENABLE_JTAG_BST_SUPPORT = OFF; + CONFIGURATION_CLOCK_DIVISOR = 1; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CLOCK_SOURCE = INTERNAL; + COMPRESSION_MODE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; +} +AUTO_SLD_HUB_ENTITY +{ + AUTO_INSERT_SLD_HUB_ENTITY = ENABLE; + HUB_INSTANCE_NAME = SLD_HUB_INST; + HUB_ENTITY_NAME = SLD_HUB; +} +SIGNALTAP_LOGIC_ANALYZER_SETTINGS +{ + ENABLE_SIGNALTAP = Off; + AUTO_ENABLE_SMART_COMPILE = On; +} +CHIP(usrp_multi) +{ + DEVICE = EP1C12Q240C8; + DEVICE_FILTER_PACKAGE = "ANY QFP"; + DEVICE_FILTER_PIN_COUNT = 240; + DEVICE_FILTER_SPEED_GRADE = ANY; + AUTO_RESTART_CONFIGURATION = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + USER_START_UP_CLOCK = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_JTAG_BST_SUPPORT = OFF; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + USE_CONFIGURATION_DEVICE = OFF; + APEX20K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + STRATIX_UPDATE_MODE = STANDARD; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + COMPRESSION_MODE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + GENERATE_TTF_FILE = OFF; + GENERATE_RBF_FILE = ON; + GENERATE_HEX_FILE = OFF; + SECURITY_BIT = OFF; + ENABLE_VREFA_PIN = OFF; + ENABLE_VREFB_PIN = OFF; + GENERATE_SVF_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_JBC_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_HEXOUT_FILE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; + BASE_PIN_OUT_FILE_ON_SAMEFRAME_DEVICE = OFF; + HEXOUT_FILE_START_ADDRESS = 0; + HEXOUT_FILE_COUNT_DIRECTION = UP; + RESERVE_ALL_UNUSED_PINS = "AS INPUT TRI-STATED"; + STRATIX_DEVICE_IO_STANDARD = LVTTL; + CLOCK_SOURCE = INTERNAL; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CONFIGURATION_CLOCK_DIVISOR = 1; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + SCLK : LOCATION = Pin_101; + SDI : LOCATION = Pin_100; + SEN : LOCATION = Pin_98; + SLD : LOCATION = Pin_95; + adc1_data[0] : LOCATION = Pin_5; + adc1_data[10] : LOCATION = Pin_235; + adc1_data[11] : LOCATION = Pin_234; + adc1_data[1] : LOCATION = Pin_4; + adc1_data[2] : LOCATION = Pin_3; + adc1_data[3] : LOCATION = Pin_2; + adc1_data[4] : LOCATION = Pin_1; + adc1_data[4] : IO_STANDARD = LVTTL; + adc1_data[5] : LOCATION = Pin_240; + adc1_data[6] : LOCATION = Pin_239; + adc1_data[7] : LOCATION = Pin_238; + adc1_data[8] : LOCATION = Pin_237; + adc1_data[9] : LOCATION = Pin_236; + adc2_data[0] : LOCATION = Pin_20; + adc2_data[10] : LOCATION = Pin_8; + adc2_data[11] : LOCATION = Pin_7; + adc2_data[1] : LOCATION = Pin_19; + adc2_data[2] : LOCATION = Pin_18; + adc2_data[3] : LOCATION = Pin_17; + adc2_data[4] : LOCATION = Pin_16; + adc2_data[5] : LOCATION = Pin_15; + adc2_data[6] : LOCATION = Pin_14; + adc2_data[7] : LOCATION = Pin_13; + adc2_data[8] : LOCATION = Pin_12; + adc2_data[9] : LOCATION = Pin_11; + adc3_data[0] : LOCATION = Pin_200; + adc3_data[10] : LOCATION = Pin_184; + adc3_data[11] : LOCATION = Pin_183; + adc3_data[1] : LOCATION = Pin_197; + adc3_data[2] : LOCATION = Pin_196; + adc3_data[3] : LOCATION = Pin_195; + adc3_data[4] : LOCATION = Pin_194; + adc3_data[5] : LOCATION = Pin_193; + adc3_data[6] : LOCATION = Pin_188; + adc3_data[7] : LOCATION = Pin_187; + adc3_data[8] : LOCATION = Pin_186; + adc3_data[9] : LOCATION = Pin_185; + adc4_data[0] : LOCATION = Pin_222; + adc4_data[10] : LOCATION = Pin_203; + adc4_data[11] : LOCATION = Pin_202; + adc4_data[1] : LOCATION = Pin_219; + adc4_data[2] : LOCATION = Pin_217; + adc4_data[3] : LOCATION = Pin_216; + adc4_data[4] : LOCATION = Pin_215; + adc4_data[5] : LOCATION = Pin_214; + adc4_data[6] : LOCATION = Pin_213; + adc4_data[7] : LOCATION = Pin_208; + adc4_data[8] : LOCATION = Pin_207; + adc4_data[9] : LOCATION = Pin_206; + adc_oeb[0] : LOCATION = Pin_228; + adc_oeb[1] : LOCATION = Pin_21; + adc_oeb[2] : LOCATION = Pin_181; + adc_oeb[3] : LOCATION = Pin_218; + adc_otr[0] : LOCATION = Pin_233; + adc_otr[1] : LOCATION = Pin_6; + adc_otr[2] : LOCATION = Pin_182; + adc_otr[3] : LOCATION = Pin_201; + adclk0 : LOCATION = Pin_224; + adclk1 : LOCATION = Pin_226; + clk0 : LOCATION = Pin_28; + clk0 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk0 : IO_STANDARD = LVTTL; + clk1 : LOCATION = Pin_29; + clk1 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk1 : IO_STANDARD = LVTTL; + clk3 : LOCATION = Pin_152; + clk3 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk3 : IO_STANDARD = LVTTL; + clk_120mhz : LOCATION = Pin_153; + clk_120mhz : IO_STANDARD = LVTTL; + clk_out : LOCATION = Pin_63; + clk_out : IO_STANDARD = LVTTL; + dac1_data[0] : LOCATION = Pin_165; + dac1_data[10] : LOCATION = Pin_177; + dac1_data[11] : LOCATION = Pin_178; + dac1_data[12] : LOCATION = Pin_179; + dac1_data[13] : LOCATION = Pin_180; + dac1_data[1] : LOCATION = Pin_166; + dac1_data[2] : LOCATION = Pin_167; + dac1_data[3] : LOCATION = Pin_168; + dac1_data[4] : LOCATION = Pin_169; + dac1_data[5] : LOCATION = Pin_170; + dac1_data[6] : LOCATION = Pin_173; + dac1_data[7] : LOCATION = Pin_174; + dac1_data[8] : LOCATION = Pin_175; + dac1_data[9] : LOCATION = Pin_176; + dac2_data[0] : LOCATION = Pin_159; + dac2_data[10] : LOCATION = Pin_163; + dac2_data[11] : LOCATION = Pin_139; + dac2_data[12] : LOCATION = Pin_164; + dac2_data[13] : LOCATION = Pin_138; + dac2_data[1] : LOCATION = Pin_158; + dac2_data[2] : LOCATION = Pin_160; + dac2_data[3] : LOCATION = Pin_156; + dac2_data[4] : LOCATION = Pin_161; + dac2_data[5] : LOCATION = Pin_144; + dac2_data[6] : LOCATION = Pin_162; + dac2_data[7] : LOCATION = Pin_141; + dac2_data[8] : LOCATION = Pin_143; + dac2_data[9] : LOCATION = Pin_140; + dac3_data[0] : LOCATION = Pin_122; + dac3_data[10] : LOCATION = Pin_134; + dac3_data[11] : LOCATION = Pin_135; + dac3_data[12] : LOCATION = Pin_136; + dac3_data[13] : LOCATION = Pin_137; + dac3_data[1] : LOCATION = Pin_123; + dac3_data[2] : LOCATION = Pin_124; + dac3_data[3] : LOCATION = Pin_125; + dac3_data[4] : LOCATION = Pin_126; + dac3_data[5] : LOCATION = Pin_127; + dac3_data[6] : LOCATION = Pin_128; + dac3_data[7] : LOCATION = Pin_131; + dac3_data[8] : LOCATION = Pin_132; + dac3_data[9] : LOCATION = Pin_133; + dac4_data[0] : LOCATION = Pin_104; + dac4_data[10] : LOCATION = Pin_118; + dac4_data[11] : LOCATION = Pin_119; + dac4_data[12] : LOCATION = Pin_120; + dac4_data[13] : LOCATION = Pin_121; + dac4_data[1] : LOCATION = Pin_105; + dac4_data[2] : LOCATION = Pin_106; + dac4_data[3] : LOCATION = Pin_107; + dac4_data[4] : LOCATION = Pin_108; + dac4_data[5] : LOCATION = Pin_113; + dac4_data[6] : LOCATION = Pin_114; + dac4_data[7] : LOCATION = Pin_115; + dac4_data[8] : LOCATION = Pin_116; + dac4_data[9] : LOCATION = Pin_117; + enable_rx : LOCATION = Pin_88; + enable_tx : LOCATION = Pin_93; + gndbus[0] : LOCATION = Pin_223; + gndbus[0] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[0] : IO_STANDARD = LVTTL; + gndbus[1] : LOCATION = Pin_225; + gndbus[1] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[1] : IO_STANDARD = LVTTL; + gndbus[2] : LOCATION = Pin_227; + gndbus[2] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[2] : IO_STANDARD = LVTTL; + gndbus[3] : LOCATION = Pin_62; + gndbus[3] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[3] : IO_STANDARD = LVTTL; + gndbus[4] : LOCATION = Pin_64; + gndbus[4] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[4] : IO_STANDARD = LVTTL; + misc_pins[0] : LOCATION = Pin_87; + misc_pins[0] : IO_STANDARD = LVTTL; + misc_pins[10] : LOCATION = Pin_76; + misc_pins[10] : IO_STANDARD = LVTTL; + misc_pins[11] : LOCATION = Pin_74; + misc_pins[11] : IO_STANDARD = LVTTL; + misc_pins[1] : LOCATION = Pin_86; + misc_pins[1] : IO_STANDARD = LVTTL; + misc_pins[2] : LOCATION = Pin_85; + misc_pins[2] : IO_STANDARD = LVTTL; + misc_pins[3] : LOCATION = Pin_84; + misc_pins[3] : IO_STANDARD = LVTTL; + misc_pins[4] : LOCATION = Pin_83; + misc_pins[4] : IO_STANDARD = LVTTL; + misc_pins[5] : LOCATION = Pin_82; + misc_pins[5] : IO_STANDARD = LVTTL; + misc_pins[6] : LOCATION = Pin_79; + misc_pins[6] : IO_STANDARD = LVTTL; + misc_pins[7] : LOCATION = Pin_78; + misc_pins[7] : IO_STANDARD = LVTTL; + misc_pins[8] : LOCATION = Pin_77; + misc_pins[8] : IO_STANDARD = LVTTL; + misc_pins[9] : LOCATION = Pin_75; + misc_pins[9] : IO_STANDARD = LVTTL; + reset : LOCATION = Pin_94; + usbclk : LOCATION = Pin_55; + usbctl[0] : LOCATION = Pin_56; + usbctl[1] : LOCATION = Pin_54; + usbctl[2] : LOCATION = Pin_53; + usbctl[3] : LOCATION = Pin_58; + usbctl[4] : LOCATION = Pin_57; + usbctl[5] : LOCATION = Pin_44; + usbdata[0] : LOCATION = Pin_73; + usbdata[10] : LOCATION = Pin_41; + usbdata[11] : LOCATION = Pin_39; + usbdata[12] : LOCATION = Pin_38; + usbdata[12] : IO_STANDARD = LVTTL; + usbdata[13] : LOCATION = Pin_37; + usbdata[14] : LOCATION = Pin_24; + usbdata[15] : LOCATION = Pin_23; + usbdata[1] : LOCATION = Pin_68; + usbdata[2] : LOCATION = Pin_67; + usbdata[3] : LOCATION = Pin_66; + usbdata[4] : LOCATION = Pin_65; + usbdata[5] : LOCATION = Pin_61; + usbdata[6] : LOCATION = Pin_60; + usbdata[7] : LOCATION = Pin_59; + usbdata[8] : LOCATION = Pin_43; + usbdata[9] : LOCATION = Pin_42; + usbrdy[0] : LOCATION = Pin_45; + usbrdy[1] : LOCATION = Pin_46; + usbrdy[2] : LOCATION = Pin_47; + usbrdy[3] : LOCATION = Pin_48; + usbrdy[4] : LOCATION = Pin_49; + usbrdy[5] : LOCATION = Pin_50; + clear_status : LOCATION = Pin_99; +} diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.esf b/usrp/fpga/toplevel/usrp_multi/usrp_multi.esf new file mode 100644 index 00000000..df45f676 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.esf @@ -0,0 +1,14 @@ +SIMULATOR_SETTINGS +{ + ESTIMATE_POWER_CONSUMPTION = OFF; + GLITCH_INTERVAL = 1NS; + GLITCH_DETECTION = OFF; + SIMULATION_COVERAGE = ON; + CHECK_OUTPUTS = OFF; + SETUP_HOLD_DETECTION = OFF; + POWER_ESTIMATION_START_TIME = "0 NS"; + ADD_DEFAULT_PINS_TO_SIMULATION_OUTPUT_WAVEFORMS = ON; + SIMULATION_MODE = TIMING; + START_TIME = 0NS; + USE_COMPILER_SETTINGS = usrp_multi; +} diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.psf b/usrp/fpga/toplevel/usrp_multi/usrp_multi.psf new file mode 100644 index 00000000..68c2d12f --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.psf @@ -0,0 +1,312 @@ +DEFAULT_DESIGN_ASSISTANT_SETTINGS +{ + HCPY_ALOAD_SIGNALS = OFF; + HCPY_VREF_PINS = OFF; + HCPY_CAT = OFF; + HCPY_ILLEGAL_HC_DEV_PKG = OFF; + ACLK_RULE_IMSZER_ADOMAIN = OFF; + ACLK_RULE_SZER_BTW_ACLK_DOMAIN = OFF; + ACLK_RULE_NO_SZER_ACLK_DOMAIN = OFF; + ACLK_CAT = OFF; + SIGNALRACE_RULE_ASYNCHPIN_SYNCH_CLKPIN = OFF; + SIGNALRACE_CAT = OFF; + NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED = OFF; + NONSYNCHSTRUCT_RULE_SRLATCH = OFF; + NONSYNCHSTRUCT_RULE_DLATCH = OFF; + NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR = OFF; + NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN = OFF; + NONSYNCHSTRUCT_RULE_RIPPLE_CLK = OFF; + NONSYNCHSTRUCT_RULE_DELAY_CHAIN = OFF; + NONSYNCHSTRUCT_RULE_REG_LOOP = OFF; + NONSYNCHSTRUCT_RULE_COMBLOOP = OFF; + NONSYNCHSTRUCT_CAT = OFF; + NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE = OFF; + TIMING_RULE_COIN_CLKEDGE = OFF; + TIMING_RULE_SHIFT_REG = OFF; + TIMING_RULE_HIGH_FANOUTS = OFF; + TIMING_CAT = OFF; + RESET_RULE_ALL = OFF; + RESET_RULE_IMSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_UNSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_REG_ASNYCH = OFF; + RESET_RULE_COMB_ASYNCH_RESET = OFF; + RESET_RULE_IMSYNCH_EXRESET = OFF; + RESET_RULE_UNSYNCH_EXRESET = OFF; + RESET_RULE_INPINS_RESETNET = OFF; + RESET_CAT = OFF; + CLK_RULE_ALL = OFF; + CLK_RULE_MIX_EDGES = OFF; + CLK_RULE_CLKNET_CLKSPINES = OFF; + CLK_RULE_INPINS_CLKNET = OFF; + CLK_RULE_GATING_SCHEME = OFF; + CLK_RULE_INV_CLOCK = OFF; + CLK_RULE_COMB_CLOCK = OFF; + CLK_CAT = OFF; + HCPY_EXCEED_USER_IO_USAGE = OFF; + HCPY_EXCEED_RAM_USAGE = OFF; + NONSYNCHSTRUCT_RULE_ASYN_RAM = OFF; + SIGNALRACE_RULE_TRISTATE = OFF; + ASSG_RULE_MISSING_TIMING = OFF; + ASSG_RULE_MISSING_FMAX = OFF; + ASSG_CAT = OFF; +} +SYNTHESIS_FITTING_SETTINGS +{ + AUTO_SHIFT_REGISTER_RECOGNITION = ON; + AUTO_DSP_RECOGNITION = ON; + AUTO_RAM_RECOGNITION = ON; + REMOVE_DUPLICATE_LOGIC = ON; + AUTO_TURBO_BIT = ON; + AUTO_MERGE_PLLS = ON; + AUTO_OPEN_DRAIN_PINS = ON; + AUTO_PARALLEL_EXPANDERS = ON; + AUTO_FAST_OUTPUT_ENABLE_REGISTERS = OFF; + AUTO_FAST_OUTPUT_REGISTERS = OFF; + AUTO_FAST_INPUT_REGISTERS = OFF; + AUTO_CASCADE_CHAINS = ON; + AUTO_CARRY_CHAINS = ON; + AUTO_DELAY_CHAINS = ON; + MAX7000_PARALLEL_EXPANDER_CHAIN_LENGTH = 4; + PARALLEL_EXPANDER_CHAIN_LENGTH = 16; + CASCADE_CHAIN_LENGTH = 2; + STRATIX_CARRY_CHAIN_LENGTH = 70; + MERCURY_CARRY_CHAIN_LENGTH = 48; + FLEX10K_CARRY_CHAIN_LENGTH = 32; + FLEX6K_CARRY_CHAIN_LENGTH = 32; + CARRY_CHAIN_LENGTH = 48; + CARRY_OUT_PINS_LCELL_INSERT = ON; + NORMAL_LCELL_INSERT = ON; + AUTO_LCELL_INSERTION = ON; + ALLOW_XOR_GATE_USAGE = ON; + AUTO_PACKED_REGISTERS_STRATIX = NORMAL; + AUTO_PACKED_REGISTERS = OFF; + AUTO_PACKED_REG_CYCLONE = NORMAL; + FLEX10K_OPTIMIZATION_TECHNIQUE = AREA; + FLEX6K_OPTIMIZATION_TECHNIQUE = AREA; + MERCURY_OPTIMIZATION_TECHNIQUE = AREA; + APEX20K_OPTIMIZATION_TECHNIQUE = SPEED; + MAX7000_OPTIMIZATION_TECHNIQUE = SPEED; + STRATIX_OPTIMIZATION_TECHNIQUE = SPEED; + CYCLONE_OPTIMIZATION_TECHNIQUE = AREA; + FLEX10K_TECHNOLOGY_MAPPER = LUT; + FLEX6K_TECHNOLOGY_MAPPER = LUT; + MERCURY_TECHNOLOGY_MAPPER = LUT; + APEX20K_TECHNOLOGY_MAPPER = LUT; + MAX7000_TECHNOLOGY_MAPPER = "PRODUCT TERM"; + STRATIX_TECHNOLOGY_MAPPER = LUT; + AUTO_IMPLEMENT_IN_ROM = OFF; + AUTO_GLOBAL_MEMORY_CONTROLS = OFF; + AUTO_GLOBAL_REGISTER_CONTROLS = ON; + AUTO_GLOBAL_OE = ON; + AUTO_GLOBAL_CLOCK = ON; + USE_LPM_FOR_AHDL_OPERATORS = ON; + LIMIT_AHDL_INTEGERS_TO_32_BITS = OFF; + ENABLE_BUS_HOLD_CIRCUITRY = OFF; + WEAK_PULL_UP_RESISTOR = OFF; + TURBO_BIT = ON; + MAX7000_IGNORE_SOFT_BUFFERS = OFF; + IGNORE_SOFT_BUFFERS = ON; + MAX7000_IGNORE_LCELL_BUFFERS = AUTO; + IGNORE_LCELL_BUFFERS = OFF; + IGNORE_ROW_GLOBAL_BUFFERS = OFF; + IGNORE_GLOBAL_BUFFERS = OFF; + IGNORE_CASCADE_BUFFERS = OFF; + IGNORE_CARRY_BUFFERS = OFF; + REMOVE_DUPLICATE_REGISTERS = ON; + REMOVE_REDUNDANT_LOGIC_CELLS = OFF; + ALLOW_POWER_UP_DONT_CARE = ON; + PCI_IO = OFF; + NOT_GATE_PUSH_BACK = ON; + SLOW_SLEW_RATE = OFF; + DSP_BLOCK_BALANCING = AUTO; + STATE_MACHINE_PROCESSING = AUTO; +} +DEFAULT_HARDCOPY_SETTINGS +{ + HARDCOPY_EXTERNAL_CLOCK_JITTER = "0.0 NS"; +} +DEFAULT_TIMING_REQUIREMENTS +{ + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + RUN_ALL_TIMING_ANALYSES = ON; + IGNORE_CLOCK_SETTINGS = OFF; + DEFAULT_HOLD_MULTICYCLE = "SAME AS MULTICYCLE"; + CUT_OFF_IO_PIN_FEEDBACK = ON; + CUT_OFF_CLEAR_AND_PRESET_PATHS = ON; + CUT_OFF_READ_DURING_WRITE_PATHS = ON; + CUT_OFF_PATHS_BETWEEN_CLOCK_DOMAINS = ON; + DO_MIN_ANALYSIS = ON; + DO_MIN_TIMING = OFF; + NUMBER_OF_PATHS_TO_REPORT = 200; + NUMBER_OF_DESTINATION_TO_REPORT = 10; + NUMBER_OF_SOURCES_PER_DESTINATION_TO_REPORT = 10; + MAX_SCC_SIZE = 50; +} +HDL_SETTINGS +{ + VERILOG_INPUT_VERSION = VERILOG_2001; + ENABLE_IP_DEBUG = OFF; + VHDL_INPUT_VERSION = VHDL93; + VHDL_SHOW_LMF_MAPPING_MESSAGES = OFF; +} +PROJECT_INFO(usrp_multi) +{ + ORIGINAL_QUARTUS_VERSION = 3.0; + PROJECT_CREATION_TIME_DATE = "00:14:04 JULY 13, 2003"; + LAST_QUARTUS_VERSION = 3.0; + SHOW_REGISTRATION_MESSAGE = ON; + USER_LIBRARIES = "e:\usrp\fpga\megacells"; +} +THIRD_PARTY_EDA_TOOLS(usrp_multi) +{ + EDA_DESIGN_ENTRY_SYNTHESIS_TOOL = ""; + EDA_SIMULATION_TOOL = ""; + EDA_TIMING_ANALYSIS_TOOL = ""; + EDA_BOARD_DESIGN_TOOL = ""; + EDA_FORMAL_VERIFICATION_TOOL = ""; + EDA_RESYNTHESIS_TOOL = ""; +} +EDA_TOOL_SETTINGS(eda_design_synthesis) +{ + EDA_INPUT_GND_NAME = GND; + EDA_INPUT_VCC_NAME = VCC; + EDA_SHOW_LMF_MAPPING_MESSAGES = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_INPUT_DATA_FORMAT = EDIF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_simulation) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_timing_analysis) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + EDA_LAUNCH_CMD_LINE_TOOL = OFF; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_board_design) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_formal_verification) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_palace) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + RESYNTHESIS_RETIMING = FULL; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; +} +CLOCK(clk_120mhz) +{ + FMAX_REQUIREMENT = "120.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(usbclk) +{ + FMAX_REQUIREMENT = "48.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(SCLK) +{ + FMAX_REQUIREMENT = "1.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(adclk0) +{ + FMAX_REQUIREMENT = "60.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(adclk1) +{ + FMAX_REQUIREMENT = "60.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.qpf b/usrp/fpga/toplevel/usrp_multi/usrp_multi.qpf new file mode 100644 index 00000000..1524de1b --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.qpf @@ -0,0 +1,29 @@ +# Copyright (C) 1991-2004 Altera Corporation +# Any megafunction design, and related netlist (encrypted or decrypted), +# support information, device programming or simulation file, and any other +# associated documentation or information provided by Altera or a partner +# under Altera's Megafunction Partnership Program may be used only +# to program PLD devices (but not masked PLD devices) from Altera. Any +# other use of such megafunction design, netlist, support information, +# device programming or simulation file, or any other related documentation +# or information is prohibited for any other purpose, including, but not +# limited to modification, reverse engineering, de-compiling, or use with +# any other silicon devices, unless such use is explicitly licensed under +# a separate agreement with Altera or a megafunction partner. Title to the +# intellectual property, including patents, copyrights, trademarks, trade +# secrets, or maskworks, embodied in any such megafunction design, netlist, +# support information, device programming or simulation file, or any other +# related documentation or information provided by Altera or a megafunction +# partner, remains with Altera, the megafunction partner, or their respective +# licensors. No other licenses, including any licenses needed under any third +# party's intellectual property, are provided herein. + + + +QUARTUS_VERSION = "4.0" +DATE = "17:10:11 December 20, 2004" + + +# Active Revisions + +PROJECT_REVISION = "usrp_multi" diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.qsf b/usrp/fpga/toplevel/usrp_multi/usrp_multi.qsf new file mode 100644 index 00000000..e45c683a --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.qsf @@ -0,0 +1,408 @@ +# Copyright (C) 1991-2005 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. + + +# The default values for assignments are stored in the file +# usrp_multi_assignment_defaults.qdf +# If this file doesn't exist, and for assignments not listed, see file +# assignment_defaults.qdf + +# Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 3.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "00:14:04 JULY 13, 2003" +set_global_assignment -name LAST_QUARTUS_VERSION "5.1 SP1" + +# Pin & Location Assignments +# ========================== +set_global_assignment -name RESERVE_PIN "AS INPUT TRI-STATED" +set_location_assignment PIN_29 -to SCLK +set_location_assignment PIN_117 -to SDI +set_location_assignment PIN_28 -to usbclk +set_location_assignment PIN_107 -to usbctl[0] +set_location_assignment PIN_106 -to usbctl[1] +set_location_assignment PIN_105 -to usbctl[2] +set_location_assignment PIN_100 -to usbdata[0] +set_location_assignment PIN_84 -to usbdata[10] +set_location_assignment PIN_83 -to usbdata[11] +set_location_assignment PIN_82 -to usbdata[12] +set_location_assignment PIN_79 -to usbdata[13] +set_location_assignment PIN_78 -to usbdata[14] +set_location_assignment PIN_77 -to usbdata[15] +set_location_assignment PIN_99 -to usbdata[1] +set_location_assignment PIN_98 -to usbdata[2] +set_location_assignment PIN_95 -to usbdata[3] +set_location_assignment PIN_94 -to usbdata[4] +set_location_assignment PIN_93 -to usbdata[5] +set_location_assignment PIN_88 -to usbdata[6] +set_location_assignment PIN_87 -to usbdata[7] +set_location_assignment PIN_86 -to usbdata[8] +set_location_assignment PIN_85 -to usbdata[9] +set_location_assignment PIN_104 -to usbrdy[0] +set_location_assignment PIN_101 -to usbrdy[1] +set_location_assignment PIN_76 -to FX2_1 +set_location_assignment PIN_75 -to FX2_2 +set_location_assignment PIN_74 -to FX2_3 +set_location_assignment PIN_116 -to io_rx_a[0] +set_location_assignment PIN_115 -to io_rx_a[1] +set_location_assignment PIN_114 -to io_rx_a[2] +set_location_assignment PIN_113 -to io_rx_a[3] +set_location_assignment PIN_108 -to io_rx_a[4] +set_location_assignment PIN_195 -to io_rx_a[5] +set_location_assignment PIN_196 -to io_rx_a[6] +set_location_assignment PIN_197 -to io_rx_a[7] +set_location_assignment PIN_200 -to io_rx_a[8] +set_location_assignment PIN_201 -to io_rx_a[9] +set_location_assignment PIN_202 -to io_rx_a[10] +set_location_assignment PIN_203 -to io_rx_a[11] +set_location_assignment PIN_206 -to io_rx_a[12] +set_location_assignment PIN_207 -to io_rx_a[13] +set_location_assignment PIN_208 -to io_rx_a[14] +set_location_assignment PIN_214 -to io_rx_b[0] +set_location_assignment PIN_215 -to io_rx_b[1] +set_location_assignment PIN_216 -to io_rx_b[2] +set_location_assignment PIN_217 -to io_rx_b[3] +set_location_assignment PIN_218 -to io_rx_b[4] +set_location_assignment PIN_219 -to io_rx_b[5] +set_location_assignment PIN_222 -to io_rx_b[6] +set_location_assignment PIN_223 -to io_rx_b[7] +set_location_assignment PIN_224 -to io_rx_b[8] +set_location_assignment PIN_225 -to io_rx_b[9] +set_location_assignment PIN_226 -to io_rx_b[10] +set_location_assignment PIN_227 -to io_rx_b[11] +set_location_assignment PIN_228 -to io_rx_b[12] +set_location_assignment PIN_233 -to io_rx_b[13] +set_location_assignment PIN_234 -to io_rx_b[14] +set_location_assignment PIN_175 -to io_tx_a[0] +set_location_assignment PIN_176 -to io_tx_a[1] +set_location_assignment PIN_177 -to io_tx_a[2] +set_location_assignment PIN_178 -to io_tx_a[3] +set_location_assignment PIN_179 -to io_tx_a[4] +set_location_assignment PIN_180 -to io_tx_a[5] +set_location_assignment PIN_181 -to io_tx_a[6] +set_location_assignment PIN_182 -to io_tx_a[7] +set_location_assignment PIN_183 -to io_tx_a[8] +set_location_assignment PIN_184 -to io_tx_a[9] +set_location_assignment PIN_185 -to io_tx_a[10] +set_location_assignment PIN_186 -to io_tx_a[11] +set_location_assignment PIN_187 -to io_tx_a[12] +set_location_assignment PIN_188 -to io_tx_a[13] +set_location_assignment PIN_193 -to io_tx_a[14] +set_location_assignment PIN_73 -to io_tx_b[0] +set_location_assignment PIN_68 -to io_tx_b[1] +set_location_assignment PIN_67 -to io_tx_b[2] +set_location_assignment PIN_66 -to io_tx_b[3] +set_location_assignment PIN_65 -to io_tx_b[4] +set_location_assignment PIN_64 -to io_tx_b[5] +set_location_assignment PIN_63 -to io_tx_b[6] +set_location_assignment PIN_62 -to io_tx_b[7] +set_location_assignment PIN_61 -to io_tx_b[8] +set_location_assignment PIN_60 -to io_tx_b[9] +set_location_assignment PIN_59 -to io_tx_b[10] +set_location_assignment PIN_58 -to io_tx_b[11] +set_location_assignment PIN_57 -to io_tx_b[12] +set_location_assignment PIN_56 -to io_tx_b[13] +set_location_assignment PIN_55 -to io_tx_b[14] +set_location_assignment PIN_152 -to master_clk +set_location_assignment PIN_144 -to rx_a_a[0] +set_location_assignment PIN_143 -to rx_a_a[1] +set_location_assignment PIN_141 -to rx_a_a[2] +set_location_assignment PIN_140 -to rx_a_a[3] +set_location_assignment PIN_139 -to rx_a_a[4] +set_location_assignment PIN_138 -to rx_a_a[5] +set_location_assignment PIN_137 -to rx_a_a[6] +set_location_assignment PIN_136 -to rx_a_a[7] +set_location_assignment PIN_135 -to rx_a_a[8] +set_location_assignment PIN_134 -to rx_a_a[9] +set_location_assignment PIN_133 -to rx_a_a[10] +set_location_assignment PIN_132 -to rx_a_a[11] +set_location_assignment PIN_23 -to rx_a_b[0] +set_location_assignment PIN_21 -to rx_a_b[1] +set_location_assignment PIN_20 -to rx_a_b[2] +set_location_assignment PIN_19 -to rx_a_b[3] +set_location_assignment PIN_18 -to rx_a_b[4] +set_location_assignment PIN_17 -to rx_a_b[5] +set_location_assignment PIN_16 -to rx_a_b[6] +set_location_assignment PIN_15 -to rx_a_b[7] +set_location_assignment PIN_14 -to rx_a_b[8] +set_location_assignment PIN_13 -to rx_a_b[9] +set_location_assignment PIN_12 -to rx_a_b[10] +set_location_assignment PIN_11 -to rx_a_b[11] +set_location_assignment PIN_131 -to rx_b_a[0] +set_location_assignment PIN_128 -to rx_b_a[1] +set_location_assignment PIN_127 -to rx_b_a[2] +set_location_assignment PIN_126 -to rx_b_a[3] +set_location_assignment PIN_125 -to rx_b_a[4] +set_location_assignment PIN_124 -to rx_b_a[5] +set_location_assignment PIN_123 -to rx_b_a[6] +set_location_assignment PIN_122 -to rx_b_a[7] +set_location_assignment PIN_121 -to rx_b_a[8] +set_location_assignment PIN_120 -to rx_b_a[9] +set_location_assignment PIN_119 -to rx_b_a[10] +set_location_assignment PIN_118 -to rx_b_a[11] +set_location_assignment PIN_8 -to rx_b_b[0] +set_location_assignment PIN_7 -to rx_b_b[1] +set_location_assignment PIN_6 -to rx_b_b[2] +set_location_assignment PIN_5 -to rx_b_b[3] +set_location_assignment PIN_4 -to rx_b_b[4] +set_location_assignment PIN_3 -to rx_b_b[5] +set_location_assignment PIN_2 -to rx_b_b[6] +set_location_assignment PIN_240 -to rx_b_b[7] +set_location_assignment PIN_239 -to rx_b_b[8] +set_location_assignment PIN_238 -to rx_b_b[9] +set_location_assignment PIN_237 -to rx_b_b[10] +set_location_assignment PIN_236 -to rx_b_b[11] +set_location_assignment PIN_156 -to SDO +set_location_assignment PIN_153 -to SEN_FPGA +set_location_assignment PIN_159 -to tx_a[0] +set_location_assignment PIN_160 -to tx_a[1] +set_location_assignment PIN_161 -to tx_a[2] +set_location_assignment PIN_162 -to tx_a[3] +set_location_assignment PIN_163 -to tx_a[4] +set_location_assignment PIN_164 -to tx_a[5] +set_location_assignment PIN_165 -to tx_a[6] +set_location_assignment PIN_166 -to tx_a[7] +set_location_assignment PIN_167 -to tx_a[8] +set_location_assignment PIN_168 -to tx_a[9] +set_location_assignment PIN_169 -to tx_a[10] +set_location_assignment PIN_170 -to tx_a[11] +set_location_assignment PIN_173 -to tx_a[12] +set_location_assignment PIN_174 -to tx_a[13] +set_location_assignment PIN_38 -to tx_b[0] +set_location_assignment PIN_39 -to tx_b[1] +set_location_assignment PIN_41 -to tx_b[2] +set_location_assignment PIN_42 -to tx_b[3] +set_location_assignment PIN_43 -to tx_b[4] +set_location_assignment PIN_44 -to tx_b[5] +set_location_assignment PIN_45 -to tx_b[6] +set_location_assignment PIN_46 -to tx_b[7] +set_location_assignment PIN_47 -to tx_b[8] +set_location_assignment PIN_48 -to tx_b[9] +set_location_assignment PIN_49 -to tx_b[10] +set_location_assignment PIN_50 -to tx_b[11] +set_location_assignment PIN_53 -to tx_b[12] +set_location_assignment PIN_54 -to tx_b[13] +set_location_assignment PIN_158 -to TXSYNC_A +set_location_assignment PIN_37 -to TXSYNC_B +set_location_assignment PIN_235 -to io_rx_b[15] +set_location_assignment PIN_24 -to io_tx_b[15] +set_location_assignment PIN_213 -to io_rx_a[15] +set_location_assignment PIN_194 -to io_tx_a[15] +set_location_assignment PIN_1 -to MYSTERY_SIGNAL + +# Timing Assignments +# ================== +set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 240 +set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "" +set_global_assignment -name FAMILY Cyclone +set_global_assignment -name CYCLONE_OPTIMIZATION_TECHNIQUE BALANCED +set_global_assignment -name STRATIX_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name APEX20K_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name TOP_LEVEL_ENTITY usrp_multi +set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name USER_LIBRARIES "H:\\usrp-for2.7\\fpga\\megacells" +set_global_assignment -name AUTO_ENABLE_SMART_COMPILE On + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP1C12Q240C8 +set_global_assignment -name CYCLONE_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" +set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF +set_global_assignment -name OPTIMIZE_TIMING "NORMAL COMPILATION" +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF +set_global_assignment -name IO_PLACEMENT_OPTIMIZATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL +set_global_assignment -name INC_PLC_MODE OFF +set_global_assignment -name ROUTING_BACK_ANNOTATION_MODE OFF +set_instance_assignment -name IO_STANDARD LVTTL -to usbdata[12] +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD LVTTL +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 + +# Timing Analysis Assignments +# =========================== +set_global_assignment -name MAX_SCC_SIZE 50 + +# EDA Netlist Writer Assignments +# ============================== +set_global_assignment -name EDA_SIMULATION_TOOL "" +set_global_assignment -name EDA_TIMING_ANALYSIS_TOOL "" +set_global_assignment -name EDA_BOARD_DESIGN_TOOL "" +set_global_assignment -name EDA_FORMAL_VERIFICATION_TOOL "" +set_global_assignment -name EDA_RESYNTHESIS_TOOL "" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "AS INPUT TRI-STATED" +set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF + +# Simulator Assignments +# ===================== +set_global_assignment -name START_TIME "0 ns" +set_global_assignment -name GLITCH_INTERVAL "1 ns" + +# Design Assistant Assignments +# ============================ +set_global_assignment -name DRC_REPORT_TOP_FANOUT OFF +set_global_assignment -name DRC_REPORT_FANOUT_EXCEEDING OFF +set_global_assignment -name ASSG_CAT OFF +set_global_assignment -name ASSG_RULE_MISSING_FMAX OFF +set_global_assignment -name ASSG_RULE_MISSING_TIMING OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ASYN_RAM OFF +set_global_assignment -name CLK_CAT OFF +set_global_assignment -name CLK_RULE_COMB_CLOCK OFF +set_global_assignment -name CLK_RULE_INV_CLOCK OFF +set_global_assignment -name CLK_RULE_GATING_SCHEME OFF +set_global_assignment -name CLK_RULE_INPINS_CLKNET OFF +set_global_assignment -name CLK_RULE_CLKNET_CLKSPINES OFF +set_global_assignment -name CLK_RULE_MIX_EDGES OFF +set_global_assignment -name RESET_CAT OFF +set_global_assignment -name RESET_RULE_INPINS_RESETNET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_IMSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_COMB_ASYNCH_RESET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name RESET_RULE_IMSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name TIMING_CAT OFF +set_global_assignment -name TIMING_RULE_SHIFT_REG OFF +set_global_assignment -name TIMING_RULE_COIN_CLKEDGE OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE OFF +set_global_assignment -name NONSYNCHSTRUCT_CAT OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMBLOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_REG_LOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_DELAY_CHAIN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_RIPPLE_CLK OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_SRLATCH OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED OFF +set_global_assignment -name SIGNALRACE_CAT OFF +set_global_assignment -name ACLK_CAT OFF +set_global_assignment -name ACLK_RULE_NO_SZER_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_SZER_BTW_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_IMSZER_ADOMAIN OFF +set_global_assignment -name HCPY_CAT OFF +set_global_assignment -name HCPY_VREF_PINS OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name HUB_ENTITY_NAME SLD_HUB +set_global_assignment -name HUB_INSTANCE_NAME SLD_HUB_INST +set_global_assignment -name ENABLE_SIGNALTAP Off + +# LogicLock Region Assignments +# ============================ +set_global_assignment -name LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT OFF + +# ----------------- +# start CLOCK(SCLK) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id SCLK + set_global_assignment -name FMAX_REQUIREMENT "1.0 MHz" -section_id SCLK + set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id SCLK + +# end CLOCK(SCLK) +# --------------- + +# ----------------------- +# start CLOCK(master_clk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id master_clk + set_global_assignment -name FMAX_REQUIREMENT "64.0 MHz" -section_id master_clk + set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id master_clk + +# end CLOCK(master_clk) +# --------------------- + +# ------------------- +# start CLOCK(usbclk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id usbclk + set_global_assignment -name FMAX_REQUIREMENT "48.0 MHz" -section_id usbclk + set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id usbclk + +# end CLOCK(usbclk) +# ----------------- + +# ---------------------- +# start ENTITY(usrp_multi) + + # Timing Assignments + # ================== + set_instance_assignment -name CLOCK_SETTINGS SCLK -to SCLK + set_instance_assignment -name CLOCK_SETTINGS usbclk -to usbclk + set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk + +# end ENTITY(usrp_multi) +# -------------------- + + +set_global_assignment -name VERILOG_FILE ../../sdr_lib/setting_reg_masked.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/master_control_multi.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/ram16.v +set_global_assignment -name VERILOG_FILE usrp_multi.vh +set_global_assignment -name VERILOG_FILE ../../megacells/fifo_4k.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/acc.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mult.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/ram16_2sum.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_rom.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/halfband_decim.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mac.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_ram.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_chain.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_dcoffset.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/adc_interface.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/io_pins.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/setting_reg.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/bidir_reg.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_int_shifter.v +set_global_assignment -name VERILOG_FILE ../../megacells/clk_doubler.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_chain.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/gen_sync.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/master_control.v +set_global_assignment -name VERILOG_FILE ../../megacells/fifo_2k.v +set_global_assignment -name VERILOG_FILE ../../megacells/bustri.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_buffer.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_buffer.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/phase_acc.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_interp.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_decim.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cordic_stage.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cordic.v +set_global_assignment -name VERILOG_FILE usrp_multi.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/clk_divider.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/serial_io.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/strobe_gen.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v \ No newline at end of file diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.v b/usrp/fpga/toplevel/usrp_multi/usrp_multi.v new file mode 100644 index 00000000..b27d3d3a --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.v @@ -0,0 +1,379 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003,2004,2005,2006 Matt Ettus +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Top level module for a full setup with DUCs and DDCs + +// Define DEBUG_OWNS_IO_PINS if we're using the daughterboard i/o pins +// for debugging info. NB, This can kill the m'board and/or d'board if you +// have anything except basic d'boards installed. + +// Uncomment the following to include optional circuitry + +`include "usrp_multi.vh" +`include "../../../firmware/include/fpga_regs_common.v" +`include "../../../firmware/include/fpga_regs_standard.v" + +module usrp_multi +(output MYSTERY_SIGNAL, + input master_clk, + input SCLK, + input SDI, + inout SDO, + input SEN_FPGA, + + input FX2_1, + output FX2_2, + output FX2_3, + + input wire [11:0] rx_a_a, + input wire [11:0] rx_b_a, + input wire [11:0] rx_a_b, + input wire [11:0] rx_b_b, + + output wire [13:0] tx_a, + output wire [13:0] tx_b, + + output wire TXSYNC_A, + output wire TXSYNC_B, + + // USB interface + input usbclk, + input wire [2:0] usbctl, + output wire [1:0] usbrdy, + inout [15:0] usbdata, // NB Careful, inout + + // These are the general purpose i/o's that go to the daughterboard slots + inout wire [15:0] io_tx_a, + inout wire [15:0] io_tx_b, + inout wire [15:0] io_rx_a, + inout wire [15:0] io_rx_b + ); + wire [15:0] debugdata,debugctrl; + assign MYSTERY_SIGNAL = 1'b0; + + wire clk64,clk128; + + wire WR = usbctl[0]; + wire RD = usbctl[1]; + wire OE = usbctl[2]; + + wire have_space, have_pkt_rdy; + assign usbrdy[0] = have_space; + assign usbrdy[1] = have_pkt_rdy; + + wire tx_underrun, rx_overrun; + wire clear_status = FX2_1; + assign FX2_2 = rx_overrun; + assign FX2_3 = tx_underrun; + + wire [15:0] usbdata_out; + + wire [3:0] dac0mux,dac1mux,dac2mux,dac3mux; + + wire tx_realsignals; + wire [3:0] rx_numchan; + wire [2:0] tx_numchan; + + wire [7:0] interp_rate, decim_rate; + wire [15:0] tx_debugbus, rx_debugbus; + + wire enable_tx, enable_rx; + wire reset_data; +`ifdef MULTI_ON + wire sync_rx; + assign reset_data = sync_rx; +`else + assign reset_data = 1'b0; +`endif // `ifdef MULTI_ON + + wire tx_dsp_reset, rx_dsp_reset, tx_bus_reset, rx_bus_reset; + wire [7:0] settings; + + // Tri-state bus macro + bustri bustri( .data(usbdata_out),.enabledt(OE),.tridata(usbdata) ); + + assign clk64 = master_clk; + + wire [15:0] ch0tx,ch1tx,ch2tx,ch3tx; //,ch4tx,ch5tx,ch6tx,ch7tx; + wire [15:0] ch0rx,ch1rx,ch2rx,ch3rx,ch4rx,ch5rx,ch6rx,ch7rx; + + // TX + wire [15:0] i_out_0,i_out_1,q_out_0,q_out_1; + wire [15:0] bb_tx_i0,bb_tx_q0,bb_tx_i1,bb_tx_q1; // bb_tx_i2,bb_tx_q2,bb_tx_i3,bb_tx_q3; + + wire strobe_interp, tx_sample_strobe; + wire tx_empty; + + wire serial_strobe; + wire [6:0] serial_addr; + wire [31:0] serial_data; + + reg [15:0] debug_counter; +`ifdef COUNTER_32BIT_ON + reg [31:0] sample_counter_32bit; +`endif // `ifdef COUNTER_32BIT_ON + reg [15:0] loopback_i_0,loopback_q_0; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Transmit Side +`ifdef TX_ON + assign bb_tx_i0 = ch0tx; + assign bb_tx_q0 = ch1tx; + assign bb_tx_i1 = ch2tx; + assign bb_tx_q1 = ch3tx; + + tx_buffer tx_buffer + ( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset), + .usbdata(usbdata),.WR(WR),.have_space(have_space),.tx_underrun(tx_underrun), + .channels({tx_numchan,1'b0}), + .tx_i_0(ch0tx),.tx_q_0(ch1tx), + .tx_i_1(ch2tx),.tx_q_1(ch3tx), + .tx_i_2(),.tx_q_2(), + .tx_i_3(),.tx_q_3(), + .txclk(clk64),.txstrobe(strobe_interp), + .clear_status(clear_status), + .tx_empty(tx_empty), + .debugbus(tx_debugbus) ); + + tx_chain tx_chain_0 + ( .clock(clk64),.reset(tx_dsp_reset),.enable(enable_tx), + .interp_rate(interp_rate),.sample_strobe(tx_sample_strobe), + .interpolator_strobe(strobe_interp),.freq(), + .i_in(bb_tx_i0),.q_in(bb_tx_q0),.i_out(i_out_0),.q_out(q_out_0) ); + + tx_chain tx_chain_1 + ( .clock(clk64),.reset(tx_dsp_reset),.enable(enable_tx), + .interp_rate(interp_rate),.sample_strobe(tx_sample_strobe), + .interpolator_strobe(strobe_interp),.freq(), + .i_in(bb_tx_i1),.q_in(bb_tx_q1),.i_out(i_out_1),.q_out(q_out_1) ); + + setting_reg #(`FR_TX_MUX) + sr_txmux(.clock(clk64),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({dac3mux,dac2mux,dac1mux,dac0mux,tx_realsignals,tx_numchan})); + + wire [15:0] tx_a_a = dac0mux[3] ? (dac0mux[1] ? (dac0mux[0] ? q_out_1 : i_out_1) : (dac0mux[0] ? q_out_0 : i_out_0)) : 16'b0; + wire [15:0] tx_b_a = dac1mux[3] ? (dac1mux[1] ? (dac1mux[0] ? q_out_1 : i_out_1) : (dac1mux[0] ? q_out_0 : i_out_0)) : 16'b0; + wire [15:0] tx_a_b = dac2mux[3] ? (dac2mux[1] ? (dac2mux[0] ? q_out_1 : i_out_1) : (dac2mux[0] ? q_out_0 : i_out_0)) : 16'b0; + wire [15:0] tx_b_b = dac3mux[3] ? (dac3mux[1] ? (dac3mux[0] ? q_out_1 : i_out_1) : (dac3mux[0] ? q_out_0 : i_out_0)) : 16'b0; + + wire txsync = tx_sample_strobe; + assign TXSYNC_A = txsync; + assign TXSYNC_B = txsync; + + assign tx_a = txsync ? tx_b_a[15:2] : tx_a_a[15:2]; + assign tx_b = txsync ? tx_b_b[15:2] : tx_a_b[15:2]; +`endif // `ifdef TX_ON + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Receive Side +`ifdef RX_ON + wire rx_sample_strobe,strobe_decim,hb_strobe; + wire [15:0] bb_rx_i0,bb_rx_q0,bb_rx_i1,bb_rx_q1, + bb_rx_i2,bb_rx_q2,bb_rx_i3,bb_rx_q3; + + wire loopback = settings[0]; + wire counter = settings[1]; +`ifdef COUNTER_32BIT_ON + wire counter_32bit = settings[2]; + + always @(posedge clk64) + if(rx_dsp_reset) + sample_counter_32bit <= #1 32'd0; + else if(~enable_rx | reset_data) + sample_counter_32bit <=#1 32'd0; + else if(hb_strobe) + sample_counter_32bit <=#1 sample_counter_32bit + 32'd1; +`endif // `ifdef COUNTER_32BIT_ON + + always @(posedge clk64) + if(rx_dsp_reset) + debug_counter <= #1 16'd0; + else if(~enable_rx) + debug_counter <= #1 16'd0; + else if(hb_strobe) + debug_counter <=#1 debug_counter + 16'd2; + + always @(posedge clk64) + if(strobe_interp) + begin + loopback_i_0 <= #1 ch0tx; + loopback_q_0 <= #1 ch1tx; + end + +`ifdef COUNTER_32BIT_ON + assign ch0rx = counter_32bit?sample_counter_32bit[31:16]:counter ? debug_counter : loopback ? loopback_i_0 : bb_rx_i0; + assign ch1rx = counter_32bit?sample_counter_32bit[15:0]:counter ? debug_counter + 16'd1 : loopback ? loopback_q_0 : bb_rx_q0; + assign ch2rx = bb_rx_i1; + assign ch3rx = bb_rx_q1; + assign ch4rx = counter_32bit?bb_rx_i0:bb_rx_i2; + assign ch5rx = counter_32bit?bb_rx_q0:bb_rx_q2;// If using counter replicate channels here to be able to get rx_i0 when using counter + //This means if you use 4 channels that channel 3 will be replaced by channel 0 + // and channel 0 will output the 32 bit counter. + assign ch6rx = bb_rx_i3; + assign ch7rx = bb_rx_q3; +`else + assign ch0rx = counter ? debug_counter : loopback ? loopback_i_0 : bb_rx_i0; + assign ch1rx = counter ? debug_counter + 16'd1 : loopback ? loopback_q_0 : bb_rx_q0; + assign ch2rx = bb_rx_i1; + assign ch3rx = bb_rx_q1; + assign ch4rx = bb_rx_i2; + assign ch5rx = bb_rx_q2; + assign ch6rx = bb_rx_i3; + assign ch7rx = bb_rx_q3; +`endif // `ifdef COUNTER_32BIT_ON + + + wire [15:0] ddc0_in_i,ddc0_in_q,ddc1_in_i,ddc1_in_q,ddc2_in_i,ddc2_in_q,ddc3_in_i,ddc3_in_q; + adc_interface adc_interface(.clock(clk64),.reset(rx_dsp_reset),.enable(1'b1), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .rx_a_a(rx_a_a),.rx_b_a(rx_b_a),.rx_a_b(rx_a_b),.rx_b_b(rx_b_b), + .ddc0_in_i(ddc0_in_i),.ddc0_in_q(ddc0_in_q), + .ddc1_in_i(ddc1_in_i),.ddc1_in_q(ddc1_in_q), + .ddc2_in_i(ddc2_in_i),.ddc2_in_q(ddc2_in_q), + .ddc3_in_i(ddc3_in_i),.ddc3_in_q(ddc3_in_q),.rx_numchan(rx_numchan) ); + + rx_buffer rx_buffer + ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset | reset_data), + .reset_regs(rx_dsp_reset), + .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun), + .channels(rx_numchan), + .ch_0(ch0rx),.ch_1(ch1rx), + .ch_2(ch2rx),.ch_3(ch3rx), + .ch_4(ch4rx),.ch_5(ch5rx), + .ch_6(ch6rx),.ch_7(ch7rx), + .rxclk(clk64),.rxstrobe(hb_strobe), + .clear_status(clear_status), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .debugbus(rx_debugbus) ); + + `ifdef RX_EN_0 + rx_chain #(`FR_RX_FREQ_0,`FR_RX_PHASE_0) rx_chain_0 + ( .clock(clk64),.reset(reset_data),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(hb_strobe), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc0_in_i),.q_in(ddc0_in_q),.i_out(bb_rx_i0),.q_out(bb_rx_q0),.debugdata(debugdata),.debugctrl(debugctrl)); + `else + assign bb_rx_i0=16'd0; + assign bb_rx_q0=16'd0; + `endif + + `ifdef RX_EN_1 + rx_chain #(`FR_RX_FREQ_1,`FR_RX_PHASE_1) rx_chain_1 + ( .clock(clk64),.reset(reset_data),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc1_in_i),.q_in(ddc1_in_q),.i_out(bb_rx_i1),.q_out(bb_rx_q1)); + `else + assign bb_rx_i1=16'd0; + assign bb_rx_q1=16'd0; + `endif + + `ifdef RX_EN_2 + rx_chain #(`FR_RX_FREQ_2,`FR_RX_PHASE_2) rx_chain_2 + ( .clock(clk64),.reset(reset_data),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc2_in_i),.q_in(ddc2_in_q),.i_out(bb_rx_i2),.q_out(bb_rx_q2)); + `else + assign bb_rx_i2=16'd0; + assign bb_rx_q2=16'd0; + `endif + + `ifdef RX_EN_3 + rx_chain #(`FR_RX_FREQ_3,`FR_RX_PHASE_3) rx_chain_3 + ( .clock(clk64),.reset(reset_data),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc3_in_i),.q_in(ddc3_in_q),.i_out(bb_rx_i3),.q_out(bb_rx_q3)); + assign bb_rx_i3=16'd0; + assign bb_rx_q3=16'd0; + `endif + +`endif // `ifdef RX_ON + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Control Functions + + wire [31:0] capabilities; + assign capabilities[7] = `TX_CAP_HB; + assign capabilities[6:4] = `TX_CAP_NCHAN; + assign capabilities[3] = `RX_CAP_HB; + assign capabilities[2:0] = `RX_CAP_NCHAN; + + + serial_io serial_io + ( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI), + .enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .readback_0({io_rx_a,io_tx_a}),.readback_1({io_rx_b,io_tx_b}),.readback_2(capabilities),.readback_3(32'hf0f0931a) ); + + wire [15:0] reg_0,reg_1,reg_2,reg_3; + +`ifdef MULTI_ON + + master_control_multi master_control + ( .master_clk(clk64),.usbclk(usbclk), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .rx_slave_sync(io_rx_a[`bitnoFR_RX_SYNC_INPUT_IOPIN]), + .tx_bus_reset(tx_bus_reset),.rx_bus_reset(rx_bus_reset), + .tx_dsp_reset(tx_dsp_reset),.rx_dsp_reset(rx_dsp_reset), + .enable_tx(enable_tx),.enable_rx(enable_rx), + .sync_rx(sync_rx), + .interp_rate(interp_rate),.decim_rate(decim_rate), + .tx_sample_strobe(tx_sample_strobe),.strobe_interp(strobe_interp), + .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim), + .tx_empty(tx_empty), + //.debug_0(rx_a_a),.debug_1(ddc0_in_i), + .debug_0(rx_debugbus),.debug_1(ddc0_in_i), + .debug_2({rx_sample_strobe,strobe_decim,serial_strobe,serial_addr}),.debug_3({rx_dsp_reset,tx_dsp_reset,rx_bus_reset,tx_bus_reset,enable_rx,tx_underrun,rx_overrun,decim_rate}), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) ); + +`else //`ifdef MULTI_ON + + master_control master_control + ( .master_clk(clk64),.usbclk(usbclk), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .tx_bus_reset(tx_bus_reset),.rx_bus_reset(rx_bus_reset), + .tx_dsp_reset(tx_dsp_reset),.rx_dsp_reset(rx_dsp_reset), + .enable_tx(enable_tx),.enable_rx(enable_rx), + .interp_rate(interp_rate),.decim_rate(decim_rate), + .tx_sample_strobe(tx_sample_strobe),.strobe_interp(strobe_interp), + .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim), + .tx_empty(tx_empty), + //.debug_0(rx_a_a),.debug_1(ddc0_in_i), + .debug_0(rx_debugbus),.debug_1(ddc0_in_i), + .debug_2({rx_sample_strobe,strobe_decim,serial_strobe,serial_addr}),.debug_3({rx_dsp_reset,tx_dsp_reset,rx_bus_reset,tx_bus_reset,enable_rx,tx_underrun,rx_overrun,decim_rate}), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) ); + +`endif //`ifdef MULTI_ON + + io_pins io_pins + (.io_0(io_tx_a),.io_1(io_rx_a),.io_2(io_tx_b),.io_3(io_rx_b), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3), + .clock(clk64),.rx_reset(rx_dsp_reset),.tx_reset(tx_dsp_reset), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe)); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Misc Settings + setting_reg #(`FR_MODE) sr_misc(.clock(clk64),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(settings)); + +endmodule // usrp_multi diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi.vh b/usrp/fpga/toplevel/usrp_multi/usrp_multi.vh new file mode 100644 index 00000000..2904a935 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi.vh @@ -0,0 +1,141 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// ==================================================================== +// User control over what parts get included +// +// >>>> EDIT ONLY THIS SECTION <<<< +// Uncomment only ONE configuration +// ==================================================================== + +// ==== Multi usrp configurations ==== +// Uncomment this for multi with 2 rx channels (w/ halfband) & 2 transmit channels +`include "usrp_multi_config_2rxhb_2tx.vh" + +// Uncomment this for multi with 4 rx channels (w/o halfband) & 0 transmit channels +//`include "usrp_multi_config_4rx_0tx.vh" + +// Uncomment this for multi with 2 rx channels (w/ halfband) & 0 transmit channels +//`include "usrp_multi_config_2rxhb_0tx.vh" + +// Uncomment this for multi with 2 rx channels (w/o halfband) & 0 transmit channels +//`include "usrp_multi_config_2rx_0tx.vh" + +// ==== Standard configurations (no multi support) ==== +// Uncomment this for standard with 2 rx channels (w/ halfband) & 2 transmit channels +// `include "../usrp_std/usrp_std_config_2rxhb_2tx.vh" + +// Uncomment this for standard with 4 rx channels (w/o halfband) & 0 transmit channels +//`include "../usrp_std/usrp_std_config_4rx_0tx.vh" + +// Add other "known to fit" configurations here... + +// ==================================================================== +// +// >>>> DO NOT EDIT BELOW HERE <<<< +// +// [The stuff from here down is derived from the stuff included above] +// +// N.B., *all* the remainder of the code should be conditionalized +// only in terms of: +// +// TX_ON, TX_EN_0, TX_EN_1, TX_EN_2, TX_EN_3, TX_CAP_NCHAN, TX_CAP_HB, +// RX_ON, RX_EN_0, RX_EN_1, RX_EN_2, RX_EN_3, RX_CAP_NCHAN, RX_CAP_HB, +// RX_NCO_ON, RX_CIC_ON +// ==================================================================== +`ifdef MULTI_ON + `define COUNTER_32BIT_ON +`endif + +`ifdef TX_ON + + `ifdef TX_SINGLE + `define TX_EN_0 + `define TX_CAP_NCHAN 3'd1 + `endif + + `ifdef TX_DUAL + `define TX_EN_0 + `define TX_EN_1 + `define TX_CAP_NCHAN 3'd2 + `endif + + `ifdef TX_QUAD + `define TX_EN_0 + `define TX_EN_1 + `define TX_EN_2 + `define TX_EN_3 + `define TX_CAP_NCHAN 3'd4 + `endif + + `ifdef TX_HB_ON + `define TX_CAP_HB 1 + `else + `define TX_CAP_HB 0 + `endif + +`else // !ifdef TX_ON + + `define TX_CAP_NCHAN 3'd0 + `define TX_CAP_HB 0 + +`endif // !ifdef TX_ON + +// -------------------------------------------------------------------- + +`ifdef RX_ON + + `ifdef RX_SINGLE + `define RX_EN_0 + `define RX_CAP_NCHAN 3'd1 + `endif + + `ifdef RX_DUAL + `define RX_EN_0 + `define RX_EN_1 + `ifdef MULTI_ON + `define RX_CAP_NCHAN 3'd4 + `else + `define RX_CAP_NCHAN 3'd2 + `endif + `endif + + `ifdef RX_QUAD + `define RX_EN_0 + `define RX_EN_1 + `define RX_EN_2 + `define RX_EN_3 + `define RX_CAP_NCHAN 3'd4 + `endif + + `ifdef RX_HB_ON + `define RX_CAP_HB 1 + `else + `define RX_CAP_HB 0 + `endif + +`else // !ifdef RX_ON + + `define RX_CAP_NCHAN 3'd0 + `define RX_CAP_HB 0 + +`endif // !ifdef RX_ON diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh new file mode 100644 index 00000000..26a41e4d --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh @@ -0,0 +1,62 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +`define MULTI_ON +// ------------------------------------------------------------ +// If TX_ON is not defined, there is *no* transmit circuitry built +// `define TX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of TX_SINGLE, TX_DUAL and TX_QUAD +// to respectively enable 1, 2 or 4 transmit channels. +// [Please note that only TX_DUAL is currently valid] +//`define TX_SINGLE +//`define TX_DUAL +//`define TX_QUAD + +// ------------------------------------------------------------ +// Define TX_HB_ON to enable the transmit halfband filter +// [Not implemented] +//`define TX_HB_ON + +// ------------------------------------------------------------ +// IF RX_ON is not defined, there is *no* transmit circuitry built + `define RX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of RX_SINGLE, RX_DUAL and RX_QUAD +// to respectively define 1, 2 or 4 receive channels. + +//`define RX_SINGLE +`define RX_DUAL +//`define RX_QUAD + +// ------------------------------------------------------------ +// Define RX_HB_ON to enable the receive halfband filter +//`define RX_HB_ON + +// ------------------------------------------------------------ +// Define RX_NCO_ON to enable the receive Numerical Controlled Osc + `define RX_NCO_ON + +// ------------------------------------------------------------ +// Define RX_CIC_ON to enable the receive Cascaded Integrator Comb filter + `define RX_CIC_ON diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh new file mode 100644 index 00000000..0673d960 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh @@ -0,0 +1,62 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +`define MULTI_ON +// ------------------------------------------------------------ +// If TX_ON is not defined, there is *no* transmit circuitry built +// `define TX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of TX_SINGLE, TX_DUAL and TX_QUAD +// to respectively enable 1, 2 or 4 transmit channels. +// [Please note that only TX_DUAL is currently valid] +//`define TX_SINGLE +//`define TX_DUAL +//`define TX_QUAD + +// ------------------------------------------------------------ +// Define TX_HB_ON to enable the transmit halfband filter +// [Not implemented] +//`define TX_HB_ON + +// ------------------------------------------------------------ +// IF RX_ON is not defined, there is *no* transmit circuitry built + `define RX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of RX_SINGLE, RX_DUAL and RX_QUAD +// to respectively define 1, 2 or 4 receive channels. + +//`define RX_SINGLE + `define RX_DUAL +//`define RX_QUAD + +// ------------------------------------------------------------ +// Define RX_HB_ON to enable the receive halfband filter + `define RX_HB_ON + +// ------------------------------------------------------------ +// Define RX_NCO_ON to enable the receive Numerical Controlled Osc + `define RX_NCO_ON + +// ------------------------------------------------------------ +// Define RX_CIC_ON to enable the receive Cascaded Integrator Comb filter + `define RX_CIC_ON diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh new file mode 100644 index 00000000..80c7fbdc --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh @@ -0,0 +1,62 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +`define MULTI_ON +// ------------------------------------------------------------ +// If TX_ON is not defined, there is *no* transmit circuitry built + `define TX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of TX_SINGLE, TX_DUAL and TX_QUAD +// to respectively enable 1, 2 or 4 transmit channels. +// [Please note that only TX_DUAL is currently valid] +//`define TX_SINGLE + `define TX_DUAL +//`define TX_QUAD + +// ------------------------------------------------------------ +// Define TX_HB_ON to enable the transmit halfband filter +// [Not implemented] +//`define TX_HB_ON + +// ------------------------------------------------------------ +// IF RX_ON is not defined, there is *no* transmit circuitry built + `define RX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of RX_SINGLE, RX_DUAL and RX_QUAD +// to respectively define 1, 2 or 4 receive channels. + +//`define RX_SINGLE + `define RX_DUAL +//`define RX_QUAD + +// ------------------------------------------------------------ +// Define RX_HB_ON to enable the receive halfband filter + `define RX_HB_ON + +// ------------------------------------------------------------ +// Define RX_NCO_ON to enable the receive Numerical Controlled Osc + `define RX_NCO_ON + +// ------------------------------------------------------------ +// Define RX_CIC_ON to enable the receive Cascaded Integrator Comb filter + `define RX_CIC_ON diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh new file mode 100644 index 00000000..36176be4 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh @@ -0,0 +1,62 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +`define MULTI_ON +// ------------------------------------------------------------ +// If TX_ON is not defined, there is *no* transmit circuitry built +// `define TX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of TX_SINGLE, TX_DUAL and TX_QUAD +// to respectively enable 1, 2 or 4 transmit channels. +// [Please note that only TX_DUAL is currently valid] +//`define TX_SINGLE +//`define TX_DUAL +//`define TX_QUAD + +// ------------------------------------------------------------ +// Define TX_HB_ON to enable the transmit halfband filter +// [Not implemented] +//`define TX_HB_ON + +// ------------------------------------------------------------ +// IF RX_ON is not defined, there is *no* transmit circuitry built + `define RX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of RX_SINGLE, RX_DUAL and RX_QUAD +// to respectively define 1, 2 or 4 receive channels. + +//`define RX_SINGLE +//`define RX_DUAL + `define RX_QUAD + +// ------------------------------------------------------------ +// Define RX_HB_ON to enable the receive halfband filter +//`define RX_HB_ON + +// ------------------------------------------------------------ +// Define RX_NCO_ON to enable the receive Numerical Controlled Osc + `define RX_NCO_ON + +// ------------------------------------------------------------ +// Define RX_CIC_ON to enable the receive Cascaded Integrator Comb filter + `define RX_CIC_ON diff --git a/usrp/fpga/toplevel/usrp_multi/usrp_std.vh b/usrp/fpga/toplevel/usrp_multi/usrp_std.vh new file mode 100644 index 00000000..189cf14b --- /dev/null +++ b/usrp/fpga/toplevel/usrp_multi/usrp_std.vh @@ -0,0 +1,29 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Martin Dudok van Heel +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// ==================================================================== +// Do not remove or edit this file. +// This is a redirect to usrp_multi.vh +// This is needed because some common source files have a +// hardcoded `include "usrp_std.vh" +// ==================================================================== + +`include "usrp_multi.vh" diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.csf b/usrp/fpga/toplevel/usrp_std/usrp_std.csf new file mode 100644 index 00000000..627197ca --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.csf @@ -0,0 +1,444 @@ +COMPILER_SETTINGS +{ + IO_PLACEMENT_OPTIMIZATION = OFF; + ENABLE_DRC_SETTINGS = OFF; + PHYSICAL_SYNTHESIS_REGISTER_RETIMING = OFF; + PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION = OFF; + PHYSICAL_SYNTHESIS_COMBO_LOGIC = OFF; + DRC_FANOUT_EXCEEDING = 30; + DRC_REPORT_FANOUT_EXCEEDING = OFF; + DRC_TOP_FANOUT = 50; + DRC_REPORT_TOP_FANOUT = OFF; + RUN_DRC_DURING_COMPILATION = OFF; + ADV_NETLIST_OPT_RETIME_CORE_AND_IO = ON; + ADV_NETLIST_OPT_SYNTH_USE_FITTER_INFO = OFF; + ADV_NETLIST_OPT_SYNTH_GATE_RETIME = OFF; + ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP = OFF; + SMART_COMPILE_IGNORES_TDC_FOR_STRATIX_PLL_CHANGES = OFF; + MERGE_HEX_FILE = OFF; + TRUE_WYSIWYG_FLOW = OFF; + SEED = 1; + FINAL_PLACEMENT_OPTIMIZATION = AUTOMATICALLY; + FAMILY = Cyclone; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "LOWER TO 1ESB UPPER TO 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_OUTPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA1 = "DPRAM0 TO 1 DPRAM1 TO 2"; + DPRAM_32BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_8BIT_16BIT_SINGLE_PORT_MODE_INPUT_EPXA1 = "MEGALAB COLUMN 1"; + DPRAM_DUAL_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_OTHER_SIGNALS_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DEEP_MODE_OTHER_SIGNALS_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_SINGLE_PORT_MODE_OUTPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4ESB"; + DPRAM_WIDE_MODE_OUTPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4ESB"; + DPRAM_DEEP_MODE_OUTPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_DUAL_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_SINGLE_PORT_MODE_INPUT_EPXA4_10 = "DPRAM0 TO 3 DPRAM1 TO 4"; + DPRAM_WIDE_MODE_INPUT_EPXA4_10 = "LOWER TO 3 UPPER TO 4"; + DPRAM_DEEP_MODE_INPUT_EPXA4_10 = "MEGALAB COLUMN 3"; + DPRAM_OTHER_SIGNALS_EPXA4_10 = "DEFAULT OTHER ROUTING OPTIONS"; + DPRAM_OUTPUT_EPXA4_10 = "DEFAULT OUTPUT ROUTING OPTIONS"; + DPRAM_INPUT_EPXA4_10 = "DEFAULT INPUT ROUTING OPTIONS"; + STRIPE_TO_PLD_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PLD_TO_STRIPE_INTERRUPTS_EPXA4_10 = "MEGALAB COLUMN 2"; + PROCESSOR_DEBUG_EXTENSIONS_EPXA4_10 = "MEGALAB COLUMN 2"; + STRIPE_TO_PLD_BRIDGE_EPXA4_10 = "MEGALAB COLUMN 1"; + FAST_FIT_COMPILATION = OFF; + SIGNALPROBE_DURING_NORMAL_COMPILATION = OFF; + OPTIMIZE_IOC_REGISTER_PLACEMENT_FOR_TIMING = ON; + OPTIMIZE_TIMING = "NORMAL COMPILATION"; + OPTIMIZE_HOLD_TIMING = OFF; + COMPILATION_LEVEL = FULL; + SAVE_DISK_SPACE = OFF; + SPEED_DISK_USAGE_TRADEOFF = NORMAL; + LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT = OFF; + SIGNALPROBE_ALLOW_OVERUSE = OFF; + FOCUS_ENTITY_NAME = |usrp_std; + ROUTING_BACK_ANNOTATION_MODE = OFF; + INC_PLC_MODE = OFF; + FIT_ONLY_ONE_ATTEMPT = OFF; +} +DEFAULT_DEVICE_OPTIONS +{ + GENERATE_CONFIG_HEXOUT_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_JBC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_SVF_FILE = OFF; + RESERVE_PIN = "AS INPUT TRI-STATED"; + RESERVE_ALL_UNUSED_PINS = "AS OUTPUT DRIVING GROUND"; + HEXOUT_FILE_COUNT_DIRECTION = UP; + HEXOUT_FILE_START_ADDRESS = 0; + GENERATE_HEX_FILE = OFF; + GENERATE_RBF_FILE = OFF; + GENERATE_TTF_FILE = OFF; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + APEX20K_CONFIGURATION_DEVICE = AUTO; + USE_CONFIGURATION_DEVICE = ON; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + AUTO_RESTART_CONFIGURATION = OFF; + ENABLE_VREFB_PIN = OFF; + ENABLE_VREFA_PIN = OFF; + SECURITY_BIT = OFF; + USER_START_UP_CLOCK = OFF; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "ACTIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_UPDATE_MODE = STANDARD; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + ENABLE_JTAG_BST_SUPPORT = OFF; + CONFIGURATION_CLOCK_DIVISOR = 1; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CLOCK_SOURCE = INTERNAL; + COMPRESSION_MODE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; +} +AUTO_SLD_HUB_ENTITY +{ + AUTO_INSERT_SLD_HUB_ENTITY = ENABLE; + HUB_INSTANCE_NAME = SLD_HUB_INST; + HUB_ENTITY_NAME = SLD_HUB; +} +SIGNALTAP_LOGIC_ANALYZER_SETTINGS +{ + ENABLE_SIGNALTAP = Off; + AUTO_ENABLE_SMART_COMPILE = On; +} +CHIP(usrp_std) +{ + DEVICE = EP1C12Q240C8; + DEVICE_FILTER_PACKAGE = "ANY QFP"; + DEVICE_FILTER_PIN_COUNT = 240; + DEVICE_FILTER_SPEED_GRADE = ANY; + AUTO_RESTART_CONFIGURATION = OFF; + RELEASE_CLEARS_BEFORE_TRI_STATES = OFF; + USER_START_UP_CLOCK = OFF; + ENABLE_DEVICE_WIDE_RESET = OFF; + ENABLE_DEVICE_WIDE_OE = OFF; + ENABLE_INIT_DONE_OUTPUT = OFF; + FLEX10K_ENABLE_LOCK_OUTPUT = OFF; + ENABLE_JTAG_BST_SUPPORT = OFF; + MAX7000_ENABLE_JTAG_BST_SUPPORT = ON; + APEX20K_JTAG_USER_CODE = FFFFFFFF; + MERCURY_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_JTAG_USER_CODE = 7F; + MAX7000_JTAG_USER_CODE = FFFFFFFF; + MAX7000S_JTAG_USER_CODE = FFFF; + STRATIX_JTAG_USER_CODE = FFFFFFFF; + APEX20K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + MERCURY_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX6K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + FLEX10K_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + EXCALIBUR_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + APEXII_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + STRATIX_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + CYCLONE_CONFIGURATION_SCHEME = "PASSIVE SERIAL"; + USE_CONFIGURATION_DEVICE = OFF; + APEX20K_CONFIGURATION_DEVICE = AUTO; + MERCURY_CONFIGURATION_DEVICE = AUTO; + FLEX6K_CONFIGURATION_DEVICE = AUTO; + FLEX10K_CONFIGURATION_DEVICE = AUTO; + EXCALIBUR_CONFIGURATION_DEVICE = AUTO; + STRATIX_CONFIGURATION_DEVICE = AUTO; + CYCLONE_CONFIGURATION_DEVICE = AUTO; + STRATIX_UPDATE_MODE = STANDARD; + APEX20K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + MERCURY_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + FLEX10K_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + STRATIX_CONFIG_DEVICE_JTAG_USER_CODE = FFFFFFFF; + AUTO_INCREMENT_CONFIG_DEVICE_JTAG_USER_CODE = ON; + DISABLE_NCS_AND_OE_PULLUPS_ON_CONFIG_DEVICE = OFF; + COMPRESSION_MODE = OFF; + ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + FLEX6K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = OFF; + FLEX10K_ENABLE_LOW_VOLTAGE_MODE_ON_CONFIG_DEVICE = ON; + EPROM_USE_CHECKSUM_AS_USERCODE = OFF; + USE_CHECKSUM_AS_USERCODE = OFF; + MAX7000_USE_CHECKSUM_AS_USERCODE = OFF; + GENERATE_TTF_FILE = OFF; + GENERATE_RBF_FILE = ON; + GENERATE_HEX_FILE = OFF; + SECURITY_BIT = OFF; + ENABLE_VREFA_PIN = OFF; + ENABLE_VREFB_PIN = OFF; + GENERATE_SVF_FILE = OFF; + GENERATE_ISC_FILE = OFF; + GENERATE_JAM_FILE = OFF; + GENERATE_JBC_FILE = OFF; + GENERATE_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_SVF_FILE = OFF; + GENERATE_CONFIG_ISC_FILE = OFF; + GENERATE_CONFIG_JAM_FILE = OFF; + GENERATE_CONFIG_JBC_FILE = OFF; + GENERATE_CONFIG_JBC_FILE_COMPRESSED = ON; + GENERATE_CONFIG_HEXOUT_FILE = OFF; + ON_CHIP_BITSTREAM_DECOMPRESSION = OFF; + BASE_PIN_OUT_FILE_ON_SAMEFRAME_DEVICE = OFF; + HEXOUT_FILE_START_ADDRESS = 0; + HEXOUT_FILE_COUNT_DIRECTION = UP; + RESERVE_ALL_UNUSED_PINS = "AS INPUT TRI-STATED"; + STRATIX_DEVICE_IO_STANDARD = LVTTL; + CLOCK_SOURCE = INTERNAL; + CONFIGURATION_CLOCK_FREQUENCY = "10 MHZ"; + CONFIGURATION_CLOCK_DIVISOR = 1; + RESERVE_NWS_NRS_NCS_CS_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_RDYNBUSY_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA7_THROUGH_DATA1_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_DATA0_AFTER_CONFIGURATION = "AS INPUT TRI-STATED"; + RESERVE_NCEO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + RESERVE_ASDO_AFTER_CONFIGURATION = "USE AS REGULAR IO"; + SCLK : LOCATION = Pin_101; + SDI : LOCATION = Pin_100; + SEN : LOCATION = Pin_98; + SLD : LOCATION = Pin_95; + adc1_data[0] : LOCATION = Pin_5; + adc1_data[10] : LOCATION = Pin_235; + adc1_data[11] : LOCATION = Pin_234; + adc1_data[1] : LOCATION = Pin_4; + adc1_data[2] : LOCATION = Pin_3; + adc1_data[3] : LOCATION = Pin_2; + adc1_data[4] : LOCATION = Pin_1; + adc1_data[4] : IO_STANDARD = LVTTL; + adc1_data[5] : LOCATION = Pin_240; + adc1_data[6] : LOCATION = Pin_239; + adc1_data[7] : LOCATION = Pin_238; + adc1_data[8] : LOCATION = Pin_237; + adc1_data[9] : LOCATION = Pin_236; + adc2_data[0] : LOCATION = Pin_20; + adc2_data[10] : LOCATION = Pin_8; + adc2_data[11] : LOCATION = Pin_7; + adc2_data[1] : LOCATION = Pin_19; + adc2_data[2] : LOCATION = Pin_18; + adc2_data[3] : LOCATION = Pin_17; + adc2_data[4] : LOCATION = Pin_16; + adc2_data[5] : LOCATION = Pin_15; + adc2_data[6] : LOCATION = Pin_14; + adc2_data[7] : LOCATION = Pin_13; + adc2_data[8] : LOCATION = Pin_12; + adc2_data[9] : LOCATION = Pin_11; + adc3_data[0] : LOCATION = Pin_200; + adc3_data[10] : LOCATION = Pin_184; + adc3_data[11] : LOCATION = Pin_183; + adc3_data[1] : LOCATION = Pin_197; + adc3_data[2] : LOCATION = Pin_196; + adc3_data[3] : LOCATION = Pin_195; + adc3_data[4] : LOCATION = Pin_194; + adc3_data[5] : LOCATION = Pin_193; + adc3_data[6] : LOCATION = Pin_188; + adc3_data[7] : LOCATION = Pin_187; + adc3_data[8] : LOCATION = Pin_186; + adc3_data[9] : LOCATION = Pin_185; + adc4_data[0] : LOCATION = Pin_222; + adc4_data[10] : LOCATION = Pin_203; + adc4_data[11] : LOCATION = Pin_202; + adc4_data[1] : LOCATION = Pin_219; + adc4_data[2] : LOCATION = Pin_217; + adc4_data[3] : LOCATION = Pin_216; + adc4_data[4] : LOCATION = Pin_215; + adc4_data[5] : LOCATION = Pin_214; + adc4_data[6] : LOCATION = Pin_213; + adc4_data[7] : LOCATION = Pin_208; + adc4_data[8] : LOCATION = Pin_207; + adc4_data[9] : LOCATION = Pin_206; + adc_oeb[0] : LOCATION = Pin_228; + adc_oeb[1] : LOCATION = Pin_21; + adc_oeb[2] : LOCATION = Pin_181; + adc_oeb[3] : LOCATION = Pin_218; + adc_otr[0] : LOCATION = Pin_233; + adc_otr[1] : LOCATION = Pin_6; + adc_otr[2] : LOCATION = Pin_182; + adc_otr[3] : LOCATION = Pin_201; + adclk0 : LOCATION = Pin_224; + adclk1 : LOCATION = Pin_226; + clk0 : LOCATION = Pin_28; + clk0 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk0 : IO_STANDARD = LVTTL; + clk1 : LOCATION = Pin_29; + clk1 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk1 : IO_STANDARD = LVTTL; + clk3 : LOCATION = Pin_152; + clk3 : RESERVE_PIN = "AS INPUT TRI-STATED"; + clk3 : IO_STANDARD = LVTTL; + clk_120mhz : LOCATION = Pin_153; + clk_120mhz : IO_STANDARD = LVTTL; + clk_out : LOCATION = Pin_63; + clk_out : IO_STANDARD = LVTTL; + dac1_data[0] : LOCATION = Pin_165; + dac1_data[10] : LOCATION = Pin_177; + dac1_data[11] : LOCATION = Pin_178; + dac1_data[12] : LOCATION = Pin_179; + dac1_data[13] : LOCATION = Pin_180; + dac1_data[1] : LOCATION = Pin_166; + dac1_data[2] : LOCATION = Pin_167; + dac1_data[3] : LOCATION = Pin_168; + dac1_data[4] : LOCATION = Pin_169; + dac1_data[5] : LOCATION = Pin_170; + dac1_data[6] : LOCATION = Pin_173; + dac1_data[7] : LOCATION = Pin_174; + dac1_data[8] : LOCATION = Pin_175; + dac1_data[9] : LOCATION = Pin_176; + dac2_data[0] : LOCATION = Pin_159; + dac2_data[10] : LOCATION = Pin_163; + dac2_data[11] : LOCATION = Pin_139; + dac2_data[12] : LOCATION = Pin_164; + dac2_data[13] : LOCATION = Pin_138; + dac2_data[1] : LOCATION = Pin_158; + dac2_data[2] : LOCATION = Pin_160; + dac2_data[3] : LOCATION = Pin_156; + dac2_data[4] : LOCATION = Pin_161; + dac2_data[5] : LOCATION = Pin_144; + dac2_data[6] : LOCATION = Pin_162; + dac2_data[7] : LOCATION = Pin_141; + dac2_data[8] : LOCATION = Pin_143; + dac2_data[9] : LOCATION = Pin_140; + dac3_data[0] : LOCATION = Pin_122; + dac3_data[10] : LOCATION = Pin_134; + dac3_data[11] : LOCATION = Pin_135; + dac3_data[12] : LOCATION = Pin_136; + dac3_data[13] : LOCATION = Pin_137; + dac3_data[1] : LOCATION = Pin_123; + dac3_data[2] : LOCATION = Pin_124; + dac3_data[3] : LOCATION = Pin_125; + dac3_data[4] : LOCATION = Pin_126; + dac3_data[5] : LOCATION = Pin_127; + dac3_data[6] : LOCATION = Pin_128; + dac3_data[7] : LOCATION = Pin_131; + dac3_data[8] : LOCATION = Pin_132; + dac3_data[9] : LOCATION = Pin_133; + dac4_data[0] : LOCATION = Pin_104; + dac4_data[10] : LOCATION = Pin_118; + dac4_data[11] : LOCATION = Pin_119; + dac4_data[12] : LOCATION = Pin_120; + dac4_data[13] : LOCATION = Pin_121; + dac4_data[1] : LOCATION = Pin_105; + dac4_data[2] : LOCATION = Pin_106; + dac4_data[3] : LOCATION = Pin_107; + dac4_data[4] : LOCATION = Pin_108; + dac4_data[5] : LOCATION = Pin_113; + dac4_data[6] : LOCATION = Pin_114; + dac4_data[7] : LOCATION = Pin_115; + dac4_data[8] : LOCATION = Pin_116; + dac4_data[9] : LOCATION = Pin_117; + enable_rx : LOCATION = Pin_88; + enable_tx : LOCATION = Pin_93; + gndbus[0] : LOCATION = Pin_223; + gndbus[0] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[0] : IO_STANDARD = LVTTL; + gndbus[1] : LOCATION = Pin_225; + gndbus[1] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[1] : IO_STANDARD = LVTTL; + gndbus[2] : LOCATION = Pin_227; + gndbus[2] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[2] : IO_STANDARD = LVTTL; + gndbus[3] : LOCATION = Pin_62; + gndbus[3] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[3] : IO_STANDARD = LVTTL; + gndbus[4] : LOCATION = Pin_64; + gndbus[4] : RESERVE_PIN = "AS INPUT TRI-STATED"; + gndbus[4] : IO_STANDARD = LVTTL; + misc_pins[0] : LOCATION = Pin_87; + misc_pins[0] : IO_STANDARD = LVTTL; + misc_pins[10] : LOCATION = Pin_76; + misc_pins[10] : IO_STANDARD = LVTTL; + misc_pins[11] : LOCATION = Pin_74; + misc_pins[11] : IO_STANDARD = LVTTL; + misc_pins[1] : LOCATION = Pin_86; + misc_pins[1] : IO_STANDARD = LVTTL; + misc_pins[2] : LOCATION = Pin_85; + misc_pins[2] : IO_STANDARD = LVTTL; + misc_pins[3] : LOCATION = Pin_84; + misc_pins[3] : IO_STANDARD = LVTTL; + misc_pins[4] : LOCATION = Pin_83; + misc_pins[4] : IO_STANDARD = LVTTL; + misc_pins[5] : LOCATION = Pin_82; + misc_pins[5] : IO_STANDARD = LVTTL; + misc_pins[6] : LOCATION = Pin_79; + misc_pins[6] : IO_STANDARD = LVTTL; + misc_pins[7] : LOCATION = Pin_78; + misc_pins[7] : IO_STANDARD = LVTTL; + misc_pins[8] : LOCATION = Pin_77; + misc_pins[8] : IO_STANDARD = LVTTL; + misc_pins[9] : LOCATION = Pin_75; + misc_pins[9] : IO_STANDARD = LVTTL; + reset : LOCATION = Pin_94; + usbclk : LOCATION = Pin_55; + usbctl[0] : LOCATION = Pin_56; + usbctl[1] : LOCATION = Pin_54; + usbctl[2] : LOCATION = Pin_53; + usbctl[3] : LOCATION = Pin_58; + usbctl[4] : LOCATION = Pin_57; + usbctl[5] : LOCATION = Pin_44; + usbdata[0] : LOCATION = Pin_73; + usbdata[10] : LOCATION = Pin_41; + usbdata[11] : LOCATION = Pin_39; + usbdata[12] : LOCATION = Pin_38; + usbdata[12] : IO_STANDARD = LVTTL; + usbdata[13] : LOCATION = Pin_37; + usbdata[14] : LOCATION = Pin_24; + usbdata[15] : LOCATION = Pin_23; + usbdata[1] : LOCATION = Pin_68; + usbdata[2] : LOCATION = Pin_67; + usbdata[3] : LOCATION = Pin_66; + usbdata[4] : LOCATION = Pin_65; + usbdata[5] : LOCATION = Pin_61; + usbdata[6] : LOCATION = Pin_60; + usbdata[7] : LOCATION = Pin_59; + usbdata[8] : LOCATION = Pin_43; + usbdata[9] : LOCATION = Pin_42; + usbrdy[0] : LOCATION = Pin_45; + usbrdy[1] : LOCATION = Pin_46; + usbrdy[2] : LOCATION = Pin_47; + usbrdy[3] : LOCATION = Pin_48; + usbrdy[4] : LOCATION = Pin_49; + usbrdy[5] : LOCATION = Pin_50; + clear_status : LOCATION = Pin_99; +} diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.esf b/usrp/fpga/toplevel/usrp_std/usrp_std.esf new file mode 100644 index 00000000..b88c1599 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.esf @@ -0,0 +1,14 @@ +SIMULATOR_SETTINGS +{ + ESTIMATE_POWER_CONSUMPTION = OFF; + GLITCH_INTERVAL = 1NS; + GLITCH_DETECTION = OFF; + SIMULATION_COVERAGE = ON; + CHECK_OUTPUTS = OFF; + SETUP_HOLD_DETECTION = OFF; + POWER_ESTIMATION_START_TIME = "0 NS"; + ADD_DEFAULT_PINS_TO_SIMULATION_OUTPUT_WAVEFORMS = ON; + SIMULATION_MODE = TIMING; + START_TIME = 0NS; + USE_COMPILER_SETTINGS = usrp_std; +} diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.psf b/usrp/fpga/toplevel/usrp_std/usrp_std.psf new file mode 100644 index 00000000..506c81b6 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.psf @@ -0,0 +1,312 @@ +DEFAULT_DESIGN_ASSISTANT_SETTINGS +{ + HCPY_ALOAD_SIGNALS = OFF; + HCPY_VREF_PINS = OFF; + HCPY_CAT = OFF; + HCPY_ILLEGAL_HC_DEV_PKG = OFF; + ACLK_RULE_IMSZER_ADOMAIN = OFF; + ACLK_RULE_SZER_BTW_ACLK_DOMAIN = OFF; + ACLK_RULE_NO_SZER_ACLK_DOMAIN = OFF; + ACLK_CAT = OFF; + SIGNALRACE_RULE_ASYNCHPIN_SYNCH_CLKPIN = OFF; + SIGNALRACE_CAT = OFF; + NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED = OFF; + NONSYNCHSTRUCT_RULE_SRLATCH = OFF; + NONSYNCHSTRUCT_RULE_DLATCH = OFF; + NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR = OFF; + NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN = OFF; + NONSYNCHSTRUCT_RULE_RIPPLE_CLK = OFF; + NONSYNCHSTRUCT_RULE_DELAY_CHAIN = OFF; + NONSYNCHSTRUCT_RULE_REG_LOOP = OFF; + NONSYNCHSTRUCT_RULE_COMBLOOP = OFF; + NONSYNCHSTRUCT_CAT = OFF; + NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE = OFF; + TIMING_RULE_COIN_CLKEDGE = OFF; + TIMING_RULE_SHIFT_REG = OFF; + TIMING_RULE_HIGH_FANOUTS = OFF; + TIMING_CAT = OFF; + RESET_RULE_ALL = OFF; + RESET_RULE_IMSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_UNSYNCH_ASYNCH_DOMAIN = OFF; + RESET_RULE_REG_ASNYCH = OFF; + RESET_RULE_COMB_ASYNCH_RESET = OFF; + RESET_RULE_IMSYNCH_EXRESET = OFF; + RESET_RULE_UNSYNCH_EXRESET = OFF; + RESET_RULE_INPINS_RESETNET = OFF; + RESET_CAT = OFF; + CLK_RULE_ALL = OFF; + CLK_RULE_MIX_EDGES = OFF; + CLK_RULE_CLKNET_CLKSPINES = OFF; + CLK_RULE_INPINS_CLKNET = OFF; + CLK_RULE_GATING_SCHEME = OFF; + CLK_RULE_INV_CLOCK = OFF; + CLK_RULE_COMB_CLOCK = OFF; + CLK_CAT = OFF; + HCPY_EXCEED_USER_IO_USAGE = OFF; + HCPY_EXCEED_RAM_USAGE = OFF; + NONSYNCHSTRUCT_RULE_ASYN_RAM = OFF; + SIGNALRACE_RULE_TRISTATE = OFF; + ASSG_RULE_MISSING_TIMING = OFF; + ASSG_RULE_MISSING_FMAX = OFF; + ASSG_CAT = OFF; +} +SYNTHESIS_FITTING_SETTINGS +{ + AUTO_SHIFT_REGISTER_RECOGNITION = ON; + AUTO_DSP_RECOGNITION = ON; + AUTO_RAM_RECOGNITION = ON; + REMOVE_DUPLICATE_LOGIC = ON; + AUTO_TURBO_BIT = ON; + AUTO_MERGE_PLLS = ON; + AUTO_OPEN_DRAIN_PINS = ON; + AUTO_PARALLEL_EXPANDERS = ON; + AUTO_FAST_OUTPUT_ENABLE_REGISTERS = OFF; + AUTO_FAST_OUTPUT_REGISTERS = OFF; + AUTO_FAST_INPUT_REGISTERS = OFF; + AUTO_CASCADE_CHAINS = ON; + AUTO_CARRY_CHAINS = ON; + AUTO_DELAY_CHAINS = ON; + MAX7000_PARALLEL_EXPANDER_CHAIN_LENGTH = 4; + PARALLEL_EXPANDER_CHAIN_LENGTH = 16; + CASCADE_CHAIN_LENGTH = 2; + STRATIX_CARRY_CHAIN_LENGTH = 70; + MERCURY_CARRY_CHAIN_LENGTH = 48; + FLEX10K_CARRY_CHAIN_LENGTH = 32; + FLEX6K_CARRY_CHAIN_LENGTH = 32; + CARRY_CHAIN_LENGTH = 48; + CARRY_OUT_PINS_LCELL_INSERT = ON; + NORMAL_LCELL_INSERT = ON; + AUTO_LCELL_INSERTION = ON; + ALLOW_XOR_GATE_USAGE = ON; + AUTO_PACKED_REGISTERS_STRATIX = NORMAL; + AUTO_PACKED_REGISTERS = OFF; + AUTO_PACKED_REG_CYCLONE = NORMAL; + FLEX10K_OPTIMIZATION_TECHNIQUE = AREA; + FLEX6K_OPTIMIZATION_TECHNIQUE = AREA; + MERCURY_OPTIMIZATION_TECHNIQUE = AREA; + APEX20K_OPTIMIZATION_TECHNIQUE = SPEED; + MAX7000_OPTIMIZATION_TECHNIQUE = SPEED; + STRATIX_OPTIMIZATION_TECHNIQUE = SPEED; + CYCLONE_OPTIMIZATION_TECHNIQUE = AREA; + FLEX10K_TECHNOLOGY_MAPPER = LUT; + FLEX6K_TECHNOLOGY_MAPPER = LUT; + MERCURY_TECHNOLOGY_MAPPER = LUT; + APEX20K_TECHNOLOGY_MAPPER = LUT; + MAX7000_TECHNOLOGY_MAPPER = "PRODUCT TERM"; + STRATIX_TECHNOLOGY_MAPPER = LUT; + AUTO_IMPLEMENT_IN_ROM = OFF; + AUTO_GLOBAL_MEMORY_CONTROLS = OFF; + AUTO_GLOBAL_REGISTER_CONTROLS = ON; + AUTO_GLOBAL_OE = ON; + AUTO_GLOBAL_CLOCK = ON; + USE_LPM_FOR_AHDL_OPERATORS = ON; + LIMIT_AHDL_INTEGERS_TO_32_BITS = OFF; + ENABLE_BUS_HOLD_CIRCUITRY = OFF; + WEAK_PULL_UP_RESISTOR = OFF; + TURBO_BIT = ON; + MAX7000_IGNORE_SOFT_BUFFERS = OFF; + IGNORE_SOFT_BUFFERS = ON; + MAX7000_IGNORE_LCELL_BUFFERS = AUTO; + IGNORE_LCELL_BUFFERS = OFF; + IGNORE_ROW_GLOBAL_BUFFERS = OFF; + IGNORE_GLOBAL_BUFFERS = OFF; + IGNORE_CASCADE_BUFFERS = OFF; + IGNORE_CARRY_BUFFERS = OFF; + REMOVE_DUPLICATE_REGISTERS = ON; + REMOVE_REDUNDANT_LOGIC_CELLS = OFF; + ALLOW_POWER_UP_DONT_CARE = ON; + PCI_IO = OFF; + NOT_GATE_PUSH_BACK = ON; + SLOW_SLEW_RATE = OFF; + DSP_BLOCK_BALANCING = AUTO; + STATE_MACHINE_PROCESSING = AUTO; +} +DEFAULT_HARDCOPY_SETTINGS +{ + HARDCOPY_EXTERNAL_CLOCK_JITTER = "0.0 NS"; +} +DEFAULT_TIMING_REQUIREMENTS +{ + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + RUN_ALL_TIMING_ANALYSES = ON; + IGNORE_CLOCK_SETTINGS = OFF; + DEFAULT_HOLD_MULTICYCLE = "SAME AS MULTICYCLE"; + CUT_OFF_IO_PIN_FEEDBACK = ON; + CUT_OFF_CLEAR_AND_PRESET_PATHS = ON; + CUT_OFF_READ_DURING_WRITE_PATHS = ON; + CUT_OFF_PATHS_BETWEEN_CLOCK_DOMAINS = ON; + DO_MIN_ANALYSIS = ON; + DO_MIN_TIMING = OFF; + NUMBER_OF_PATHS_TO_REPORT = 200; + NUMBER_OF_DESTINATION_TO_REPORT = 10; + NUMBER_OF_SOURCES_PER_DESTINATION_TO_REPORT = 10; + MAX_SCC_SIZE = 50; +} +HDL_SETTINGS +{ + VERILOG_INPUT_VERSION = VERILOG_2001; + ENABLE_IP_DEBUG = OFF; + VHDL_INPUT_VERSION = VHDL93; + VHDL_SHOW_LMF_MAPPING_MESSAGES = OFF; +} +PROJECT_INFO(usrp_std) +{ + ORIGINAL_QUARTUS_VERSION = 3.0; + PROJECT_CREATION_TIME_DATE = "00:14:04 JULY 13, 2003"; + LAST_QUARTUS_VERSION = 3.0; + SHOW_REGISTRATION_MESSAGE = ON; + USER_LIBRARIES = "e:\usrp\fpga\megacells"; +} +THIRD_PARTY_EDA_TOOLS(usrp_std) +{ + EDA_DESIGN_ENTRY_SYNTHESIS_TOOL = ""; + EDA_SIMULATION_TOOL = ""; + EDA_TIMING_ANALYSIS_TOOL = ""; + EDA_BOARD_DESIGN_TOOL = ""; + EDA_FORMAL_VERIFICATION_TOOL = ""; + EDA_RESYNTHESIS_TOOL = ""; +} +EDA_TOOL_SETTINGS(eda_design_synthesis) +{ + EDA_INPUT_GND_NAME = GND; + EDA_INPUT_VCC_NAME = VCC; + EDA_SHOW_LMF_MAPPING_MESSAGES = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_INPUT_DATA_FORMAT = EDIF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_simulation) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_timing_analysis) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + EDA_LAUNCH_CMD_LINE_TOOL = OFF; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_board_design) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_formal_verification) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + RESYNTHESIS_RETIMING = FULL; +} +EDA_TOOL_SETTINGS(eda_palace) +{ + EDA_INCLUDE_VHDL_CONFIGURATION_DECLARATION = OFF; + EDA_TRUNCATE_LONG_HIERARCHY_PATHS = OFF; + EDA_MAINTAIN_DESIGN_HIERARCHY = OFF; + EDA_WRITE_DEVICE_CONTROL_PORTS = OFF; + EDA_GENERATE_FUNCTIONAL_NETLIST = OFF; + EDA_FLATTEN_BUSES = OFF; + EDA_MAP_ILLEGAL_CHARACTERS = OFF; + EDA_EXCALIBUR_ATOMS_AS_SINGLE_STRIPE = OFF; + EDA_RUN_TOOL_AUTOMATICALLY = OFF; + EDA_OUTPUT_DATA_FORMAT = NONE; + RESYNTHESIS_RETIMING = FULL; + RESYNTHESIS_PHYSICAL_SYNTHESIS = NORMAL; + RESYNTHESIS_OPTIMIZATION_EFFORT = NORMAL; + USE_GENERATED_PHYSICAL_CONSTRAINTS = ON; +} +CLOCK(clk_120mhz) +{ + FMAX_REQUIREMENT = "120.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(usbclk) +{ + FMAX_REQUIREMENT = "48.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(SCLK) +{ + FMAX_REQUIREMENT = "1.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(adclk0) +{ + FMAX_REQUIREMENT = "60.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} +CLOCK(adclk1) +{ + FMAX_REQUIREMENT = "60.0 MHz"; + INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS = OFF; + DUTY_CYCLE = 50; + DIVIDE_BASE_CLOCK_PERIOD_BY = 1; + MULTIPLY_BASE_CLOCK_PERIOD_BY = 1; + INVERT_BASE_CLOCK = OFF; +} diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.qpf b/usrp/fpga/toplevel/usrp_std/usrp_std.qpf new file mode 100644 index 00000000..e8b27505 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.qpf @@ -0,0 +1,29 @@ +# Copyright (C) 1991-2004 Altera Corporation +# Any megafunction design, and related netlist (encrypted or decrypted), +# support information, device programming or simulation file, and any other +# associated documentation or information provided by Altera or a partner +# under Altera's Megafunction Partnership Program may be used only +# to program PLD devices (but not masked PLD devices) from Altera. Any +# other use of such megafunction design, netlist, support information, +# device programming or simulation file, or any other related documentation +# or information is prohibited for any other purpose, including, but not +# limited to modification, reverse engineering, de-compiling, or use with +# any other silicon devices, unless such use is explicitly licensed under +# a separate agreement with Altera or a megafunction partner. Title to the +# intellectual property, including patents, copyrights, trademarks, trade +# secrets, or maskworks, embodied in any such megafunction design, netlist, +# support information, device programming or simulation file, or any other +# related documentation or information provided by Altera or a megafunction +# partner, remains with Altera, the megafunction partner, or their respective +# licensors. No other licenses, including any licenses needed under any third +# party's intellectual property, are provided herein. + + + +QUARTUS_VERSION = "4.0" +DATE = "17:10:11 December 20, 2004" + + +# Active Revisions + +PROJECT_REVISION = "usrp_std" diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.qsf b/usrp/fpga/toplevel/usrp_std/usrp_std.qsf new file mode 100644 index 00000000..51d7e1ea --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.qsf @@ -0,0 +1,406 @@ +# Copyright (C) 1991-2005 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. + + +# The default values for assignments are stored in the file +# usrp_std_assignment_defaults.qdf +# If this file doesn't exist, and for assignments not listed, see file +# assignment_defaults.qdf + +# Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 3.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "00:14:04 JULY 13, 2003" +set_global_assignment -name LAST_QUARTUS_VERSION "5.1 SP2" + +# Pin & Location Assignments +# ========================== +set_global_assignment -name RESERVE_PIN "AS INPUT TRI-STATED" +set_location_assignment PIN_29 -to SCLK +set_location_assignment PIN_117 -to SDI +set_location_assignment PIN_28 -to usbclk +set_location_assignment PIN_107 -to usbctl[0] +set_location_assignment PIN_106 -to usbctl[1] +set_location_assignment PIN_105 -to usbctl[2] +set_location_assignment PIN_100 -to usbdata[0] +set_location_assignment PIN_84 -to usbdata[10] +set_location_assignment PIN_83 -to usbdata[11] +set_location_assignment PIN_82 -to usbdata[12] +set_location_assignment PIN_79 -to usbdata[13] +set_location_assignment PIN_78 -to usbdata[14] +set_location_assignment PIN_77 -to usbdata[15] +set_location_assignment PIN_99 -to usbdata[1] +set_location_assignment PIN_98 -to usbdata[2] +set_location_assignment PIN_95 -to usbdata[3] +set_location_assignment PIN_94 -to usbdata[4] +set_location_assignment PIN_93 -to usbdata[5] +set_location_assignment PIN_88 -to usbdata[6] +set_location_assignment PIN_87 -to usbdata[7] +set_location_assignment PIN_86 -to usbdata[8] +set_location_assignment PIN_85 -to usbdata[9] +set_location_assignment PIN_104 -to usbrdy[0] +set_location_assignment PIN_101 -to usbrdy[1] +set_location_assignment PIN_76 -to FX2_1 +set_location_assignment PIN_75 -to FX2_2 +set_location_assignment PIN_74 -to FX2_3 +set_location_assignment PIN_116 -to io_rx_a[0] +set_location_assignment PIN_115 -to io_rx_a[1] +set_location_assignment PIN_114 -to io_rx_a[2] +set_location_assignment PIN_113 -to io_rx_a[3] +set_location_assignment PIN_108 -to io_rx_a[4] +set_location_assignment PIN_195 -to io_rx_a[5] +set_location_assignment PIN_196 -to io_rx_a[6] +set_location_assignment PIN_197 -to io_rx_a[7] +set_location_assignment PIN_200 -to io_rx_a[8] +set_location_assignment PIN_201 -to io_rx_a[9] +set_location_assignment PIN_202 -to io_rx_a[10] +set_location_assignment PIN_203 -to io_rx_a[11] +set_location_assignment PIN_206 -to io_rx_a[12] +set_location_assignment PIN_207 -to io_rx_a[13] +set_location_assignment PIN_208 -to io_rx_a[14] +set_location_assignment PIN_214 -to io_rx_b[0] +set_location_assignment PIN_215 -to io_rx_b[1] +set_location_assignment PIN_216 -to io_rx_b[2] +set_location_assignment PIN_217 -to io_rx_b[3] +set_location_assignment PIN_218 -to io_rx_b[4] +set_location_assignment PIN_219 -to io_rx_b[5] +set_location_assignment PIN_222 -to io_rx_b[6] +set_location_assignment PIN_223 -to io_rx_b[7] +set_location_assignment PIN_224 -to io_rx_b[8] +set_location_assignment PIN_225 -to io_rx_b[9] +set_location_assignment PIN_226 -to io_rx_b[10] +set_location_assignment PIN_227 -to io_rx_b[11] +set_location_assignment PIN_228 -to io_rx_b[12] +set_location_assignment PIN_233 -to io_rx_b[13] +set_location_assignment PIN_234 -to io_rx_b[14] +set_location_assignment PIN_175 -to io_tx_a[0] +set_location_assignment PIN_176 -to io_tx_a[1] +set_location_assignment PIN_177 -to io_tx_a[2] +set_location_assignment PIN_178 -to io_tx_a[3] +set_location_assignment PIN_179 -to io_tx_a[4] +set_location_assignment PIN_180 -to io_tx_a[5] +set_location_assignment PIN_181 -to io_tx_a[6] +set_location_assignment PIN_182 -to io_tx_a[7] +set_location_assignment PIN_183 -to io_tx_a[8] +set_location_assignment PIN_184 -to io_tx_a[9] +set_location_assignment PIN_185 -to io_tx_a[10] +set_location_assignment PIN_186 -to io_tx_a[11] +set_location_assignment PIN_187 -to io_tx_a[12] +set_location_assignment PIN_188 -to io_tx_a[13] +set_location_assignment PIN_193 -to io_tx_a[14] +set_location_assignment PIN_73 -to io_tx_b[0] +set_location_assignment PIN_68 -to io_tx_b[1] +set_location_assignment PIN_67 -to io_tx_b[2] +set_location_assignment PIN_66 -to io_tx_b[3] +set_location_assignment PIN_65 -to io_tx_b[4] +set_location_assignment PIN_64 -to io_tx_b[5] +set_location_assignment PIN_63 -to io_tx_b[6] +set_location_assignment PIN_62 -to io_tx_b[7] +set_location_assignment PIN_61 -to io_tx_b[8] +set_location_assignment PIN_60 -to io_tx_b[9] +set_location_assignment PIN_59 -to io_tx_b[10] +set_location_assignment PIN_58 -to io_tx_b[11] +set_location_assignment PIN_57 -to io_tx_b[12] +set_location_assignment PIN_56 -to io_tx_b[13] +set_location_assignment PIN_55 -to io_tx_b[14] +set_location_assignment PIN_152 -to master_clk +set_location_assignment PIN_144 -to rx_a_a[0] +set_location_assignment PIN_143 -to rx_a_a[1] +set_location_assignment PIN_141 -to rx_a_a[2] +set_location_assignment PIN_140 -to rx_a_a[3] +set_location_assignment PIN_139 -to rx_a_a[4] +set_location_assignment PIN_138 -to rx_a_a[5] +set_location_assignment PIN_137 -to rx_a_a[6] +set_location_assignment PIN_136 -to rx_a_a[7] +set_location_assignment PIN_135 -to rx_a_a[8] +set_location_assignment PIN_134 -to rx_a_a[9] +set_location_assignment PIN_133 -to rx_a_a[10] +set_location_assignment PIN_132 -to rx_a_a[11] +set_location_assignment PIN_23 -to rx_a_b[0] +set_location_assignment PIN_21 -to rx_a_b[1] +set_location_assignment PIN_20 -to rx_a_b[2] +set_location_assignment PIN_19 -to rx_a_b[3] +set_location_assignment PIN_18 -to rx_a_b[4] +set_location_assignment PIN_17 -to rx_a_b[5] +set_location_assignment PIN_16 -to rx_a_b[6] +set_location_assignment PIN_15 -to rx_a_b[7] +set_location_assignment PIN_14 -to rx_a_b[8] +set_location_assignment PIN_13 -to rx_a_b[9] +set_location_assignment PIN_12 -to rx_a_b[10] +set_location_assignment PIN_11 -to rx_a_b[11] +set_location_assignment PIN_131 -to rx_b_a[0] +set_location_assignment PIN_128 -to rx_b_a[1] +set_location_assignment PIN_127 -to rx_b_a[2] +set_location_assignment PIN_126 -to rx_b_a[3] +set_location_assignment PIN_125 -to rx_b_a[4] +set_location_assignment PIN_124 -to rx_b_a[5] +set_location_assignment PIN_123 -to rx_b_a[6] +set_location_assignment PIN_122 -to rx_b_a[7] +set_location_assignment PIN_121 -to rx_b_a[8] +set_location_assignment PIN_120 -to rx_b_a[9] +set_location_assignment PIN_119 -to rx_b_a[10] +set_location_assignment PIN_118 -to rx_b_a[11] +set_location_assignment PIN_8 -to rx_b_b[0] +set_location_assignment PIN_7 -to rx_b_b[1] +set_location_assignment PIN_6 -to rx_b_b[2] +set_location_assignment PIN_5 -to rx_b_b[3] +set_location_assignment PIN_4 -to rx_b_b[4] +set_location_assignment PIN_3 -to rx_b_b[5] +set_location_assignment PIN_2 -to rx_b_b[6] +set_location_assignment PIN_240 -to rx_b_b[7] +set_location_assignment PIN_239 -to rx_b_b[8] +set_location_assignment PIN_238 -to rx_b_b[9] +set_location_assignment PIN_237 -to rx_b_b[10] +set_location_assignment PIN_236 -to rx_b_b[11] +set_location_assignment PIN_156 -to SDO +set_location_assignment PIN_153 -to SEN_FPGA +set_location_assignment PIN_159 -to tx_a[0] +set_location_assignment PIN_160 -to tx_a[1] +set_location_assignment PIN_161 -to tx_a[2] +set_location_assignment PIN_162 -to tx_a[3] +set_location_assignment PIN_163 -to tx_a[4] +set_location_assignment PIN_164 -to tx_a[5] +set_location_assignment PIN_165 -to tx_a[6] +set_location_assignment PIN_166 -to tx_a[7] +set_location_assignment PIN_167 -to tx_a[8] +set_location_assignment PIN_168 -to tx_a[9] +set_location_assignment PIN_169 -to tx_a[10] +set_location_assignment PIN_170 -to tx_a[11] +set_location_assignment PIN_173 -to tx_a[12] +set_location_assignment PIN_174 -to tx_a[13] +set_location_assignment PIN_38 -to tx_b[0] +set_location_assignment PIN_39 -to tx_b[1] +set_location_assignment PIN_41 -to tx_b[2] +set_location_assignment PIN_42 -to tx_b[3] +set_location_assignment PIN_43 -to tx_b[4] +set_location_assignment PIN_44 -to tx_b[5] +set_location_assignment PIN_45 -to tx_b[6] +set_location_assignment PIN_46 -to tx_b[7] +set_location_assignment PIN_47 -to tx_b[8] +set_location_assignment PIN_48 -to tx_b[9] +set_location_assignment PIN_49 -to tx_b[10] +set_location_assignment PIN_50 -to tx_b[11] +set_location_assignment PIN_53 -to tx_b[12] +set_location_assignment PIN_54 -to tx_b[13] +set_location_assignment PIN_158 -to TXSYNC_A +set_location_assignment PIN_37 -to TXSYNC_B +set_location_assignment PIN_235 -to io_rx_b[15] +set_location_assignment PIN_24 -to io_tx_b[15] +set_location_assignment PIN_213 -to io_rx_a[15] +set_location_assignment PIN_194 -to io_tx_a[15] +set_location_assignment PIN_1 -to MYSTERY_SIGNAL + +# Timing Assignments +# ================== +set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 240 +set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "" +set_global_assignment -name FAMILY Cyclone +set_global_assignment -name CYCLONE_OPTIMIZATION_TECHNIQUE BALANCED +set_global_assignment -name STRATIX_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name APEX20K_OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name TOP_LEVEL_ENTITY usrp_std +set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name USER_LIBRARIES "e:\\usrp\\fpga\\megacells" +set_global_assignment -name AUTO_ENABLE_SMART_COMPILE On + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP1C12Q240C8 +set_global_assignment -name CYCLONE_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" +set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF +set_global_assignment -name OPTIMIZE_TIMING "NORMAL COMPILATION" +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF +set_global_assignment -name IO_PLACEMENT_OPTIMIZATION OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL +set_global_assignment -name INC_PLC_MODE OFF +set_global_assignment -name ROUTING_BACK_ANNOTATION_MODE OFF +set_instance_assignment -name IO_STANDARD LVTTL -to usbdata[12] +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD LVTTL +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 + +# Timing Analysis Assignments +# =========================== +set_global_assignment -name MAX_SCC_SIZE 50 + +# EDA Netlist Writer Assignments +# ============================== +set_global_assignment -name EDA_SIMULATION_TOOL "" +set_global_assignment -name EDA_TIMING_ANALYSIS_TOOL "" +set_global_assignment -name EDA_BOARD_DESIGN_TOOL "" +set_global_assignment -name EDA_FORMAL_VERIFICATION_TOOL "" +set_global_assignment -name EDA_RESYNTHESIS_TOOL "" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name RESERVE_ALL_UNUSED_PINS_NO_OUTPUT_GND "AS INPUT TRI-STATED" +set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF + +# Simulator Assignments +# ===================== +set_global_assignment -name START_TIME "0 ns" +set_global_assignment -name GLITCH_INTERVAL "1 ns" + +# Design Assistant Assignments +# ============================ +set_global_assignment -name DRC_REPORT_TOP_FANOUT OFF +set_global_assignment -name DRC_REPORT_FANOUT_EXCEEDING OFF +set_global_assignment -name ASSG_CAT OFF +set_global_assignment -name ASSG_RULE_MISSING_FMAX OFF +set_global_assignment -name ASSG_RULE_MISSING_TIMING OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ASYN_RAM OFF +set_global_assignment -name CLK_CAT OFF +set_global_assignment -name CLK_RULE_COMB_CLOCK OFF +set_global_assignment -name CLK_RULE_INV_CLOCK OFF +set_global_assignment -name CLK_RULE_GATING_SCHEME OFF +set_global_assignment -name CLK_RULE_INPINS_CLKNET OFF +set_global_assignment -name CLK_RULE_CLKNET_CLKSPINES OFF +set_global_assignment -name CLK_RULE_MIX_EDGES OFF +set_global_assignment -name RESET_CAT OFF +set_global_assignment -name RESET_RULE_INPINS_RESETNET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_IMSYNCH_EXRESET OFF +set_global_assignment -name RESET_RULE_COMB_ASYNCH_RESET OFF +set_global_assignment -name RESET_RULE_UNSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name RESET_RULE_IMSYNCH_ASYNCH_DOMAIN OFF +set_global_assignment -name TIMING_CAT OFF +set_global_assignment -name TIMING_RULE_SHIFT_REG OFF +set_global_assignment -name TIMING_RULE_COIN_CLKEDGE OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMB_DRIVES_RAM_WE OFF +set_global_assignment -name NONSYNCHSTRUCT_CAT OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_COMBLOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_REG_LOOP OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_DELAY_CHAIN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_RIPPLE_CLK OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_ILLEGAL_PULSE_GEN OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_MULTI_VIBRATOR OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_SRLATCH OFF +set_global_assignment -name NONSYNCHSTRUCT_RULE_LATCH_UNIDENTIFIED OFF +set_global_assignment -name SIGNALRACE_CAT OFF +set_global_assignment -name ACLK_CAT OFF +set_global_assignment -name ACLK_RULE_NO_SZER_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_SZER_BTW_ACLK_DOMAIN OFF +set_global_assignment -name ACLK_RULE_IMSZER_ADOMAIN OFF +set_global_assignment -name HCPY_CAT OFF +set_global_assignment -name HCPY_VREF_PINS OFF + +# SignalTap II Assignments +# ======================== +set_global_assignment -name HUB_ENTITY_NAME SLD_HUB +set_global_assignment -name HUB_INSTANCE_NAME SLD_HUB_INST +set_global_assignment -name ENABLE_SIGNALTAP Off + +# LogicLock Region Assignments +# ============================ +set_global_assignment -name LOGICLOCK_INCREMENTAL_COMPILE_ASSIGNMENT OFF + +# ----------------- +# start CLOCK(SCLK) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id SCLK + set_global_assignment -name FMAX_REQUIREMENT "1.0 MHz" -section_id SCLK + set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id SCLK + +# end CLOCK(SCLK) +# --------------- + +# ----------------------- +# start CLOCK(master_clk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id master_clk + set_global_assignment -name FMAX_REQUIREMENT "64.0 MHz" -section_id master_clk + set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id master_clk + +# end CLOCK(master_clk) +# --------------------- + +# ------------------- +# start CLOCK(usbclk) + + # Timing Assignments + # ================== +set_global_assignment -name DUTY_CYCLE 50 -section_id usbclk + set_global_assignment -name FMAX_REQUIREMENT "48.0 MHz" -section_id usbclk + set_global_assignment -name INCLUDE_EXTERNAL_PIN_DELAYS_IN_FMAX_CALCULATIONS OFF -section_id usbclk + +# end CLOCK(usbclk) +# ----------------- + +# ---------------------- +# start ENTITY(usrp_std) + + # Timing Assignments + # ================== + set_instance_assignment -name CLOCK_SETTINGS SCLK -to SCLK + set_instance_assignment -name CLOCK_SETTINGS usbclk -to usbclk + set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk + +# end ENTITY(usrp_std) +# -------------------- + +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rssi.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/ram16.v +set_global_assignment -name VERILOG_FILE usrp_std.vh +set_global_assignment -name VERILOG_FILE ../../megacells/fifo_4k.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/acc.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mult.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/ram16_2sum.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_rom.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/halfband_decim.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mac.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_ram.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_chain.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_dcoffset.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/adc_interface.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/io_pins.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/setting_reg.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/bidir_reg.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_int_shifter.v +set_global_assignment -name VERILOG_FILE ../../megacells/clk_doubler.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_chain.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/gen_sync.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/master_control.v +set_global_assignment -name VERILOG_FILE ../../megacells/fifo_2k.v +set_global_assignment -name VERILOG_FILE ../../megacells/bustri.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_buffer.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_buffer.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/phase_acc.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_interp.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_decim.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cordic_stage.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/cordic.v +set_global_assignment -name VERILOG_FILE usrp_std.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/clk_divider.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/serial_io.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/strobe_gen.v +set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v \ No newline at end of file diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.v b/usrp/fpga/toplevel/usrp_std/usrp_std.v new file mode 100644 index 00000000..9ba8c7c6 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.v @@ -0,0 +1,324 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003,2004 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Top level module for a full setup with DUCs and DDCs + +// Define DEBUG_OWNS_IO_PINS if we're using the daughterboard i/o pins +// for debugging info. NB, This can kill the m'board and/or d'board if you +// have anything except basic d'boards installed. + +// Uncomment the following to include optional circuitry + +`include "usrp_std.vh" +`include "../../../firmware/include/fpga_regs_common.v" +`include "../../../firmware/include/fpga_regs_standard.v" + +module usrp_std +(output MYSTERY_SIGNAL, + input master_clk, + input SCLK, + input SDI, + inout SDO, + input SEN_FPGA, + + input FX2_1, + output FX2_2, + output FX2_3, + + input wire [11:0] rx_a_a, + input wire [11:0] rx_b_a, + input wire [11:0] rx_a_b, + input wire [11:0] rx_b_b, + + output wire [13:0] tx_a, + output wire [13:0] tx_b, + + output wire TXSYNC_A, + output wire TXSYNC_B, + + // USB interface + input usbclk, + input wire [2:0] usbctl, + output wire [1:0] usbrdy, + inout [15:0] usbdata, // NB Careful, inout + + // These are the general purpose i/o's that go to the daughterboard slots + inout wire [15:0] io_tx_a, + inout wire [15:0] io_tx_b, + inout wire [15:0] io_rx_a, + inout wire [15:0] io_rx_b + ); + wire [15:0] debugdata,debugctrl; + assign MYSTERY_SIGNAL = 1'b0; + + wire clk64,clk128; + + wire WR = usbctl[0]; + wire RD = usbctl[1]; + wire OE = usbctl[2]; + + wire have_space, have_pkt_rdy; + assign usbrdy[0] = have_space; + assign usbrdy[1] = have_pkt_rdy; + + wire tx_underrun, rx_overrun; + wire clear_status = FX2_1; + assign FX2_2 = rx_overrun; + assign FX2_3 = tx_underrun; + + wire [15:0] usbdata_out; + + wire [3:0] dac0mux,dac1mux,dac2mux,dac3mux; + + wire tx_realsignals; + wire [3:0] rx_numchan; + wire [2:0] tx_numchan; + + wire [7:0] interp_rate, decim_rate; + wire [15:0] tx_debugbus, rx_debugbus; + + wire enable_tx, enable_rx; + wire tx_dsp_reset, rx_dsp_reset, tx_bus_reset, rx_bus_reset; + wire [7:0] settings; + + // Tri-state bus macro + bustri bustri( .data(usbdata_out),.enabledt(OE),.tridata(usbdata) ); + + assign clk64 = master_clk; + + wire [15:0] ch0tx,ch1tx,ch2tx,ch3tx; //,ch4tx,ch5tx,ch6tx,ch7tx; + wire [15:0] ch0rx,ch1rx,ch2rx,ch3rx,ch4rx,ch5rx,ch6rx,ch7rx; + + // TX + wire [15:0] i_out_0,i_out_1,q_out_0,q_out_1; + wire [15:0] bb_tx_i0,bb_tx_q0,bb_tx_i1,bb_tx_q1; // bb_tx_i2,bb_tx_q2,bb_tx_i3,bb_tx_q3; + + wire strobe_interp, tx_sample_strobe; + wire tx_empty; + + wire serial_strobe; + wire [6:0] serial_addr; + wire [31:0] serial_data; + + reg [15:0] debug_counter; + reg [15:0] loopback_i_0,loopback_q_0; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Transmit Side +`ifdef TX_ON + assign bb_tx_i0 = ch0tx; + assign bb_tx_q0 = ch1tx; + assign bb_tx_i1 = ch2tx; + assign bb_tx_q1 = ch3tx; + + tx_buffer tx_buffer + ( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset), + .usbdata(usbdata),.WR(WR),.have_space(have_space),.tx_underrun(tx_underrun), + .channels({tx_numchan,1'b0}), + .tx_i_0(ch0tx),.tx_q_0(ch1tx), + .tx_i_1(ch2tx),.tx_q_1(ch3tx), + .tx_i_2(),.tx_q_2(), + .tx_i_3(),.tx_q_3(), + .txclk(clk64),.txstrobe(strobe_interp), + .clear_status(clear_status), + .tx_empty(tx_empty), + .debugbus(tx_debugbus) ); + + tx_chain tx_chain_0 + ( .clock(clk64),.reset(tx_dsp_reset),.enable(enable_tx), + .interp_rate(interp_rate),.sample_strobe(tx_sample_strobe), + .interpolator_strobe(strobe_interp),.freq(), + .i_in(bb_tx_i0),.q_in(bb_tx_q0),.i_out(i_out_0),.q_out(q_out_0) ); + + tx_chain tx_chain_1 + ( .clock(clk64),.reset(tx_dsp_reset),.enable(enable_tx), + .interp_rate(interp_rate),.sample_strobe(tx_sample_strobe), + .interpolator_strobe(strobe_interp),.freq(), + .i_in(bb_tx_i1),.q_in(bb_tx_q1),.i_out(i_out_1),.q_out(q_out_1) ); + + setting_reg #(`FR_TX_MUX) + sr_txmux(.clock(clk64),.reset(tx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data), + .out({dac3mux,dac2mux,dac1mux,dac0mux,tx_realsignals,tx_numchan})); + + wire [15:0] tx_a_a = dac0mux[3] ? (dac0mux[1] ? (dac0mux[0] ? q_out_1 : i_out_1) : (dac0mux[0] ? q_out_0 : i_out_0)) : 16'b0; + wire [15:0] tx_b_a = dac1mux[3] ? (dac1mux[1] ? (dac1mux[0] ? q_out_1 : i_out_1) : (dac1mux[0] ? q_out_0 : i_out_0)) : 16'b0; + wire [15:0] tx_a_b = dac2mux[3] ? (dac2mux[1] ? (dac2mux[0] ? q_out_1 : i_out_1) : (dac2mux[0] ? q_out_0 : i_out_0)) : 16'b0; + wire [15:0] tx_b_b = dac3mux[3] ? (dac3mux[1] ? (dac3mux[0] ? q_out_1 : i_out_1) : (dac3mux[0] ? q_out_0 : i_out_0)) : 16'b0; + + wire txsync = tx_sample_strobe; + assign TXSYNC_A = txsync; + assign TXSYNC_B = txsync; + + assign tx_a = txsync ? tx_b_a[15:2] : tx_a_a[15:2]; + assign tx_b = txsync ? tx_b_b[15:2] : tx_a_b[15:2]; +`endif // `ifdef TX_ON + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Receive Side +`ifdef RX_ON + wire rx_sample_strobe,strobe_decim,hb_strobe; + wire [15:0] bb_rx_i0,bb_rx_q0,bb_rx_i1,bb_rx_q1, + bb_rx_i2,bb_rx_q2,bb_rx_i3,bb_rx_q3; + + wire loopback = settings[0]; + wire counter = settings[1]; + + always @(posedge clk64) + if(rx_dsp_reset) + debug_counter <= #1 16'd0; + else if(~enable_rx) + debug_counter <= #1 16'd0; + else if(hb_strobe) + debug_counter <=#1 debug_counter + 16'd2; + + always @(posedge clk64) + if(strobe_interp) + begin + loopback_i_0 <= #1 ch0tx; + loopback_q_0 <= #1 ch1tx; + end + + assign ch0rx = counter ? debug_counter : loopback ? loopback_i_0 : bb_rx_i0; + assign ch1rx = counter ? debug_counter + 16'd1 : loopback ? loopback_q_0 : bb_rx_q0; + assign ch2rx = bb_rx_i1; + assign ch3rx = bb_rx_q1; + assign ch4rx = bb_rx_i2; + assign ch5rx = bb_rx_q2; + assign ch6rx = bb_rx_i3; + assign ch7rx = bb_rx_q3; + + wire [15:0] ddc0_in_i,ddc0_in_q,ddc1_in_i,ddc1_in_q,ddc2_in_i,ddc2_in_q,ddc3_in_i,ddc3_in_q; + wire [31:0] rssi_0,rssi_1,rssi_2,rssi_3; + + adc_interface adc_interface(.clock(clk64),.reset(rx_dsp_reset),.enable(1'b1), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .rx_a_a(rx_a_a),.rx_b_a(rx_b_a),.rx_a_b(rx_a_b),.rx_b_b(rx_b_b), + .rssi_0(rssi_0),.rssi_1(rssi_1),.rssi_2(rssi_2),.rssi_3(rssi_3), + .ddc0_in_i(ddc0_in_i),.ddc0_in_q(ddc0_in_q), + .ddc1_in_i(ddc1_in_i),.ddc1_in_q(ddc1_in_q), + .ddc2_in_i(ddc2_in_i),.ddc2_in_q(ddc2_in_q), + .ddc3_in_i(ddc3_in_i),.ddc3_in_q(ddc3_in_q),.rx_numchan(rx_numchan) ); + + rx_buffer rx_buffer + ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset), + .reset_regs(rx_dsp_reset), + .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun), + .channels(rx_numchan), + .ch_0(ch0rx),.ch_1(ch1rx), + .ch_2(ch2rx),.ch_3(ch3rx), + .ch_4(ch4rx),.ch_5(ch5rx), + .ch_6(ch6rx),.ch_7(ch7rx), + .rxclk(clk64),.rxstrobe(hb_strobe), + .clear_status(clear_status), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .debugbus(rx_debugbus) ); + + `ifdef RX_EN_0 + rx_chain #(`FR_RX_FREQ_0,`FR_RX_PHASE_0) rx_chain_0 + ( .clock(clk64),.reset(1'b0),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(hb_strobe), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc0_in_i),.q_in(ddc0_in_q),.i_out(bb_rx_i0),.q_out(bb_rx_q0),.debugdata(debugdata),.debugctrl(debugctrl)); + `else + assign bb_rx_i0=16'd0; + assign bb_rx_q0=16'd0; + `endif + + `ifdef RX_EN_1 + rx_chain #(`FR_RX_FREQ_1,`FR_RX_PHASE_1) rx_chain_1 + ( .clock(clk64),.reset(1'b0),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc1_in_i),.q_in(ddc1_in_q),.i_out(bb_rx_i1),.q_out(bb_rx_q1)); + `else + assign bb_rx_i1=16'd0; + assign bb_rx_q1=16'd0; + `endif + + `ifdef RX_EN_2 + rx_chain #(`FR_RX_FREQ_2,`FR_RX_PHASE_2) rx_chain_2 + ( .clock(clk64),.reset(1'b0),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc2_in_i),.q_in(ddc2_in_q),.i_out(bb_rx_i2),.q_out(bb_rx_q2)); + `else + assign bb_rx_i2=16'd0; + assign bb_rx_q2=16'd0; + `endif + + `ifdef RX_EN_3 + rx_chain #(`FR_RX_FREQ_3,`FR_RX_PHASE_3) rx_chain_3 + ( .clock(clk64),.reset(1'b0),.enable(enable_rx), + .decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .i_in(ddc3_in_i),.q_in(ddc3_in_q),.i_out(bb_rx_i3),.q_out(bb_rx_q3)); + `else + assign bb_rx_i3=16'd0; + assign bb_rx_q3=16'd0; + `endif + +`endif // `ifdef RX_ON + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Control Functions + + wire [31:0] capabilities; + assign capabilities[7] = `TX_CAP_HB; + assign capabilities[6:4] = `TX_CAP_NCHAN; + assign capabilities[3] = `RX_CAP_HB; + assign capabilities[2:0] = `RX_CAP_NCHAN; + + + serial_io serial_io + ( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI), + .enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .readback_0({io_rx_a,io_tx_a}),.readback_1({io_rx_b,io_tx_b}),.readback_2(capabilities),.readback_3(32'hf0f0931a), + .readback_4(rssi_0),.readback_5(rssi_1),.readback_6(rssi_2),.readback_7(rssi_3) + ); + + wire [15:0] reg_0,reg_1,reg_2,reg_3; + master_control master_control + ( .master_clk(clk64),.usbclk(usbclk), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe), + .tx_bus_reset(tx_bus_reset),.rx_bus_reset(rx_bus_reset), + .tx_dsp_reset(tx_dsp_reset),.rx_dsp_reset(rx_dsp_reset), + .enable_tx(enable_tx),.enable_rx(enable_rx), + .interp_rate(interp_rate),.decim_rate(decim_rate), + .tx_sample_strobe(tx_sample_strobe),.strobe_interp(strobe_interp), + .rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim), + .tx_empty(tx_empty), + //.debug_0(rx_a_a),.debug_1(ddc0_in_i), + .debug_0(rx_debugbus),.debug_1(ddc0_in_i), + .debug_2({rx_sample_strobe,strobe_decim,serial_strobe,serial_addr}),.debug_3({rx_dsp_reset,tx_dsp_reset,rx_bus_reset,tx_bus_reset,enable_rx,tx_underrun,rx_overrun,decim_rate}), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) ); + + io_pins io_pins + (.io_0(io_tx_a),.io_1(io_rx_a),.io_2(io_tx_b),.io_3(io_rx_b), + .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3), + .clock(clk64),.rx_reset(rx_dsp_reset),.tx_reset(tx_dsp_reset), + .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe)); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Misc Settings + setting_reg #(`FR_MODE) sr_misc(.clock(clk64),.reset(rx_dsp_reset),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(settings)); + +endmodule // usrp_std diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std.vh b/usrp/fpga/toplevel/usrp_std/usrp_std.vh new file mode 100644 index 00000000..65aed9b4 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std.vh @@ -0,0 +1,119 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// ==================================================================== +// User control over what parts get included +// +// >>>> EDIT ONLY THIS SECTION <<<< +// +// ==================================================================== + +// Uncomment this for 2 rx channels (w/ halfband) & 2 transmit channels + `include "usrp_std_config_2rxhb_2tx.vh" + +// Uncomment this for 4 rx channels (w/o halfband) & 0 transmit channels +//`include "usrp_std_config_4rx_0tx.vh" + +// Add other "known to fit" configurations here... + +// ==================================================================== +// +// >>>> DO NOT EDIT BELOW HERE <<<< +// +// [The stuff from here down is derived from the stuff included above] +// +// N.B., *all* the remainder of the code should be conditionalized +// only in terms of: +// +// TX_ON, TX_EN_0, TX_EN_1, TX_EN_2, TX_EN_3, TX_CAP_NCHAN, TX_CAP_HB, +// RX_ON, RX_EN_0, RX_EN_1, RX_EN_2, RX_EN_3, RX_CAP_NCHAN, RX_CAP_HB, +// RX_NCO_ON, RX_CIC_ON +// ==================================================================== + +`ifdef TX_ON + + `ifdef TX_SINGLE + `define TX_EN_0 + `define TX_CAP_NCHAN 3'd1 + `endif + + `ifdef TX_DUAL + `define TX_EN_0 + `define TX_EN_1 + `define TX_CAP_NCHAN 3'd2 + `endif + + `ifdef TX_QUAD + `define TX_EN_0 + `define TX_EN_1 + `define TX_EN_2 + `define TX_EN_3 + `define TX_CAP_NCHAN 3'd4 + `endif + + `ifdef TX_HB_ON + `define TX_CAP_HB 1 + `else + `define TX_CAP_HB 0 + `endif + +`else // !ifdef TX_ON + + `define TX_CAP_NCHAN 3'd0 + `define TX_CAP_HB 0 + +`endif // !ifdef TX_ON + +// -------------------------------------------------------------------- + +`ifdef RX_ON + + `ifdef RX_SINGLE + `define RX_EN_0 + `define RX_CAP_NCHAN 3'd1 + `endif + + `ifdef RX_DUAL + `define RX_EN_0 + `define RX_EN_1 + `define RX_CAP_NCHAN 3'd2 + `endif + + `ifdef RX_QUAD + `define RX_EN_0 + `define RX_EN_1 + `define RX_EN_2 + `define RX_EN_3 + `define RX_CAP_NCHAN 3'd4 + `endif + + `ifdef RX_HB_ON + `define RX_CAP_HB 1 + `else + `define RX_CAP_HB 0 + `endif + +`else // !ifdef RX_ON + + `define RX_CAP_NCHAN 3'd0 + `define RX_CAP_HB 0 + +`endif // !ifdef RX_ON diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std_config_2rxhb_2tx.vh b/usrp/fpga/toplevel/usrp_std/usrp_std_config_2rxhb_2tx.vh new file mode 100644 index 00000000..74f1bfd1 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std_config_2rxhb_2tx.vh @@ -0,0 +1,61 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// ------------------------------------------------------------ +// If TX_ON is not defined, there is *no* transmit circuitry built + `define TX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of TX_SINGLE, TX_DUAL and TX_QUAD +// to respectively enable 1, 2 or 4 transmit channels. +// [Please note that only TX_DUAL is currently valid] +//`define TX_SINGLE + `define TX_DUAL +//`define TX_QUAD + +// ------------------------------------------------------------ +// Define TX_HB_ON to enable the transmit halfband filter +// [Not implemented] +//`define TX_HB_ON + +// ------------------------------------------------------------ +// IF RX_ON is not defined, there is *no* transmit circuitry built + `define RX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of RX_SINGLE, RX_DUAL and RX_QUAD +// to respectively define 1, 2 or 4 receive channels. + +//`define RX_SINGLE + `define RX_DUAL +//`define RX_QUAD + +// ------------------------------------------------------------ +// Define RX_HB_ON to enable the receive halfband filter + `define RX_HB_ON + +// ------------------------------------------------------------ +// Define RX_NCO_ON to enable the receive Numerical Controlled Osc + `define RX_NCO_ON + +// ------------------------------------------------------------ +// Define RX_CIC_ON to enable the receive Cascaded Integrator Comb filter + `define RX_CIC_ON diff --git a/usrp/fpga/toplevel/usrp_std/usrp_std_config_4rx_0tx.vh b/usrp/fpga/toplevel/usrp_std/usrp_std_config_4rx_0tx.vh new file mode 100644 index 00000000..0bd18877 --- /dev/null +++ b/usrp/fpga/toplevel/usrp_std/usrp_std_config_4rx_0tx.vh @@ -0,0 +1,61 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2006 Matt Ettus +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// ------------------------------------------------------------ +// If TX_ON is not defined, there is *no* transmit circuitry built +// `define TX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of TX_SINGLE, TX_DUAL and TX_QUAD +// to respectively enable 1, 2 or 4 transmit channels. +// [Please note that only TX_DUAL is currently valid] +//`define TX_SINGLE +//`define TX_DUAL +//`define TX_QUAD + +// ------------------------------------------------------------ +// Define TX_HB_ON to enable the transmit halfband filter +// [Not implemented] +//`define TX_HB_ON + +// ------------------------------------------------------------ +// IF RX_ON is not defined, there is *no* transmit circuitry built + `define RX_ON + +// ------------------------------------------------------------ +// Define 1 and only one of RX_SINGLE, RX_DUAL and RX_QUAD +// to respectively define 1, 2 or 4 receive channels. + +//`define RX_SINGLE +//`define RX_DUAL + `define RX_QUAD + +// ------------------------------------------------------------ +// Define RX_HB_ON to enable the receive halfband filter +//`define RX_HB_ON + +// ------------------------------------------------------------ +// Define RX_NCO_ON to enable the receive Numerical Controlled Osc + `define RX_NCO_ON + +// ------------------------------------------------------------ +// Define RX_CIC_ON to enable the receive Cascaded Integrator Comb filter + `define RX_CIC_ON diff --git a/usrp/host/Makefile.am b/usrp/host/Makefile.am new file mode 100644 index 00000000..05ba5178 --- /dev/null +++ b/usrp/host/Makefile.am @@ -0,0 +1,23 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = misc lib swig apps + diff --git a/usrp/host/apps/Makefile.am b/usrp/host/apps/Makefile.am new file mode 100644 index 00000000..b08e3252 --- /dev/null +++ b/usrp/host/apps/Makefile.am @@ -0,0 +1,53 @@ +# +# Copyright 2003,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +INCLUDES = -I../lib -I$(top_srcdir)/usrp/firmware/include + +bin_PROGRAMS = \ + usrper \ + usrp_cal_dc_offset + +noinst_PROGRAMS = \ + check_order_quickly \ + test_usrp_standard_rx \ + test_usrp_standard_tx + +noinst_HEADERS = \ + time_stuff.h + +noinst_PYTHON = \ + burn-db-eeprom \ + burn-serial-number + + +check_order_quickly_SOURCES = check_order_quickly.cc + +test_usrp_standard_rx_SOURCES = test_usrp_standard_rx.cc time_stuff.c +test_usrp_standard_rx_LDADD = $(top_builddir)/usrp/host/lib/libusrp.la + +test_usrp_standard_tx_SOURCES = test_usrp_standard_tx.cc time_stuff.c +test_usrp_standard_tx_LDADD = $(top_builddir)/usrp/host/lib/libusrp.la + +usrper_SOURCES = usrper.cc +usrper_LDADD = $(top_builddir)/usrp/host/lib/libusrp.la + +usrp_cal_dc_offset_SOURCES = usrp_cal_dc_offset.cc +usrp_cal_dc_offset_LDADD = $(top_builddir)/usrp/host/lib/libusrp.la diff --git a/usrp/host/apps/burn-db-eeprom b/usrp/host/apps/burn-db-eeprom new file mode 100755 index 00000000..e7c92eb9 --- /dev/null +++ b/usrp/host/apps/burn-db-eeprom @@ -0,0 +1,164 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from usrp_prims import * +from optparse import OptionParser +import sys +from usrp_dbid import * + +i2c_addr_map = { 'TX_A' : 0x54, 'RX_A' : 0x55, 'TX_B' : 0x56, 'RX_B' : 0x57 } + +daughterboards = { + # name : ((tx-dbid, tx-oe), (rx-dbid, rx-oe)) + 'basictx' : ((BASIC_TX, 0x0000), None), + 'basicrx' : (None, (BASIC_RX, 0x0000)), + 'dbsrx' : (None, (DBS_RX, 0x0000)), + 'dbsrx2' : (None, (DBS_RX_REV_2_1, 0x0000)), + 'tvrx' : (None, (TV_RX, 0x0000)), + 'tvrx2' : (None, (TV_RX_REV_2, 0x0000)), + 'tvrx3' : (None, (TV_RX_REV_3, 0x0000)), + 'rfx400' : ((FLEX_400_TX, 0x0000), (FLEX_400_RX, 0x0000)), + 'rfx900' : ((FLEX_900_TX, 0x0000), (FLEX_900_RX, 0x0000)), + 'rfx1200' : ((FLEX_1200_TX, 0x0000), (FLEX_1200_RX, 0x0000)), + 'rfx1800' : ((FLEX_1800_TX, 0x0000), (FLEX_1800_RX, 0x0000)), + 'rfx2400' : ((FLEX_2400_TX, 0x0000), (FLEX_2400_RX, 0x0000)), + 'rfx400_tx' : ((FLEX_400_TX, 0x0000), None), + 'rfx900_tx' : ((FLEX_900_TX, 0x0000), None), + 'rfx1200_tx' : ((FLEX_1200_TX, 0x0000), None), + 'rfx1800_tx' : ((FLEX_1800_TX, 0x0000), None), + 'rfx2400_tx' : ((FLEX_2400_TX, 0x0000), None), + 'rfx400_rx' : (None, (FLEX_400_RX, 0x0000)), + 'rfx900_rx' : (None, (FLEX_900_RX, 0x0000)), + 'rfx1200_rx' : (None, (FLEX_1200_RX, 0x0000)), + 'rfx1800_rx' : (None, (FLEX_1800_RX, 0x0000)), + 'rfx2400_rx' : (None, (FLEX_2400_RX, 0x0000)), + 'rfx400_mimo_a' : ((FLEX_400_TX_MIMO_A, 0x0000), (FLEX_400_RX_MIMO_A, 0x0000)), + 'rfx900_mimo_a' : ((FLEX_900_TX_MIMO_A, 0x0000), (FLEX_900_RX_MIMO_A, 0x0000)), + 'rfx1200_mimo_a' : ((FLEX_1200_TX_MIMO_A, 0x0000), (FLEX_1200_RX_MIMO_A, 0x0000)), + 'rfx1800_mimo_a' : ((FLEX_1800_TX_MIMO_A, 0x0000), (FLEX_1800_RX_MIMO_A, 0x0000)), + 'rfx2400_mimo_a' : ((FLEX_2400_TX_MIMO_A, 0x0000), (FLEX_2400_RX_MIMO_A, 0x0000)), + 'rfx400_mimo_b' : ((FLEX_400_TX_MIMO_B, 0x0000), (FLEX_400_RX_MIMO_B, 0x0000)), + 'rfx900_mimo_b' : ((FLEX_900_TX_MIMO_B, 0x0000), (FLEX_900_RX_MIMO_B, 0x0000)), + 'rfx1200_mimo_b' : ((FLEX_1200_TX_MIMO_B, 0x0000), (FLEX_1200_RX_MIMO_B, 0x0000)), + 'rfx1800_mimo_b' : ((FLEX_1800_TX_MIMO_B, 0x0000), (FLEX_1800_RX_MIMO_B, 0x0000)), + 'rfx2400_mimo_b' : ((FLEX_2400_TX_MIMO_B, 0x0000), (FLEX_2400_RX_MIMO_B, 0x0000)), + 'lftx' : ((LF_TX, 0x0000), None), + 'lfrx' : (None, (LF_RX, 0x0000)), + 'experimental_tx' : ((EXPERIMENTAL_TX, 0x0000), None), + 'experimental_rx' : (None, (EXPERIMENTAL_RX, 0x0000)), + } + +def open_cmd_interface(which_board = 0): + if not usrp_load_standard_bits (which_board, 0): + raise RuntimeError, "usrp_load_standard_bits" + dev = usrp_find_device (which_board) + if not dev: + raise RuntimeError, "usrp_find_device" + u = usrp_open_cmd_interface (dev) + if not u: + raise RuntimeError, "usrp_open_cmd_interface" + return u + +def write_dboard_eeprom(u, i2c_addr, dbid, oe): + eeprom = 0x20 * [0] + eeprom[0] = 0xDB # magic value + eeprom[1] = dbid & 0xff + eeprom[2] = (dbid >> 8) & 0xff + eeprom[3] = oe & 0xff + eeprom[4] = (oe >> 8) & 0xff + eeprom[0x1f] = 0xff & (-reduce(lambda x, y: x+y, eeprom)) # checksum + s = ''.join (map (chr, eeprom)) + ok = usrp_eeprom_write (u, i2c_addr, 0, s) + return ok + + +def init_eeprom(u, slot_name, force, dbid, oe): + i2c_addr = i2c_addr_map[slot_name] + e = usrp_eeprom_read (u, i2c_addr, 0, 0x20) + if not e: + print "%s: no d'board, skipped" % (slot_name,) + return True + + if not force and (sum (map (ord, e)) & 0xff) == 0 and ord (e[0]) == 0xDB: + print "%s: already initialized, skipped" % (slot_name,) + return True + + if not write_dboard_eeprom (u, i2c_addr, dbid, oe): + print "%s: failed to write d'board EEPROM" % (slot_name,) + return False + + print "%s: OK" % (slot_name,) + return True + + +def init_daughterboard(u, side, type, force): + ok = True + dbinfo = daughterboards[type] + if dbinfo[0] is not None: # burn tx slot + ok &= init_eeprom(u, 'TX_' + side, force, dbinfo[0][0], dbinfo[0][1]) + if dbinfo[1] is not None: # burn rx slot + ok &= init_eeprom(u, 'RX_' + side, force, dbinfo[1][0], dbinfo[1][1]) + return ok + + +def main(): + dbs = daughterboards.keys() + dbs.sort() + usage = """\ +usage: %prog [options] +You must specify a type with -t or --type, +and at least one side using -A and/or -B.""" + + parser = OptionParser(usage=usage) + parser.add_option ("-t", "--type", type="choice", help="choose type from %r" % (dbs,), + choices=dbs, default=None) + parser.add_option ("-A", "--burn-a", action="store_true", default=False, + help="burn eeprom(s) on side A") + parser.add_option ("-B", "--burn-b", action="store_true", default=False, + help="burn eeprom(s) on side B") + parser.add_option ("-f", "--force", action="store_true", default=False, + help="force init of already initialized eeproms") + (options, args) = parser.parse_args () + + which=[] + if options.burn_a: + which.append('A') + if options.burn_b: + which.append('B') + + if len(args) != 0 or len(which) == 0 or options.type is None: + parser.print_help() + sys.exit (1) + + u = open_cmd_interface (0) + ok = True + for w in which: + ok &= init_daughterboard (u, w, options.type, options.force) + + if ok: + sys.exit (0) + else: + sys.exit (1) + +if __name__ == "__main__": + main () + diff --git a/usrp/host/apps/burn-serial-number b/usrp/host/apps/burn-serial-number new file mode 100755 index 00000000..1bf944e9 --- /dev/null +++ b/usrp/host/apps/burn-serial-number @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from usrp_prims import * +from optparse import OptionParser +import sys +import time + + +def open_cmd_interface(which_board = 0): + if not usrp_load_standard_bits (which_board, 0): + raise RuntimeError, "usrp_load_standard_bits" + dev = usrp_find_device (which_board) + if not dev: + raise RuntimeError, "usrp_find_device" + u = usrp_open_cmd_interface (dev) + if not u: + raise RuntimeError, "usrp_open_cmd_interface" + return u + + +def write_serial_number_eeprom(u, serial_number): + if not str(serial_number): + raise TypeError + + i2c_addr = 0x50 # usrp boot rom + serial_number_offset = 248 # offset to serial number + serial_number_len = 8 # length of serial number + + lsn = len(serial_number) + if lsn > serial_number_len: + serial_number = serial_number[0:serial_number_len] + if lsn < serial_number_len: + serial_number = serial_number + (serial_number_len - lsn) * ' ' + + ok = usrp_eeprom_write (u, i2c_addr, serial_number_offset, serial_number) + return ok + + +def main(): + + default_serial_number = hex(int(time.time()))[2:] + parser = OptionParser() + parser.add_option ("-s", "--serial-number", default=default_serial_number, + help="set serial number [default=%default]") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + u = open_cmd_interface (0) + ok = write_serial_number_eeprom(u, options.serial_number) + + if ok: + sys.exit(0) + else: + sys.exit(1) + +if __name__ == "__main__": + main () diff --git a/usrp/host/apps/check_order b/usrp/host/apps/check_order new file mode 100755 index 00000000..56e19271 --- /dev/null +++ b/usrp/host/apps/check_order @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- Python -*- + +import sys +import fileinput + +skip_count = 4096 +lineno = 0 +last_error = 0 + +for line in fileinput.input (): + lineno += 1 + if lineno < skip_count: + continue + (offset, dec_val, hex_val) = line.split () + if lineno == skip_count: + expected_val = int (dec_val) + int_dec_val = int (dec_val) + int_hex_val = int (hex_val, 16) + if int_dec_val != expected_val: + print "line %6d, delta %4d, expected %6d, got %6d" % (lineno, + lineno - last_error, + expected_val, + int_dec_val) + last_error = lineno + elif ((int_hex_val >> 12) & 0xf) != (int_hex_val & 0xf): + print "line %6d, delta %4d, invalid high bits %04x" % (lineno, + lineno - last_error, + int_hex_val) + last_error = lineno + + # expected_val = (expected_val + 1) & 0xffff + expected_val = (expected_val + 1) & 0x0fff + + + + + + diff --git a/usrp/host/apps/check_order_quickly.cc b/usrp/host/apps/check_order_quickly.cc new file mode 100644 index 00000000..d6ebd2f0 --- /dev/null +++ b/usrp/host/apps/check_order_quickly.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +static bool +check (int v, int counter, int offset) +{ + if ((v & 0x0fff) != counter){ + fprintf (stdout, "%08x: expected 0x%04x, got 0x%04x\n", offset, counter, v & 0x0fff); + return false; + } + + if (((v >> 12) & 0xf) != (v & 0xf)){ + fprintf (stdout, "%08x: bad high bits 0x%04x\n", offset, v); + return false; + } + + return true; +} + +int +main (int argc, char **argv) +{ + static const int BUFSIZE = 64 * 1024; + unsigned short buf[BUFSIZE]; + + int n; + int i; + int counter = 0; + int offset = 0; + bool ok = true; + + while ((n = fread (buf, sizeof (short), BUFSIZE, stdin)) != 0){ + for (i = 0; i < n; i++){ + ok &= check (buf[i], counter, offset); + counter = (counter + 1) & 0x0fff; + offset++; + } + } + + return ok ? 0 : 1; +} diff --git a/usrp/host/apps/dump_12bit_shorts b/usrp/host/apps/dump_12bit_shorts new file mode 100755 index 00000000..a896f2dd --- /dev/null +++ b/usrp/host/apps/dump_12bit_shorts @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- Python -*- + +import sys, errno + +counter = 0 + +try: + while 1: + x = sys.stdin.read (2) + if not x: + break + + v = (ord(x[1]) << 8) | ord(x[0]) + sys.stdout.write ("0x%08x %6d 0x%04x\n" % (counter, v & 0x0fff, v)) + counter += 1 +except IOError, e: + if e.errno == errno.EPIPE: + sys.exit (0) + + + + diff --git a/usrp/host/apps/dump_shorts b/usrp/host/apps/dump_shorts new file mode 100755 index 00000000..6104ea06 --- /dev/null +++ b/usrp/host/apps/dump_shorts @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- Python -*- + +import sys, errno + +counter = 0 + +try: + while 1: + x = sys.stdin.read (2) + if not x: + break + + v = (ord(x[1]) << 8) | ord(x[0]) + sys.stdout.write ("0x%08x %6d 0x%04x\n" % (counter, v, v)) + counter += 1 +except IOError, e: + if e.errno == errno.EPIPE: + sys.exit (0) + + + + diff --git a/usrp/host/apps/print-db b/usrp/host/apps/print-db new file mode 100755 index 00000000..b741969d --- /dev/null +++ b/usrp/host/apps/print-db @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import usrp +from optparse import OptionParser +import usrp_dbid + +u_source = usrp.source_c() +u_sink = usrp.sink_c() +subdev_Ar = usrp.selected_subdev(u_source, (0,0)) +subdev_Br = usrp.selected_subdev(u_source, (1,0)) +subdev_At = usrp.selected_subdev(u_sink, (0,0)) +subdev_Bt = usrp.selected_subdev(u_sink, (1,0)) + +print "RX d'board %s" % (subdev_Ar.side_and_name(),) +print "RX d'board %s" % (subdev_Br.side_and_name(),) +print "TX d'board %s" % (subdev_At.side_and_name(),) +print "TX d'board %s" % (subdev_Bt.side_and_name(),) + diff --git a/usrp/host/apps/run b/usrp/host/apps/run new file mode 100755 index 00000000..5b13336c --- /dev/null +++ b/usrp/host/apps/run @@ -0,0 +1,6 @@ +#!/bin/sh + +./test_usrp_standard_rx -D 8 -o rx.bin +./dump_12bit_shorts rx.ascii +./check_order rx.ascii +#./dump_12bit_shorts rx.ascii + diff --git a/usrp/host/apps/test_usrp_standard_rx.cc b/usrp/host/apps/test_usrp_standard_rx.cc new file mode 100644 index 00000000..d19b6a6b --- /dev/null +++ b/usrp/host/apps/test_usrp_standard_rx.cc @@ -0,0 +1,276 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include /* needed for usb functions */ +#include +#include +#include +#include "time_stuff.h" +#include "usrp_standard.h" +#include "usrp_bytesex.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" + +#ifdef HAVE_SCHED_H +#include +#endif + +char *prog_name; + +static bool test_input (usrp_standard_rx *urx, int max_bytes, FILE *fp); + +static void +set_progname (char *path) +{ + char *p = strrchr (path, '/'); + if (p != 0) + prog_name = p+1; + else + prog_name = path; +} + +static void +usage () +{ + fprintf (stderr, "usage: %s [-f] [-v] [-l] [-c] [-D ] [-F freq] [-o output_file]\n", prog_name); + fprintf (stderr, " [-f] loop forever\n"); + fprintf (stderr, " [-M] how many Megabytes to transfer (default 128)\n"); + fprintf (stderr, " [-v] verbose\n"); + fprintf (stderr, " [-l] digital loopback in FPGA\n"); + fprintf (stderr, " [-c] counting in FPGA\n"); + fprintf (stderr, " [-8] 8-bit samples across USB\n"); + fprintf (stderr, " [-B ] set fast usb block_size\n"); + fprintf (stderr, " [-N ] set fast usb nblocks\n"); + fprintf (stderr, " [-R] set real time scheduling: SCHED_FIFO; pri = midpoint\n"); + + exit (1); +} + +static void +die (const char *msg) +{ + fprintf (stderr, "die: %s: %s\n", prog_name, msg); + exit (1); +} + +int +main (int argc, char **argv) +{ + bool verbose_p = false; + bool loopback_p = false; + bool counting_p = false; + bool width_8_p = false; + int max_bytes = 128 * (1L << 20); + int ch; + char *output_filename = 0; + int which_board = 0; + int decim = 8; // 32 MB/sec + double center_freq = 0; + int fusb_block_size = 0; + int fusb_nblocks = 0; + bool realtime_p = false; + + + set_progname (argv[0]); + + while ((ch = getopt (argc, argv, "fvlco:D:F:M:8B:N:R")) != EOF){ + switch (ch){ + case 'f': + max_bytes = 0; + break; + + case 'v': + verbose_p = true; + break; + + case 'l': + loopback_p = true; + break; + + case 'c': + counting_p = true; + break; + + case '8': + width_8_p = true; + break; + + case 'o': + output_filename = optarg; + break; + + case 'D': + decim = strtol (optarg, 0, 0); + break; + + case 'F': + center_freq = strtod (optarg, 0); + break; + + case 'M': + max_bytes = strtol (optarg, 0, 0) * (1L << 20); + if (max_bytes < 0) max_bytes = 0; + break; + + case 'B': + fusb_block_size = strtol (optarg, 0, 0); + break; + + case 'N': + fusb_nblocks = strtol (optarg, 0, 0); + break; + + case 'R': + realtime_p = true; + break; + + default: + usage (); + } + } + +#ifdef HAVE_SCHED_SETSCHEDULER + if (realtime_p){ + int policy = SCHED_FIFO; + int pri = (sched_get_priority_max (policy) - sched_get_priority_min (policy)) / 2; + int pid = 0; // this process + + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = pri; + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ + perror ("sched_setscheduler: failed to set real time priority"); + } + else + printf("SCHED_FIFO enabled with priority = %d\n", pri); + } +#endif + + FILE *fp = 0; + + if (output_filename){ + fp = fopen (output_filename, "wb"); + if (fp == 0) + perror (output_filename); + } + + int mode = 0; + if (loopback_p) + mode |= usrp_standard_rx::FPGA_MODE_LOOPBACK; + if (counting_p) + mode |= usrp_standard_rx::FPGA_MODE_COUNTING; + + + usrp_standard_rx *urx = + usrp_standard_rx::make (which_board, decim, 1, -1, mode, + fusb_block_size, fusb_nblocks); + + if (urx == 0) + die ("usrp_standard_rx::make"); + + if (!urx->set_rx_freq (0, center_freq)) + die ("urx->set_rx_freq"); + + if (width_8_p){ + int width = 8; + int shift = 8; + bool want_q = true; + if (!urx->set_format(usrp_standard_rx::make_format(width, shift, want_q))) + die("urx->set_format"); + } + + urx->start(); // start data xfers + + test_input (urx, max_bytes, fp); + + if (fp) + fclose (fp); + + delete urx; + + return 0; +} + + +static bool +test_input (usrp_standard_rx *urx, int max_bytes, FILE *fp) +{ + int fd = -1; + static const int BUFSIZE = urx->block_size(); + static const int N = BUFSIZE/sizeof (short); + short buf[N]; + int nbytes = 0; + + double start_wall_time = get_elapsed_time (); + double start_cpu_time = get_cpu_usage (); + + if (fp) + fd = fileno (fp); + + bool overrun; + int noverruns = 0; + + for (nbytes = 0; max_bytes == 0 || nbytes < max_bytes; nbytes += BUFSIZE){ + + unsigned int ret = urx->read (buf, sizeof (buf), &overrun); + if (ret != sizeof (buf)){ + fprintf (stderr, "test_input: error, ret = %d\n", ret); + } + + if (overrun){ + printf ("rx_overrun\n"); + noverruns++; + } + + if (fd != -1){ + + for (unsigned int i = 0; i < sizeof (buf) / sizeof (short); i++) + buf[i] = usrp_to_host_short (buf[i]); + + if (write (fd, buf, sizeof (buf)) == -1){ + perror ("write"); + fd = -1; + } + } + } + + double stop_wall_time = get_elapsed_time (); + double stop_cpu_time = get_cpu_usage (); + + double delta_wall = stop_wall_time - start_wall_time; + double delta_cpu = stop_cpu_time - start_cpu_time; + + printf ("xfered %.3g bytes in %.3g seconds. %.4g bytes/sec. cpu time = %.4g\n", + (double) max_bytes, delta_wall, max_bytes / delta_wall, delta_cpu); + printf ("noverruns = %d\n", noverruns); + + return true; +} diff --git a/usrp/host/apps/test_usrp_standard_tx.cc b/usrp/host/apps/test_usrp_standard_tx.cc new file mode 100644 index 00000000..8aebaeb8 --- /dev/null +++ b/usrp/host/apps/test_usrp_standard_tx.cc @@ -0,0 +1,319 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include /* needed for usb functions */ +#include +#include +#include +#include "time_stuff.h" +#include "usrp_standard.h" +#include "usrp_bytesex.h" + +#ifdef HAVE_SCHED_H +#include +#endif + +char *prog_name; + +static bool test_output (usrp_standard_tx *utx, int max_bytes, double ampl, + bool dc_p, bool counting_p); + +static void +set_progname (char *path) +{ + char *p = strrchr (path, '/'); + if (p != 0) + prog_name = p+1; + else + prog_name = path; +} + +static void +usage () +{ + fprintf (stderr, + "usage: %s [-f] [-v] [-d] [-c] [-a ][-I ] [-F freq] [-D]\n", prog_name); + fprintf (stderr, " [-f] loop forever\n"); + fprintf (stderr, " [-M] how many Megabytes to transfer (default 128)\n"); + fprintf (stderr, " [-v] verbose\n"); + fprintf (stderr, " [-d] dump registers\n"); + // fprintf (stderr, " [-l] digital loopback in FPGA\n"); + fprintf (stderr, " [-c] Tx counting sequence\n"); + fprintf (stderr, " [-D] DC output\n"); + + fprintf (stderr, " [-B ] set fast usb block_size\n"); + fprintf (stderr, " [-N ] set fast usb nblocks\n"); + fprintf (stderr, " [-R] set real time scheduling: SCHED_FIFO; pri = midpoint\n"); + + exit (1); +} + +static void +die (const char *msg) +{ + fprintf (stderr, "die: %s: %s\n", prog_name, msg); + exit (1); +} + +static void +dump_codec_regs (usrp_basic *u, int which_codec, FILE *fp) +{ + for (int i = 0; i < 64; i++){ + unsigned char v; + u->_read_9862 (which_codec, i, &v); + fprintf (fp, "%2d: 0x%02x\n", i, v); + } + fflush (fp); +} + +static void +do_dump_codec_regs (usrp_basic *u) +{ + char name[100]; + strcpy (name, "regsXXXXXX"); + int fd = mkstemp (name); + if (fd == -1){ + perror (name); + } + else { + FILE *fp = fdopen (fd, "w"); + dump_codec_regs (u, 0, fp); + fclose (fp); + } +} + +int +main (int argc, char **argv) +{ + bool verbose_p = false; + bool dump_regs_p = false; + bool dc_p = false; + // bool loopback_p = false; + bool counting_p = false; + int max_bytes = 128 * (1L << 20); + int ch; + int which_board = 0; + int interp = 16; // 32.0 MB/sec + double center_freq = 0; + double ampl = 10000; + int fusb_block_size = 0; + int fusb_nblocks = 0; + bool realtime_p = false; + + + set_progname (argv[0]); + + while ((ch = getopt (argc, argv, "vfdcI:F:a:DM:B:N:R")) != EOF){ + switch (ch){ + case 'f': + max_bytes = 0; + break; + + case 'v': + verbose_p = true; + break; + + case 'd': + dump_regs_p = true; + break; + + case 'D': + dc_p = true; + break; + +#if 0 + case 'l': + loopback_p = true; + break; +#endif + + case 'c': + counting_p = true; + break; + + case 'I': + interp = strtol (optarg, 0, 0); + break; + + case 'F': + center_freq = strtod (optarg, 0); + break; + + case 'a': + ampl = strtod (optarg, 0); + break; + + case 'M': + max_bytes = strtol (optarg, 0, 0) * (1L << 20); + if (max_bytes < 0) max_bytes = 0; + break; + + case 'B': + fusb_block_size = strtol (optarg, 0, 0); + break; + + case 'N': + fusb_nblocks = strtol (optarg, 0, 0); + break; + + case 'R': + realtime_p = true; + break; + + default: + usage (); + } + } + +#ifdef HAVE_SCHED_SETSCHEDULER + if (realtime_p){ + int policy = SCHED_FIFO; + int pri = (sched_get_priority_max (policy) - sched_get_priority_min (policy)) / 2; + int pid = 0; // this process + + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = pri; + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ + perror ("sched_setscheduler: failed to set real time priority"); + } + else + printf("SCHED_FIFO enabled with priority = %d\n", pri); + } +#endif + + usrp_standard_tx *utx; + + utx = usrp_standard_tx::make (which_board, + interp, + 1, // nchan + -1, // mux + fusb_block_size, + fusb_nblocks); + + if (utx == 0) + die ("usrp_standard_tx::make"); + + if (!utx->set_tx_freq (0, center_freq)) + die ("utx->set_tx_freq"); + + if (dump_regs_p) + do_dump_codec_regs (utx); + + + fflush (stdout); + fflush (stderr); + + utx->start(); // start data xfers + + test_output (utx, max_bytes, ampl, dc_p, counting_p); + + delete utx; + + return 0; +} + + +static bool +test_output (usrp_standard_tx *utx, int max_bytes, double ampl, + bool dc_p, bool counting_p) +{ + static const int BUFSIZE = utx->block_size(); + static const int N = BUFSIZE/sizeof (short); + + short buf[N]; + int nbytes = 0; + int counter = 0; + + static const int PERIOD = 65; // any value is valid + static const int PATLEN = 2 * PERIOD; + short pattern[PATLEN]; + + for (int i = 0; i < PERIOD; i++){ + if (dc_p){ + pattern[2*i+0] = host_to_usrp_short ((short) ampl); + pattern[2*i+1] = host_to_usrp_short ((short) 0); + } + else { + pattern[2*i+0] = host_to_usrp_short ((short) (ampl * cos (2*M_PI * i / PERIOD))); + pattern[2*i+1] = host_to_usrp_short ((short) (ampl * sin (2*M_PI * i / PERIOD))); + } + } + + double start_wall_time = get_elapsed_time (); + double start_cpu_time = get_cpu_usage (); + + bool underrun; + int nunderruns = 0; + int pi = 0; + + for (nbytes = 0; max_bytes == 0 || nbytes < max_bytes; nbytes += BUFSIZE){ + + if (counting_p){ + for (int i = 0; i < N; i++) + buf[i] = host_to_usrp_short (counter++ & 0xffff); + } + else { + for (int i = 0; i < N; i++){ + buf[i] = pattern[pi]; + pi++; + if (pi >= PATLEN) + pi = 0; + } + } + + int ret = utx->write (buf, sizeof (buf), &underrun); + if ((unsigned) ret != sizeof (buf)){ + fprintf (stderr, "test_output: error, ret = %d\n", ret); + } + + if (underrun){ + nunderruns++; + printf ("tx_underrun\n"); + //printf ("tx_underrun %9d %6d\n", nbytes, nbytes/BUFSIZE); + } + } + + utx->wait_for_completion (); + + double stop_wall_time = get_elapsed_time (); + double stop_cpu_time = get_cpu_usage (); + + double delta_wall = stop_wall_time - start_wall_time; + double delta_cpu = stop_cpu_time - start_cpu_time; + + printf ("xfered %.3g bytes in %.3g seconds. %.4g bytes/sec. cpu time = %.3g\n", + (double) max_bytes, delta_wall, max_bytes / delta_wall, delta_cpu); + + printf ("%d underruns\n", nunderruns); + + return true; +} diff --git a/usrp/host/apps/time_stuff.c b/usrp/host/apps/time_stuff.c new file mode 100644 index 00000000..aa62e9ad --- /dev/null +++ b/usrp/host/apps/time_stuff.c @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "time_stuff.h" + +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include + +static double +timeval_to_secs (struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + +double +get_cpu_usage (void) +{ +#ifdef HAVE_GETRUSAGE + struct rusage ru; + + if (getrusage (RUSAGE_SELF, &ru) != 0) + return 0; + + return timeval_to_secs (&ru.ru_utime) + timeval_to_secs (&ru.ru_stime); +#else + return 0; /* FIXME */ +#endif +} + +/* + * return elapsed time (wall time) in seconds + */ +double +get_elapsed_time (void) +{ + struct timeval tv; + if (gettimeofday (&tv, 0) != 0) + return 0; + + return timeval_to_secs (&tv); +} + diff --git a/usrp/host/apps/time_stuff.h b/usrp/host/apps/time_stuff.h new file mode 100644 index 00000000..c995ef64 --- /dev/null +++ b/usrp/host/apps/time_stuff.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _TIME_STUFF_H_ +#define _TIME_STUFF_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * return USER + SYS cpu time in seconds + */ +double get_cpu_usage (void); + +/* + * return elapsed time in seconds + */ +double get_elapsed_time (void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _TIME_STUFF_H_ */ diff --git a/usrp/host/apps/usrp_cal_dc_offset.cc b/usrp/host/apps/usrp_cal_dc_offset.cc new file mode 100644 index 00000000..2308bdda --- /dev/null +++ b/usrp/host/apps/usrp_cal_dc_offset.cc @@ -0,0 +1,242 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include /* needed for usb functions */ +#include +#include +#include +#include +#include "usrp_local_sighandler.h" +#include "usrp_standard.h" +#include "usrp_bytesex.h" + +char *prog_name; + + + + +static void +run_cal(usrp_standard_rx *u, int which_side, int decim, bool verbose_p) +{ + static const int BUFSIZE = u->block_size(); + static const int N = BUFSIZE/sizeof (short); + short buf[N]; + bool cal_done = false; + bool overrun; + int noverruns = 0; + + static const double K = 1e-4; + long integrator[2]; + int offset[2]; + + integrator[0] = 0; + integrator[1] = 0; + offset[0] = 0; + offset[1] = 0; + + u->start(); // start data xfers + + while(!cal_done){ + int ret = u->read (buf, sizeof (buf), &overrun); + if (ret != (int) sizeof (buf)){ + fprintf (stderr, "usrp_cal_dc_offset: error, ret = %d\n", ret); + continue; + } + if (overrun){ + fprintf (stderr, "O"); + noverruns++; + } + else { + // fputc('.', stderr); + } + + static const int MAX = (1L << 30); // 1G + + for (int i = 0; i < N/2; i++){ + for (int n = 0; n < 2; n++){ + integrator[n] = integrator[n] + buf[2*i + n]; + if (integrator[n] > MAX) + integrator[n] = MAX; + else if (integrator[n] < -MAX) + integrator[n] = -MAX; + } + } + +#if 1 + for (int n = 0; n < 2; n++){ + offset[n] = (int) rint(integrator[n] * K); + if (offset[n] > 32767) + offset[n] = 32767; + else if (offset[n] < -32767) + offset[n] = -32767; + u->set_adc_offset(which_side * 2 + n, offset[n]); + } +#else + offset[0] = (int) rint(integrator[0] * K); + if (offset[0] > 32767) + offset[0] = 32767; + else if (offset[0] < -32767) + offset[0] = -32767; + u->set_adc_offset(which_side * 2 + 0, offset[0]); + u->set_adc_offset(which_side * 2 + 1, offset[0]); +#endif + + + printf ("%9ld : %6d\t\t%9ld : %6d\n", + integrator[0], offset[0], integrator[1], offset[1]); + } + + u->stop(); +} + + +static void +set_progname (char *path) +{ + char *p = strrchr (path, '/'); + if (p != 0) + prog_name = p+1; + else + prog_name = path; +} + +static void +usage () +{ + fprintf(stderr, "usage: %s [-v] [-w which_side] [-D decim] [-c ddc_freq] [-g gain]\n", prog_name); + fprintf(stderr, " [-S fusb_block_size] [-N fusb_nblocks]\n"); + exit (1); +} + +static void +die (const char *msg) +{ + fprintf (stderr, "die: %s: %s\n", prog_name, msg); + exit (1); +} + +int +main (int argc, char **argv) +{ + int ch; + int decim = 128; // 500 kS/sec + bool verbose_p = false; + int which_board = 0; + int which_side = 0; + double ddc_freq = 0; + int fusb_block_size = 1024; + int fusb_nblocks = 4; + double pga_gain = 0.0; + + set_progname(argv[0]); + + while ((ch = getopt (argc, argv, "vw:D:c:S:N:g:")) != EOF){ + switch (ch){ + + case 'w': + which_side = strtol (optarg, 0, 0); + if (which_side < 0 || which_side > 1) + usage(); + break; + + case 'D': + decim = strtol (optarg, 0, 0); + if (decim < 1) + usage(); + break; + + case 'c': + ddc_freq = strtod (optarg, 0); + break; + + case 'v': + verbose_p = true; + break; + + case 'S': + fusb_block_size = strtol(optarg, 0, 0); + break; + + case 'N': + fusb_nblocks = strtol(optarg, 0, 0); + break; + + case 'g': + pga_gain = strtod (optarg, 0); + break; + + default: + usage (); + } + } + + int nchannels = 1; + int mode = usrp_standard_rx::FPGA_MODE_NORMAL; + int mux; + + if (which_side == 0) + mux = 0x00000010; + else + mux = 0x00000032; + +#ifdef SIGINT + usrp_local_sighandler sigint (SIGINT, usrp_local_sighandler::throw_signal); +#endif +#ifdef SIGQUIT + usrp_local_sighandler sigquit (SIGQUIT, usrp_local_sighandler::throw_signal); +#endif + + usrp_standard_rx *urx = + usrp_standard_rx::make(which_board, decim, + nchannels, mux, mode, + fusb_block_size, fusb_nblocks); + if (urx == 0) + die("usrp_standard_rx::make"); + + try { + + if (!urx->set_rx_freq(0, ddc_freq)) + die("urx->set_rx_freq"); + + urx->set_pga(2 * which_side + 0, pga_gain); + urx->set_pga(2 * which_side + 1, pga_gain); + + run_cal(urx, which_side, decim, verbose_p); + } + catch (usrp_signal &sig){ + fprintf (stderr, "usrp_cal_dc_offset: caught %s\n", sig.name().c_str()); + } + catch(...){ + fprintf (stderr, "usrp_cal_dc_offset: caught something\n"); + } + + delete urx; +} + diff --git a/usrp/host/apps/usrper.cc b/usrp/host/apps/usrper.cc new file mode 100644 index 00000000..51c5ee6b --- /dev/null +++ b/usrp/host/apps/usrper.cc @@ -0,0 +1,352 @@ +/* -*- c++ -*- */ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2004 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include /* needed for usb functions */ +#include +#include +#include + +#include "usrp_prims.h" +#include "usrp_spi_defs.h" + +char *prog_name; + + +static void +set_progname (char *path) +{ + char *p = strrchr (path, '/'); + if (p != 0) + prog_name = p+1; + else + prog_name = path; +} + +static void +usage () +{ + fprintf (stderr, "usage: \n"); + fprintf (stderr, " %s [-v] [-w ] [-x] ...\n", prog_name); + fprintf (stderr, " %s load_standard_bits\n", prog_name); + fprintf (stderr, " %s load_firmware \n", prog_name); + fprintf (stderr, " %s load_fpga \n", prog_name); + fprintf (stderr, " %s write_fpga_reg \n", prog_name); + fprintf (stderr, " %s set_fpga_reset {on|off}\n", prog_name); + fprintf (stderr, " %s set_fpga_tx_enable {on|off}\n", prog_name); + fprintf (stderr, " %s set_fpga_rx_enable {on|off}\n", prog_name); + fprintf (stderr, " ----- diagnostic routines -----\n"); + fprintf (stderr, " %s led0 {on|off}\n", prog_name); + fprintf (stderr, " %s led1 {on|off}\n", prog_name); + fprintf (stderr, " %s set_hash0 \n", prog_name); + fprintf (stderr, " %s get_hash0\n", prog_name); + fprintf (stderr, " %s i2c_read i2c_addr len\n", prog_name); + fprintf (stderr, " %s i2c_write i2c_addr \n", prog_name); + fprintf (stderr, " %s 9862a_write regno value\n", prog_name); + fprintf (stderr, " %s 9862b_write regno value\n", prog_name); + fprintf (stderr, " %s 9862a_read regno\n", prog_name); + fprintf (stderr, " %s 9862b_read regno\n", prog_name); + exit (1); +} + +static void +die (const char *msg) +{ + fprintf (stderr, "%s (die): %s\n", prog_name, msg); + exit (1); +} + +static int +hexval (char ch) +{ + if ('0' <= ch && ch <= '9') + return ch - '0'; + + if ('a' <= ch && ch <= 'f') + return ch - 'a' + 10; + + if ('A' <= ch && ch <= 'F') + return ch - 'A' + 10; + + return -1; +} + +static unsigned char * +hex_string_to_binary (const char *string, int *lenptr) +{ + int sl = strlen (string); + if (sl & 0x01){ + fprintf (stderr, "%s: odd number of chars in \n", prog_name); + return 0; + } + + int len = sl / 2; + *lenptr = len; + unsigned char *buf = new unsigned char [len]; + + for (int i = 0; i < len; i++){ + int hi = hexval (string[2 * i]); + int lo = hexval (string[2 * i + 1]); + if (hi < 0 || lo < 0){ + fprintf (stderr, "%s: invalid char in \n", prog_name); + delete [] buf; + return 0; + } + buf[i] = (hi << 4) | lo; + } + return buf; +} + +static void +print_hex (FILE *fp, unsigned char *buf, int len) +{ + for (int i = 0; i < len; i++){ + fprintf (fp, "%02x", buf[i]); + } + fprintf (fp, "\n"); +} + +static void +chk_result (bool ok) +{ + if (!ok){ + fprintf (stderr, "%s: failed\n", prog_name); + exit (1); + } +} + +static bool +get_on_off (const char *s) +{ + if (strcmp (s, "on") == 0) + return true; + + if (strcmp (s, "off") == 0) + return false; + + usage (); // no return + return false; +} + + +int +main (int argc, char **argv) +{ + int ch; + bool verbose = false; + int which_board = 0; + bool fx2_ok_p = false; + + set_progname (argv[0]); + + while ((ch = getopt (argc, argv, "vw:x")) != EOF){ + switch (ch){ + + case 'v': + verbose = true; + break; + + case 'w': + which_board = strtol (optarg, 0, 0); + break; + + case 'x': + fx2_ok_p = true; + break; + + default: + usage (); + } + } + + int nopts = argc - optind; + + if (nopts < 1) + usage (); + + const char *cmd = argv[optind++]; + nopts--; + + usrp_one_time_init (); + + + struct usb_device *udev = usrp_find_device (which_board, fx2_ok_p); + if (udev == 0){ + fprintf (stderr, "%s: failed to find usrp[%d]\n", prog_name, which_board); + exit (1); + } + + if (usrp_unconfigured_usrp_p (udev)){ + fprintf (stderr, "%s: found unconfigured usrp; needs firmware.\n", prog_name); + } + + if (usrp_fx2_p (udev)){ + fprintf (stderr, "%s: found unconfigured FX2; needs firmware.\n", prog_name); + } + + struct usb_dev_handle *udh = usrp_open_cmd_interface (udev); + if (udh == 0){ + fprintf (stderr, "%s: failed to open_cmd_interface\n", prog_name); + exit (1); + } + +#define CHKARGS(n) if (nopts != n) usage (); else + + if (strcmp (cmd, "led0") == 0){ + CHKARGS (1); + bool on = get_on_off (argv[optind]); + chk_result (usrp_set_led (udh, 0, on)); + } + else if (strcmp (cmd, "led1") == 0){ + CHKARGS (1); + bool on = get_on_off (argv[optind]); + chk_result (usrp_set_led (udh, 1, on)); + } + else if (strcmp (cmd, "led2") == 0){ + CHKARGS (1); + bool on = get_on_off (argv[optind]); + chk_result (usrp_set_led (udh, 2, on)); + } + else if (strcmp (cmd, "set_hash0") == 0){ + CHKARGS (1); + char *p = argv[optind]; + unsigned char buf[16]; + + memset (buf, ' ', 16); + for (int i = 0; i < 16 && *p; i++) + buf[i] = *p++; + + chk_result (usrp_set_hash (udh, 0, buf)); + } + else if (strcmp (cmd, "get_hash0") == 0){ + CHKARGS (0); + unsigned char buf[17]; + memset (buf, 0, 17); + bool r = usrp_get_hash (udh, 0, buf); + if (r) + printf ("hash: %s\n", buf); + chk_result (r); + } + else if (strcmp (cmd, "load_fpga") == 0){ + CHKARGS (1); + char *filename = argv[optind]; + chk_result (usrp_load_fpga (udh, filename, true)); + } + else if (strcmp (cmd, "load_firmware") == 0){ + CHKARGS (1); + char *filename = argv[optind]; + chk_result (usrp_load_firmware (udh, filename, true)); + } + else if (strcmp (cmd, "write_fpga_reg") == 0){ + CHKARGS (2); + chk_result (usrp_write_fpga_reg (udh, strtoul (argv[optind], 0, 0), + strtoul(argv[optind+1], 0, 0))); + } + else if (strcmp (cmd, "set_fpga_reset") == 0){ + CHKARGS (1); + chk_result (usrp_set_fpga_reset (udh, get_on_off (argv[optind]))); + } + else if (strcmp (cmd, "set_fpga_tx_enable") == 0){ + CHKARGS (1); + chk_result (usrp_set_fpga_tx_enable (udh, get_on_off (argv[optind]))); + } + else if (strcmp (cmd, "set_fpga_rx_enable") == 0){ + CHKARGS (1); + chk_result (usrp_set_fpga_rx_enable (udh, get_on_off (argv[optind]))); + } + else if (strcmp (cmd, "load_standard_bits") == 0){ + CHKARGS (0); + usrp_close_interface (udh); + udh = 0; + chk_result (usrp_load_standard_bits (which_board, true)); + } + else if (strcmp (cmd, "i2c_read") == 0){ + CHKARGS (2); + int i2c_addr = strtol (argv[optind], 0, 0); + int len = strtol (argv[optind + 1], 0, 0); + if (len < 0) + chk_result (0); + + unsigned char *buf = new unsigned char [len]; + bool result = usrp_i2c_read (udh, i2c_addr, buf, len); + if (!result){ + chk_result (0); + } + print_hex (stdout, buf, len); + } + else if (strcmp (cmd, "i2c_write") == 0){ + CHKARGS (2); + int i2c_addr = strtol (argv[optind], 0, 0); + int len; + char *hex_string = argv[optind + 1]; + unsigned char *buf = hex_string_to_binary (hex_string, &len); + if (buf == 0) + chk_result (0); + + bool result = usrp_i2c_write (udh, i2c_addr, buf, len); + chk_result (result); + } + else if (strcmp (cmd, "9862a_write") == 0){ + CHKARGS (2); + int regno = strtol (argv[optind], 0, 0); + int value = strtol (argv[optind+1], 0, 0); + chk_result (usrp_9862_write (udh, 0, regno, value)); + } + else if (strcmp (cmd, "9862b_write") == 0){ + CHKARGS (2); + int regno = strtol (argv[optind], 0, 0); + int value = strtol (argv[optind+1], 0, 0); + chk_result (usrp_9862_write (udh, 1, regno, value)); + } + else if (strcmp (cmd, "9862a_read") == 0){ + CHKARGS (1); + int regno = strtol (argv[optind], 0, 0); + unsigned char value; + bool result = usrp_9862_read (udh, 0, regno, &value); + if (!result){ + chk_result (0); + } + fprintf (stdout, "reg[%d] = 0x%02x\n", regno, value); + } + else if (strcmp (cmd, "9862b_read") == 0){ + CHKARGS (1); + int regno = strtol (argv[optind], 0, 0); + unsigned char value; + bool result = usrp_9862_read (udh, 1, regno, &value); + if (!result){ + chk_result (0); + } + fprintf (stdout, "reg[%d] = 0x%02x\n", regno, value); + } + else { + usage (); + } + + if (udh){ + usrp_close_interface (udh); + udh = 0; + } + + return 0; +} diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am new file mode 100644 index 00000000..e2086bc2 --- /dev/null +++ b/usrp/host/lib/Makefile.am @@ -0,0 +1,137 @@ +# +# USRP - Universal Software Radio Peripheral +# +# Copyright (C) 2003,2004,2006 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +INCLUDES = -I$(top_srcdir)/usrp/firmware/include + +lib_LTLIBRARIES = libusrp.la + + +EXTRA_DIST = \ + std_paths.h.in \ + usrp_dbid.dat + + +BUILT_SOURCES = \ + usrp_dbid.h \ + usrp_dbid.cc \ + usrp_dbid.py + + +# ---------------------------------------------------------------- +# FUSB_TECH is set at configure time by way of +# usrp/config/usrp_fusb_tech.m4. +# It indicates which fast usb strategy we should be building. +# We currently implement "generic", "darwin", "win32" and "linux" + + +generic_CODE = \ + fusb_generic.cc \ + fusb_sysconfig_generic.cc + +darwin_CODE = \ + fusb_darwin.cc \ + fusb_sysconfig_darwin.cc \ + README_OSX \ + circular_buffer.h \ + circular_linked_list.h \ + darwin_libusb.h \ + mld_threads.h + +win32_CODE = \ + fusb_win32.cc \ + fusb_sysconfig_win32.cc + +linux_CODE = \ + fusb_linux.cc \ + fusb_sysconfig_linux.cc + + +# +# include each _CODE entry here... +# +EXTRA_libusrp_la_SOURCES = \ + $(generic_CODE) \ + $(darwin_CODE) \ + $(win32_CODE) \ + $(linux_CODE) + + +# work around automake deficiency +libusrp_la_common_SOURCES = \ + fusb.cc \ + md5.c \ + usrp_basic.cc \ + usrp_config.cc \ + usrp_dbid.cc \ + usrp_local_sighandler.cc \ + usrp_prims.cc \ + usrp_standard.cc + + +if FUSB_TECH_generic +libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(generic_CODE) +endif + +if FUSB_TECH_darwin +libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(darwin_CODE) +endif + +if FUSB_TECH_win32 +libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(win32_CODE) +endif + +if FUSB_TECH_linux +libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(linux_CODE) +endif + + +libusrp_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 +libusrp_la_LIBADD = $(USB_LIBS) ../misc/libmisc.la + +include_HEADERS = \ + usrp_basic.h \ + usrp_bytesex.h \ + usrp_config.h \ + usrp_dbid.h \ + usrp_prims.h \ + usrp_slots.h \ + usrp_standard.h + +noinst_HEADERS = \ + ad9862.h \ + fusb.h \ + fusb_darwin.h \ + fusb_win32.h \ + fusb_generic.h \ + fusb_linux.h \ + md5.h \ + rate_to_regval.h \ + usrp_local_sighandler.h + +python_PYTHON = \ + usrp_dbid.py + +noinst_PYTHON = \ + gen_usrp_dbid.py + +usrp_dbid.py usrp_dbid.h usrp_dbid.cc: gen_usrp_dbid.py usrp_dbid.dat + PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc diff --git a/usrp/host/lib/README_OSX b/usrp/host/lib/README_OSX new file mode 100644 index 00000000..20230f12 --- /dev/null +++ b/usrp/host/lib/README_OSX @@ -0,0 +1,63 @@ +USRP Darwin Fast USB Changes +Version 0.2 of 2006-04-27 +Michael Dickens + +The files included in this archive are: + +circular_buffer.h +circular_linked_list.h +darwin_libusb.h +fusb_darwin.cc +fusb_darwin.h +mld_threads.h + +These files allow GNURadio code for Darwin / MaxOS X to talk to the +USRP via USB 2.0 at rates up to around 30 Mega-Bytes/sec (MBps), up +from 4-8 MBps without the changes. + +I implemented the buffering myself; there are probably GR buffers +available which would do the work but as this is "beta" software it's +a good place to start. Speed improvements are made by porting +LIBUSB's non-true async bulk read and write functions into USRP's +"fusb", and upgrading them to handle -true- async transfers. +Unfortunately, the easiest way to do this is to spawn a thread or 2 to +handle the "async" part of the transfers. This implementation uses +Darwin's pthreads to do the work for mutexes, conditions, and threads. +Previous implementations (0.1 and before) used "omni_threads" as +provided by gnuradio-core, which caused issues with compiling and +execution ... I'm glad that this is no longer the case. + +As far as I have tested, there is no way to improve the throughput to +32+ MBps without moving into Darwin's "port"s ... a kernel-level data +transport method with a user/application layer for USB-specific +functions. Unfortunately, Apple's documentation for these "port"s is +minimal; I have learned more from reading the Darwin source code +< http://darwinsource.opendarwin.org/ > than by reading Apple's +documents! This would also require -not- using LIBUSB, of which the +removal from the rest of the USRP code would be potentially tedious. + +If you run into issues either compiling or testing the USRP on +OSX, please send me a note. + +(1) Go through the bootstrap, configure, compile, and install as +usual (e.g. see < http://www.nd.edu/~mdickens/GNURadio/ > for my +usual). + +(2) from .../usrp/host/apps : run the scripts +++++++++++++++++ +./test_usrp_standard_tx +./test_usrp_standard_rx +++++++++++++++++ + +For -all- systems I've tested on thus far, both of these return +exactly 41 overruns / underruns, and -most- systems start out with a +stalled pipe. This stall comes in a usb_control funciton call to +LIBUSB; one would have to change the LIBUSB code to handle this issue. + +(3) from gr-build/gnuradio-examples/python/usrp : +++++++++++++++++ +./benchmark_usb.py +++++++++++++++++ + +(4) If you get to here, the try doing the FM receiver (gui or not). +If that sounds correct, then the USB is working. Yay! \ No newline at end of file diff --git a/usrp/host/lib/ad9862.h b/usrp/host/lib/ad9862.h new file mode 100644 index 00000000..70cb2028 --- /dev/null +++ b/usrp/host/lib/ad9862.h @@ -0,0 +1,221 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AD9862_H +#define INCLUDED_AD9862_H + +/* + * Analog Devices AD9862 registers and some fields + */ + +#define BEGIN_AD9862 namespace ad9862 { +#define END_AD962 } +#define DEF static const int + +BEGIN_AD9862; + +DEF REG_GENERAL = 0; +DEF REG_RX_PWR_DN = 1; +DEF RX_PWR_DN_VREF_DIFF = (1 << 7); +DEF RX_PWR_DN_VREF = (1 << 6); +DEF RX_PWR_DN_RX_DIGIGAL = (1 << 5); +DEF RX_PWR_DN_RX_B = (1 << 4); +DEF RX_PWR_DN_RX_A = (1 << 3); +DEF RX_PWR_DN_BUF_B = (1 << 2); +DEF RX_PWR_DN_BUF_A = (1 << 1); +DEF RX_PWR_DN_ALL = (1 << 0); + +DEF REG_RX_A = 2; // bypass input buffer / RxPGA +DEF REG_RX_B = 3; // pypass input buffer / RxPGA +DEF RX_X_BYPASS_INPUT_BUFFER = (1 << 7); + +DEF REG_RX_MISC = 4; +DEF RX_MISC_HS_DUTY_CYCLE = (1 << 2); +DEF RX_MISC_SHARED_REF = (1 << 1); +DEF RX_MISC_CLK_DUTY = (1 << 0); + +DEF REG_RX_IF = 5; +DEF RX_IF_THREE_STATE = (1 << 4); +DEF RX_IF_USE_CLKOUT1 = (0 << 3); +DEF RX_IF_USE_CLKOUT2 = (1 << 3); // aka Rx Retime +DEF RX_IF_2S_COMP = (1 << 2); +DEF RX_IF_INV_RX_SYNC = (1 << 1); +DEF RX_IF_MUX_OUT = (1 << 0); + +DEF REG_RX_DIGITAL = 6; +DEF RX_DIGITAL_2_CHAN = (1 << 3); +DEF RX_DIGITAL_KEEP_MINUS_VE = (1 << 2); +DEF RX_DIGITAL_HILBERT = (1 << 1); +DEF RX_DIGITAL_DECIMATE = (1 << 0); + +DEF REG_RESERVED_7 = 7; + +DEF REG_TX_PWR_DN = 8; +DEF TX_PWR_DN_ALT_TIMING_MODE = (1 << 5); +DEF TX_PWR_DN_TX_OFF_ENABLE = (1 << 4); +DEF TX_PWR_DN_TX_DIGITAL = (1 << 3); +DEF TX_PWR_DN_TX_ANALOG_B = 0x4; +DEF TX_PWR_DN_TX_ANALOG_A = 0x2; +DEF TX_PWR_DN_TX_ANALOG_BOTH = 0x7; + +DEF REG_RESERVED_9 = 9; + +DEF REG_TX_A_OFFSET_LO = 10; +DEF REG_TX_A_OFFSET_HI = 11; +DEF REG_TX_B_OFFSET_LO = 12; +DEF REG_TX_B_OFFSET_HI = 13; + +DEF REG_TX_A_GAIN = 14; // fine trim for matching +DEF REG_TX_B_GAIN = 15; // fine trim for matching +DEF TX_X_GAIN_COARSE_FULL = (3 << 6); +DEF TX_X_GAIN_COARSE_1_HALF = (1 << 6); +DEF TX_X_GAIN_COARSE_1_ELEVENTH = (0 << 6); + +DEF REG_TX_PGA = 16; // 20 dB continuous gain in 0.1 dB steps + // 0x00 = min gain (-20 dB) + // 0xff = max gain ( 0 dB) + +DEF REG_TX_MISC = 17; +DEF TX_MISC_SLAVE_ENABLE = (1 << 1); +DEF TX_MISC_TX_PGA_FAST = (1 << 0); + +DEF REG_TX_IF = 18; +DEF TX_IF_USE_CLKOUT2 = (0 << 6); +DEF TX_IF_USE_CLKOUT1 = (1 << 6); // aka Tx Retime +DEF TX_IF_I_FIRST = (0 << 5); +DEF TX_IF_Q_FIRST = (1 << 5); +DEF TX_IF_INV_TX_SYNC = (1 << 4); +DEF TX_IF_2S_COMP = (1 << 3); +DEF TX_IF_INVERSE_SAMPLE = (1 << 2); +DEF TX_IF_TWO_EDGES = (1 << 1); +DEF TX_IF_INTERLEAVED = (1 << 0); + +DEF REG_TX_DIGITAL = 19; +DEF TX_DIGITAL_2_DATA_PATHS = (1 << 4); +DEF TX_DIGITAL_KEEP_NEGATIVE = (1 << 3); +DEF TX_DIGITAL_HILBERT = (1 << 2); +DEF TX_DIGITAL_INTERPOLATE_NONE = 0x0; +DEF TX_DIGITAL_INTERPOLATE_2X = 0x1; +DEF TX_DIGITAL_INTERPOLATE_4X = 0x2; + +DEF REG_TX_MODULATOR = 20; +DEF TX_MODULATOR_NEG_FINE_TUNE = (1 << 5); +DEF TX_MODULATOR_DISABLE_NCO = (0 << 4); +DEF TX_MODULATOR_ENABLE_NCO = (1 << 4); // aka Fine Mode +DEF TX_MODULATOR_REAL_MIX_MODE = (1 << 3); +DEF TX_MODULATOR_NEG_COARSE_TUNE = (1 << 2); +DEF TX_MODULATOR_COARSE_MODULATION_NONE = 0x0; +DEF TX_MODULATOR_COARSE_MODULATION_F_OVER_4 = 0x1; +DEF TX_MODULATOR_COARSE_MODULATION_F_OVER_8 = 0x2; +DEF TX_MODULATOR_CM_MASK = 0x7; + + +DEF REG_TX_NCO_FTW_7_0 = 21; +DEF REG_TX_NCO_FTW_15_8 = 22; +DEF REG_TX_NCO_FTW_23_16= 23; + +DEF REG_DLL = 24; +DEF DLL_DISABLE_INTERNAL_XTAL_OSC = (1 << 6); // aka Input Clock Ctrl +DEF DLL_ADC_DIV2 = (1 << 5); +DEF DLL_MULT_1X = (0 << 3); +DEF DLL_MULT_2X = (1 << 3); +DEF DLL_MULT_4X = (2 << 3); +DEF DLL_PWR_DN = (1 << 2); +// undefined bit = (1 << 1); +DEF DLL_FAST = (1 << 0); + +DEF REG_CLKOUT = 25; +DEF CLKOUT2_EQ_DLL = (0 << 6); +DEF CLKOUT2_EQ_DLL_OVER_2 = (1 << 6); +DEF CLKOUT2_EQ_DLL_OVER_4 = (2 << 6); +DEF CLKOUT2_EQ_DLL_OVER_8 = (3 << 6); +DEF CLKOUT_INVERT_CLKOUT2 = (1 << 5); +DEF CLKOUT_DISABLE_CLKOUT2 = (1 << 4); +// undefined bit = (1 << 3); +// undefined bit = (1 << 2); +DEF CLKOUT_INVERT_CLKOUT1 = (1 << 1); +DEF CLKOUT_DISABLE_CLKOUT1 = (1 << 0); + +DEF REG_AUX_ADC_A2_LO = 26; +DEF REG_AUX_ADC_A2_HI = 27; +DEF REG_AUX_ADC_A1_LO = 28; +DEF REG_AUX_ADC_A1_HI = 29; +DEF REG_AUX_ADC_B2_LO = 30; +DEF REG_AUX_ADC_B2_HI = 31; +DEF REG_AUX_ADC_B1_LO = 32; +DEF REG_AUX_ADC_B1_HI = 33; + +DEF REG_AUX_ADC_CTRL = 34; +DEF AUX_ADC_CTRL_AUX_SPI = (1 << 7); +DEF AUX_ADC_CTRL_SELBNOTA = (1 << 6); +DEF AUX_ADC_CTRL_REFSEL_B = (1 << 5); +DEF AUX_ADC_CTRL_SELECT_B2 = (0 << 4); +DEF AUX_ADC_CTRL_SELECT_B1 = (1 << 4); +DEF AUX_ADC_CTRL_START_B = (1 << 3); +DEF AUX_ADC_CTRL_REFSEL_A = (1 << 2); +DEF AUX_ADC_CTRL_SELECT_A2 = (0 << 1); +DEF AUX_ADC_CTRL_SELECT_A1 = (1 << 1); +DEF AUX_ADC_CTRL_START_A = (1 << 0); + +DEF REG_AUX_ADC_CLK = 35; +DEF AUX_ADC_CLK_CLK_OVER_4 = (1 << 0); + +DEF REG_AUX_DAC_A = 36; +DEF REG_AUX_DAC_B = 37; +DEF REG_AUX_DAC_C = 38; + +DEF REG_AUX_DAC_UPDATE = 39; +DEF AUX_DAC_UPDATE_SLAVE_ENABLE = (1 << 7); +DEF AUX_DAC_UPDATE_C = (1 << 2); +DEF AUX_DAC_UPDATE_B = (1 << 1); +DEF AUX_DAC_UPDATE_A = (1 << 0); + +DEF REG_AUX_DAC_PWR_DN = 40; +DEF AUX_DAC_PWR_DN_C = (1 << 2); +DEF AUX_DAC_PWR_DN_B = (1 << 1); +DEF AUX_DAC_PWR_DN_A = (1 << 0); + +DEF REG_AUX_DAC_CTRL = 41; +DEF AUX_DAC_CTRL_INV_C = (1 << 4); +DEF AUX_DAC_CTRL_INV_B = (1 << 2); +DEF AUX_DAC_CTRL_INV_A = (1 << 0); + +DEF REG_SIGDELT_LO = 42; +DEF REG_SIGDELT_HI = 43; + +// 44 to 48 reserved + +DEF REG_ADC_LOW_PWR_LO = 49; +DEF REG_ADC_LOW_PWR_HI = 50; + +// 51 to 62 reserved + +DEF REG_CHIP_ID = 63; + + +END_AD962; + +#undef DEF +#undef BEGIN_AD9862 +#undef END_AD962 + +#endif /* INCLUDED_AD9862_H */ diff --git a/usrp/host/lib/check_data.py b/usrp/host/lib/check_data.py new file mode 100755 index 00000000..0f8ea2ef --- /dev/null +++ b/usrp/host/lib/check_data.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import sys +import struct + +fin = sys.stdin + +count = 0 +expected = 0 +last_correction = 0 + +while 1: + s = fin.read(2) + if not s or len(s) != 2: + break + + v, = struct.unpack ('H', s) + iv = int(v) & 0xffff + # print "%8d %6d 0x%04x" % (count, iv, iv) + if count & 0x1: # only counting on the Q channel + if (expected & 0xffff) != iv: + print "%8d (%6d) %6d 0x%04x" % (count, count - last_correction, iv, iv) + expected = iv # reset expected sequence + last_correction = count + expected = (expected + 1) & 0xffff + + count += 1 + + + + diff --git a/usrp/host/lib/circular_buffer.h b/usrp/host/lib/circular_buffer.h new file mode 100644 index 00000000..4d507c2e --- /dev/null +++ b/usrp/host/lib/circular_buffer.h @@ -0,0 +1,325 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CIRCULAR_BUFFER_H_ +#define _CIRCULAR_BUFFER_H_ + +#include "mld_threads.h" +#include + +#define DO_DEBUG 0 + +template class circular_buffer +{ +private: +// the buffer to use + T* d_buffer; + +// the following are in Items (type T) + UInt32 d_bufLen_I, d_readNdx_I, d_writeNdx_I; + UInt32 d_n_avail_write_I, d_n_avail_read_I; + +// stuff to control access to class internals + mld_mutex_ptr d_internal; + mld_condition_ptr d_readBlock, d_writeBlock; + +// booleans to decide how to control reading, writing, and aborting + bool d_doWriteBlock, d_doFullRead, d_doAbort; + + void delete_mutex_cond () { + if (d_internal) { + delete d_internal; + d_internal = NULL; + } + if (d_readBlock) { + delete d_readBlock; + d_readBlock = NULL; + } + if (d_writeBlock) { + delete d_writeBlock; + d_writeBlock = NULL; + } + }; + +public: + circular_buffer (UInt32 bufLen_I, + bool doWriteBlock = true, bool doFullRead = false) { + if (bufLen_I == 0) + throw std::runtime_error ("circular_buffer(): " + "Number of items to buffer must be > 0.\n"); + d_bufLen_I = bufLen_I; + d_buffer = (T*) new T[d_bufLen_I]; + d_doWriteBlock = doWriteBlock; + d_doFullRead = doFullRead; + d_internal = NULL; + d_readBlock = d_writeBlock = NULL; + reset (); +#if DO_DEBUG + fprintf (stderr, "c_b(): buf len (items) = %ld, " + "doWriteBlock = %s, doFullRead = %s\n", d_bufLen_I, + (d_doWriteBlock ? "true" : "false"), + (d_doFullRead ? "true" : "false")); +#endif + }; + + ~circular_buffer () { + delete_mutex_cond (); + delete [] d_buffer; + }; + + inline UInt32 n_avail_write_items () { + d_internal->lock (); + UInt32 retVal = d_n_avail_write_I; + d_internal->unlock (); + return (retVal); + }; + + inline UInt32 n_avail_read_items () { + d_internal->lock (); + UInt32 retVal = d_n_avail_read_I; + d_internal->unlock (); + return (retVal); + }; + + inline UInt32 buffer_length_items () {return (d_bufLen_I);}; + inline bool do_write_block () {return (d_doWriteBlock);}; + inline bool do_full_read () {return (d_doFullRead);}; + + void reset () { + d_doAbort = false; + bzero (d_buffer, d_bufLen_I * sizeof (T)); + d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0; + d_n_avail_write_I = d_bufLen_I; + delete_mutex_cond (); + d_internal = new mld_mutex (); + d_readBlock = new mld_condition (); + d_writeBlock = new mld_condition (); + }; + +/* + * enqueue: add the given buffer of item-length to the queue, + * first-in-first-out (FIFO). + * + * inputs: + * buf: a pointer to the buffer holding the data + * + * bufLen_I: the buffer length in items (of the instantiated type) + * + * returns: + * -1: on overflow (write is not blocking, and data is being + * written faster than it is being read) + * 0: if nothing to do (0 length buffer) + * 1: if success + * 2: in the process of aborting, do doing nothing + * + * will throw runtime errors if inputs are improper: + * buffer pointer is NULL + * buffer length is larger than the instantiated buffer length + */ + + int enqueue (T* buf, UInt32 bufLen_I) { +#if DO_DEBUG + fprintf (stderr, "enqueue: buf = %X, bufLen = %ld.\n", + (unsigned int)buf, bufLen_I); +#endif + if (bufLen_I > d_bufLen_I) { + fprintf (stderr, "cannot add buffer longer (%ld" + ") than instantiated length (%ld" + ").\n", bufLen_I, d_bufLen_I); + throw std::runtime_error ("circular_buffer::enqueue()"); + } + + if (bufLen_I == 0) + return (0); + if (!buf) + throw std::runtime_error ("circular_buffer::enqueue(): " + "input buffer is NULL.\n"); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); + return (2); + } + if (bufLen_I > d_n_avail_write_I) { + if (d_doWriteBlock) { + while (bufLen_I > d_n_avail_write_I) { +#if DO_DEBUG + fprintf (stderr, "enqueue: #len > #a, waiting.\n"); +#endif + d_internal->unlock (); + d_writeBlock->wait (); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); +#if DO_DEBUG + fprintf (stderr, "enqueue: #len > #a, aborting.\n"); +#endif + return (2); + } +#if DO_DEBUG + fprintf (stderr, "enqueue: #len > #a, done waiting.\n"); +#endif + } + } else { + d_n_avail_read_I = d_bufLen_I - bufLen_I; + d_n_avail_write_I = bufLen_I; +#if DO_DEBUG + fprintf (stderr, "circular_buffer::enqueue: overflow\n"); +#endif + return (-1); + } + } + UInt32 n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0; + if (n_now_I > bufLen_I) + n_now_I = bufLen_I; + else if (n_now_I < bufLen_I) + n_start_I = bufLen_I - n_now_I; + bcopy (buf, &(d_buffer[d_writeNdx_I]), n_now_I * sizeof (T)); + if (n_start_I) { + bcopy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T)); + d_writeNdx_I = n_start_I; + } else + d_writeNdx_I += n_now_I; + d_n_avail_read_I += bufLen_I; + d_n_avail_write_I -= bufLen_I; + d_readBlock->signal (); + d_internal->unlock (); + return (1); + }; + +/* + * dequeue: removes from the queue the number of items requested, or + * available, into the given buffer on a FIFO basis. + * + * inputs: + * buf: a pointer to the buffer into which to copy the data + * + * bufLen_I: pointer to the number of items to remove in items + * (of the instantiated type) + * + * returns: + * 0: if nothing to do (0 length buffer) + * 1: if success + * 2: in the process of aborting, do doing nothing + * + * will throw runtime errors if inputs are improper: + * buffer pointer is NULL + * buffer length pointer is NULL + * buffer length is larger than the instantiated buffer length + */ + + + int dequeue (T* buf, UInt32* bufLen_I) { +#if DO_DEBUG + fprintf (stderr, "dequeue: buf = %X, *bufLen = %ld.\n", + (unsigned int)buf, *bufLen_I); +#endif + if (!bufLen_I) + throw std::runtime_error ("circular_buffer::dequeue(): " + "input bufLen pointer is NULL.\n"); + if (!buf) + throw std::runtime_error ("circular_buffer::dequeue(): " + "input buffer pointer is NULL.\n"); + UInt32 l_bufLen_I = *bufLen_I; + if (l_bufLen_I == 0) + return (0); + if (l_bufLen_I > d_bufLen_I) { + fprintf (stderr, "cannot remove buffer longer (%ld" + ") than instantiated length (%ld" + ").\n", l_bufLen_I, d_bufLen_I); + throw std::runtime_error ("circular_buffer::dequeue()"); + } + + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); + return (2); + } + if (d_doFullRead) { + while (d_n_avail_read_I < l_bufLen_I) { +#if DO_DEBUG + fprintf (stderr, "dequeue: #a < #len, waiting.\n"); +#endif + d_internal->unlock (); + d_readBlock->wait (); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); +#if DO_DEBUG + fprintf (stderr, "dequeue: #a < #len, aborting.\n"); +#endif + return (2); + } +#if DO_DEBUG + fprintf (stderr, "dequeue: #a < #len, done waiting.\n"); +#endif + } + } else { + while (d_n_avail_read_I == 0) { +#if DO_DEBUG + fprintf (stderr, "dequeue: #a == 0, waiting.\n"); +#endif + d_internal->unlock (); + d_readBlock->wait (); + d_internal->lock (); + if (d_doAbort) { + d_internal->unlock (); +#if DO_DEBUG + fprintf (stderr, "dequeue: #a == 0, aborting.\n"); +#endif + return (2); + } +#if DO_DEBUG + fprintf (stderr, "dequeue: #a == 0, done waiting.\n"); +#endif + } + } + if (l_bufLen_I > d_n_avail_read_I) + l_bufLen_I = d_n_avail_read_I; + UInt32 n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0; + if (n_now_I > l_bufLen_I) + n_now_I = l_bufLen_I; + else if (n_now_I < l_bufLen_I) + n_start_I = l_bufLen_I - n_now_I; + bcopy (&(d_buffer[d_readNdx_I]), buf, n_now_I * sizeof (T)); + if (n_start_I) { + bcopy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T)); + d_readNdx_I = n_start_I; + } else + d_readNdx_I += n_now_I; + *bufLen_I = l_bufLen_I; + d_n_avail_read_I -= l_bufLen_I; + d_n_avail_write_I += l_bufLen_I; + d_writeBlock->signal (); + d_internal->unlock (); + return (1); + }; + + void abort () { + d_internal->lock (); + d_doAbort = true; + d_writeBlock->signal (); + d_readBlock->signal (); + d_internal->unlock (); + }; +}; + +#endif /* _CIRCULAR_BUFFER_H_ */ diff --git a/usrp/host/lib/circular_linked_list.h b/usrp/host/lib/circular_linked_list.h new file mode 100644 index 00000000..bdfcb084 --- /dev/null +++ b/usrp/host/lib/circular_linked_list.h @@ -0,0 +1,267 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CIRCULAR_LINKED_LIST_H_ +#define _CIRCULAR_LINKED_LIST_H_ + +#include +#include + +#define __INLINE__ inline + +template class s_both; + +template class s_node +{ + typedef s_node* s_node_ptr; + +private: + T d_object; + bool d_available; + s_node_ptr d_prev, d_next; + s_both* d_both; + +public: + s_node (T l_object, + s_node_ptr l_prev = NULL, + s_node_ptr l_next = NULL) + : d_object (l_object), d_available (TRUE), d_prev (l_prev), + d_next (l_next), d_both (0) {}; + + __INLINE__ s_node (s_node_ptr l_prev, s_node_ptr l_next = NULL) { + s_node ((T) NULL, l_prev, l_next); }; + __INLINE__ s_node () { s_node (NULL, NULL, NULL); }; + __INLINE__ ~s_node () {}; + + void remove () { + d_prev->next (d_next); + d_next->prev (d_prev); + d_prev = d_next = this; + }; + + void insert_before (s_node_ptr l_next) { + if (l_next) { + s_node_ptr l_prev = l_next->prev (); + d_next = l_next; + d_prev = l_prev; + l_prev->next (this); + l_next->prev (this); + } else + d_next = d_prev = this; + }; + + void insert_after (s_node_ptr l_prev) { + if (l_prev) { + s_node_ptr l_next = l_prev->next (); + d_prev = l_prev; + d_next = l_next; + l_next->prev (this); + l_prev->next (this); + } else + d_prev = d_next = this; + }; + + __INLINE__ T object () { return (d_object); }; + __INLINE__ void object (T l_object) { d_object = l_object; }; + __INLINE__ bool available () { return (d_available); }; + __INLINE__ void set_available () { d_available = TRUE; }; + __INLINE__ void set_available (bool l_avail) { d_available = l_avail; }; + __INLINE__ void set_not_available () { d_available = FALSE; }; + __INLINE__ s_node_ptr next () { return (d_next); }; + __INLINE__ s_node_ptr prev () { return (d_prev); }; + __INLINE__ s_both* both () { return (d_both); }; + __INLINE__ void next (s_node_ptr l_next) { d_next = l_next; }; + __INLINE__ void prev (s_node_ptr l_prev) { d_prev = l_prev; }; + __INLINE__ void both (s_both* l_both) { d_both = l_both; }; +}; + +template class circular_linked_list { + typedef s_node* s_node_ptr; + +private: + s_node_ptr d_current, d_iterate, d_available, d_inUse; + UInt32 d_n_nodes, d_n_used; + mld_mutex_ptr d_internal; + mld_condition_ptr d_ioBlock; + +public: + circular_linked_list (UInt32 n_nodes) { + if (n_nodes == 0) + throw std::runtime_error ("circular_linked_list(): n_nodes == 0"); + + d_iterate = NULL; + d_n_nodes = n_nodes; + d_n_used = 0; + s_node_ptr l_prev, l_next; + d_inUse = d_current = l_next = l_prev = NULL; + + l_prev = new s_node (); + l_prev->set_available (); + l_prev->next (l_prev); + l_prev->prev (l_prev); + if (n_nodes > 1) { + l_next = new s_node (l_prev, l_prev); + l_next->set_available (); + l_next->next (l_prev); + l_next->prev (l_prev); + l_prev->next (l_next); + l_prev->prev (l_next); + if (n_nodes > 2) { + UInt32 n = n_nodes - 2; + while (n-- > 0) { + d_current = new s_node (l_prev, l_next); + d_current->set_available (); + d_current->prev (l_prev); + d_current->next (l_next); + l_prev->next (d_current); + l_next->prev (d_current); + l_next = d_current; + d_current = NULL; + } + } + } + d_available = d_current = l_prev; + d_internal = new mld_mutex (); + d_ioBlock = new mld_condition (); + }; + + ~circular_linked_list () { + iterate_start (); + s_node_ptr l_node = iterate_next (); + while (l_node) { + delete l_node; + l_node = iterate_next (); + } + delete d_internal; + d_internal = NULL; + delete d_ioBlock; + d_ioBlock = NULL; + d_available = d_inUse = d_iterate = d_current = NULL; + d_n_used = d_n_nodes = 0; + }; + + s_node_ptr find_next_available_node () { + d_internal->lock (); +// find an available node + s_node_ptr l_node = d_available; + while (! l_node) { + d_internal->unlock (); + d_ioBlock->wait (); + d_internal->lock (); + l_node = d_available; + } +// fprintf (stderr, "::f_n_a_n: #u = %ld, node = %p\n", num_used(), l_node); +// remove this one from the current available list + if (num_available () == 1) { +// last one, just set available to NULL + d_available = NULL; + } else + d_available = l_node->next (); + l_node->remove (); +// add is to the inUse list + if (! d_inUse) + d_inUse = l_node; + else + l_node->insert_before (d_inUse); + d_n_used++; + l_node->set_not_available (); + d_internal->unlock (); + return (l_node); + }; + + void make_node_available (s_node_ptr l_node) { + if (!l_node) return; + d_internal->lock (); +// fprintf (stderr, "::m_n_a: #u = %ld, node = %p\n", num_used(), l_node); +// remove this node from the inUse list + if (num_used () == 1) { +// last one, just set inUse to NULL + d_inUse = NULL; + } else + d_inUse = l_node->next (); + l_node->remove (); +// add this node to the available list + if (! d_available) + d_available = l_node; + else + l_node->insert_before (d_available); + d_n_used--; +// signal the condition when new data arrives + d_ioBlock->signal (); +// unlock the mutex for thread safety + d_internal->unlock (); + }; + + __INLINE__ void iterate_start () { d_iterate = d_current; }; + + s_node_ptr iterate_next () { +#if 0 +// lock the mutex for thread safety + d_internal->lock (); +#endif + s_node_ptr l_this = NULL; + if (d_iterate) { + l_this = d_iterate; + d_iterate = d_iterate->next (); + if (d_iterate == d_current) + d_iterate = NULL; + } +#if 0 +// unlock the mutex for thread safety + d_internal->unlock (); +#endif + return (l_this); + }; + + __INLINE__ T object () { return (d_current->d_object); }; + __INLINE__ void object (T l_object) { d_current->d_object = l_object; }; + __INLINE__ UInt32 num_nodes () { return (d_n_nodes); }; + __INLINE__ UInt32 num_used () { return (d_n_used); }; + __INLINE__ void num_used (UInt32 l_n_used) { d_n_used = l_n_used; }; + __INLINE__ UInt32 num_available () { return (d_n_nodes - d_n_used); }; + __INLINE__ void num_used_inc (void) { + if (d_n_used < d_n_nodes) ++d_n_used; + }; + __INLINE__ void num_used_dec (void) { + if (d_n_used != 0) --d_n_used; +// signal the condition that new data has arrived + d_ioBlock->signal (); + }; + __INLINE__ bool in_use () { return (d_n_used != 0); }; +}; + +template class s_both +{ +private: + s_node* d_node; + void* d_this; +public: + __INLINE__ s_both (s_node* l_node, void* l_this) + : d_node (l_node), d_this (l_this) {}; + __INLINE__ ~s_both () {}; + __INLINE__ s_node* node () { return (d_node); }; + __INLINE__ void* This () { return (d_this); }; + __INLINE__ void set (s_node* l_node, void* l_this) { + d_node = l_node; d_this = l_this;}; +}; + +#endif /* _CIRCULAR_LINKED_LIST_H_ */ diff --git a/usrp/host/lib/darwin_libusb.h b/usrp/host/lib/darwin_libusb.h new file mode 100644 index 00000000..164ab9c7 --- /dev/null +++ b/usrp/host/lib/darwin_libusb.h @@ -0,0 +1,190 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * The following code was taken from LIBUSB verion 0.1.10a, + * and makes the fusb_darwin codes do-able in the current GR + * programming framework. Parts and pieces were taken from + * usbi.h, darwin.c, and error.h . + * + * LIBUSB version 0.1.10a is covered by the LGPL, version 2; + * These codes are used with permission from: + * (c) 2000-2003 Johannes Erdfelt + * (c) 2002-2005 Nathan Hjelm + * All rights reserved. + */ + +#ifndef __DARWIN_LIBUSB_H__ +#define __DARWIN_LIBUSB_H__ + +#include +#include +#include +#include + +extern "C" { +static char * +darwin_error_str (int result) +{ + switch (result) { + case kIOReturnSuccess: + return "no error"; + case kIOReturnNotOpen: + return "device not opened for exclusive access"; + case kIOReturnNoDevice: + return "no connection to an IOService"; + case kIOUSBNoAsyncPortErr: + return "no asyc port has been opened for interface"; + case kIOReturnExclusiveAccess: + return "another process has device opened for exclusive access"; + case kIOUSBPipeStalled: + return "pipe is stalled"; + case kIOReturnError: + return "could not establish a connection to Darin kernel"; + case kIOReturnBadArgument: + return "invalid argument"; + default: + return "unknown error"; + } +} + +/* not a valid errorno outside darwin.c */ +#define LUSBDARWINSTALL (ELAST+1) + +static int +darwin_to_errno (int result) +{ + switch (result) { + case kIOReturnSuccess: + return 0; + case kIOReturnNotOpen: + return EBADF; + case kIOReturnNoDevice: + case kIOUSBNoAsyncPortErr: + return ENXIO; + case kIOReturnExclusiveAccess: + return EBUSY; + case kIOUSBPipeStalled: + return LUSBDARWINSTALL; + case kIOReturnBadArgument: + return EINVAL; + case kIOReturnError: + default: + return 1; + } +} + +typedef enum { + USB_ERROR_TYPE_NONE = 0, + USB_ERROR_TYPE_STRING, + USB_ERROR_TYPE_ERRNO, +} usb_error_type_t; + +extern char usb_error_str[1024]; +extern int usb_error_errno; +extern usb_error_type_t usb_error_type; + +#define USB_ERROR(r, x) \ + do { \ + usb_error_type = USB_ERROR_TYPE_ERRNO; \ + usb_error_errno = x; \ + return r; \ + } while (0) + +#define USB_ERROR_STR(r, x, format, args...) \ + do { \ + usb_error_type = USB_ERROR_TYPE_STRING; \ + snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \ + if (usb_debug) \ + fprintf(stderr, "USB error: %s\n", usb_error_str); \ + return r; \ + } while (0) + +#define USB_ERROR_STR_ORIG(x, format, args...) \ + do { \ + usb_error_type = USB_ERROR_TYPE_STRING; \ + snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \ + if (usb_debug) \ + fprintf(stderr, "USB error: %s\n", usb_error_str); \ + return x; \ + } while (0) + +#define USB_ERROR_STR_NO_RET(x, format, args...) \ + do { \ + usb_error_type = USB_ERROR_TYPE_STRING; \ + snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \ + if (usb_debug) \ + fprintf(stderr, "USB error: %s\n", usb_error_str); \ + } while (0) + +/* simple function that figures out what pipeRef is associated with an endpoint */ +static int ep_to_pipeRef (darwin_dev_handle *device, int ep) +{ + io_return_t ret; + UInt8 numep, direction, number; + UInt8 dont_care1, dont_care3; + UInt16 dont_care2; + int i; + + if (usb_debug > 3) + fprintf(stderr, "Converting ep address to pipeRef.\n"); + + /* retrieve the total number of endpoints on this interface */ + ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep); + if ( ret ) { + if ( usb_debug > 3 ) + fprintf ( stderr, "ep_to_pipeRef: interface is %p\n", device->interface ); + USB_ERROR_STR_ORIG ( -ret, "ep_to_pipeRef: can't get number of endpoints for interface" ); + } + + /* iterate through the pipeRefs until we find the correct one */ + for (i = 1 ; i <= numep ; i++) { + ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number, + &dont_care1, &dont_care2, &dont_care3); + + if (ret != kIOReturnSuccess) { + fprintf (stderr, "ep_to_pipeRef: an error occurred getting pipe information on pipe %d\n", + i ); + USB_ERROR_STR_ORIG (-darwin_to_errno(ret), "ep_to_pipeRef(GetPipeProperties): %s", darwin_error_str(ret)); + } + + if (usb_debug > 3) + fprintf (stderr, "ep_to_pipeRef: Pipe %i: DIR: %i number: %i\n", i, direction, number); + + /* calculate the endpoint of the pipe and check it versus the requested endpoint */ + if ( ((direction << 7 & USB_ENDPOINT_DIR_MASK) | (number & USB_ENDPOINT_ADDRESS_MASK)) == ep ) { + if (usb_debug > 3) + fprintf(stderr, "ep_to_pipeRef: pipeRef for ep address 0x%02x found: 0x%02x\n", ep, i); + + return i; + } + } + + if (usb_debug > 3) + fprintf(stderr, "ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep); + + /* none of the found pipes match the requested endpoint */ + return -1; +} + +} +#endif /* __DARWIN_LIBUSB_H__ */ diff --git a/usrp/host/lib/dump_data.py b/usrp/host/lib/dump_data.py new file mode 100755 index 00000000..fea0b9de --- /dev/null +++ b/usrp/host/lib/dump_data.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import sys +import struct + +fin = sys.stdin + +count = 0 + +while 1: + s = fin.read(2) + if not s or len(s) != 2: + break + + v, = struct.unpack ('H', s) + iv = int(v) & 0xffff + print "%8d %6d 0x%04x" % (count, iv, iv) + count += 1 + + + diff --git a/usrp/host/lib/dxc-io-assignments.gnumeric b/usrp/host/lib/dxc-io-assignments.gnumeric new file mode 100644 index 00000000..85e1a881 Binary files /dev/null and b/usrp/host/lib/dxc-io-assignments.gnumeric differ diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc new file mode 100644 index 00000000..ef32cd8d --- /dev/null +++ b/usrp/host/lib/fusb.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +// ------------------------------------------------------------------------ +// device handle +// ------------------------------------------------------------------------ + +fusb_devhandle::fusb_devhandle (usb_dev_handle *udh) + : d_udh (udh) +{ + // that's it +}; + +fusb_devhandle::~fusb_devhandle () +{ + // nop +} + +// ------------------------------------------------------------------------ +// end point handle +// ------------------------------------------------------------------------ + +fusb_ephandle::fusb_ephandle (int endpoint, bool input_p, + int block_size, int nblocks) + : d_endpoint (endpoint), d_input_p (input_p), + d_block_size (block_size), d_nblocks (nblocks), d_started (false) +{ + // that't it +} + +fusb_ephandle::~fusb_ephandle () +{ + // nop +} diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h new file mode 100644 index 00000000..5a902278 --- /dev/null +++ b/usrp/host/lib/fusb.h @@ -0,0 +1,128 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Fast USB interface + +#ifndef _FUSB_H_ +#define _FUSB_H_ + + +struct usb_dev_handle; +class fusb_ephandle; + +/*! + * \brief abstract usb device handle + */ +class fusb_devhandle { +private: + // NOT IMPLEMENTED + fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor + fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator + +protected: + usb_dev_handle *d_udh; + +public: + // CREATORS + fusb_devhandle (usb_dev_handle *udh); + virtual ~fusb_devhandle (); + + // MANIPULATORS + + /*! + * \brief return an ephandle of the correct subtype + */ + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0) = 0; + + // ACCESSORS + usb_dev_handle *get_usb_dev_handle () const { return d_udh; } +}; + + +/*! + * \brief abstract usb end point handle + */ +class fusb_ephandle { +private: + // NOT IMPLEMENTED + fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor + fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator + +protected: + int d_endpoint; + bool d_input_p; + int d_block_size; + int d_nblocks; + bool d_started; + +public: + fusb_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle (); + + virtual bool start () = 0; //!< begin streaming i/o + virtual bool stop () = 0; //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes) = 0; + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes) = 0; + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion () = 0; + + /*! + * \brief returns current block size. + */ + int block_size () { return d_block_size; }; +}; + + +/*! + * \brief factory for creating concrete instances of the appropriate subtype. + */ +class fusb_sysconfig { +public: + /*! + * \brief returns fusb_devhandle or throws if trouble + */ + static fusb_devhandle *make_devhandle (usb_dev_handle *udh); + + /*! + * \brief returns max block size hard limit + */ + static int max_block_size (); + +}; + +#endif /* _FUSB_H_ */ diff --git a/usrp/host/lib/fusb_darwin.cc b/usrp/host/lib/fusb_darwin.cc new file mode 100644 index 00000000..081e9811 --- /dev/null +++ b/usrp/host/lib/fusb_darwin.cc @@ -0,0 +1,499 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// tell mld_threads to NOT use omni_threads, +// but rather Darwin's pthreads +#undef _USE_OMNI_THREADS_ + +#include +#include "fusb.h" +#include "fusb_darwin.h" +#include "darwin_libusb.h" + +static const int USB_TIMEOUT = 100; // in milliseconds +static const UInt8 NUM_QUEUE_ITEMS = 20; + +fusb_devhandle_darwin::fusb_devhandle_darwin (usb_dev_handle* udh) + : fusb_devhandle (udh) +{ + // that's it +} + +fusb_devhandle_darwin::~fusb_devhandle_darwin () +{ + // nop +} + +fusb_ephandle* +fusb_devhandle_darwin::make_ephandle (int endpoint, bool input_p, + int block_size, int nblocks) +{ + return new fusb_ephandle_darwin (this, endpoint, input_p, + block_size, nblocks); +} + +// ---------------------------------------------------------------- + +fusb_ephandle_darwin::fusb_ephandle_darwin (fusb_devhandle_darwin* dh, + int endpoint, bool input_p, + int block_size, int nblocks) + : fusb_ephandle (endpoint, input_p, block_size, nblocks), + d_devhandle (dh), d_pipeRef (0), d_transferType (0), + d_interfaceRef (0), d_interface (0), d_queue (0), + d_buffer (0), d_bufLenBytes (0) +{ + d_bufLenBytes = fusb_sysconfig::max_block_size(); + +// create circular buffer + d_buffer = new circular_buffer (NUM_QUEUE_ITEMS * d_bufLenBytes, + !d_input_p, d_input_p); + +// create the queue + d_queue = new circular_linked_list (NUM_QUEUE_ITEMS); + d_queue->iterate_start (); + s_node_ptr l_node = d_queue->iterate_next (); + while (l_node) { + l_node->both (new s_both (l_node, this)); + s_buffer_ptr l_buf = new s_buffer (d_bufLenBytes); + l_node->object (l_buf); + l_node = d_queue->iterate_next (); + l_buf = NULL; + } + + d_readRunning = new mld_mutex (); + d_runThreadRunning = new mld_mutex (); + d_runBlock = new mld_condition (); + d_readBlock = new mld_condition (); +} + +fusb_ephandle_darwin::~fusb_ephandle_darwin () +{ + stop (); + + d_queue->iterate_start (); + s_node_ptr l_node = d_queue->iterate_next (); + while (l_node) { + s_both_ptr l_both = l_node->both (); + delete l_both; + l_both = NULL; + l_node->both (NULL); + s_buffer_ptr l_buf = l_node->object (); + delete l_buf; + l_buf = NULL; + l_node->object (NULL); + l_node = d_queue->iterate_next (); + } + delete d_queue; + d_queue = NULL; + delete d_buffer; + d_buffer = NULL; + delete d_readRunning; + d_readRunning = NULL; + delete d_runThreadRunning; + d_runThreadRunning = NULL; + delete d_runBlock; + d_runBlock = NULL; + delete d_readBlock; + d_readBlock = NULL; +} + +bool +fusb_ephandle_darwin::start () +{ + UInt8 direction, number, interval; + UInt16 maxPacketSize; + +// reset circular buffer + d_buffer->reset (); + +// reset the queue + d_queue->num_used (0); + d_queue->iterate_start (); + s_node_ptr l_node = d_queue->iterate_next (); + while (l_node) { + l_node->both()->set (l_node, this); + l_node->object()->reset (); + l_node->set_available (); + l_node = d_queue->iterate_next (); + } + + d_pipeRef = d_transferType = 0; + + usb_dev_handle* dev = d_devhandle->get_usb_dev_handle (); + if (! dev) + USB_ERROR_STR (false, -ENXIO, "fusb_ephandle_darwin::start: " + "null device"); + + darwin_dev_handle* device = (darwin_dev_handle*) dev->impl_info; + if (! device) + USB_ERROR_STR (false, -ENOENT, "fusb_ephandle_darwin::start: " + "device not initialized"); + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::start: " + "dev = %p, device = %p\n", dev, device); + + d_interfaceRef = device->interface; + if (! d_interfaceRef) + USB_ERROR_STR (false, -EACCES, "fusb_ephandle_darwin::start: " + "interface used without being claimed"); + d_interface = *d_interfaceRef; + +// get read or write pipe info (depends on "d_input_p") + + if (usb_debug > 3) + fprintf (stderr, "fusb_ephandle_darwin::start " + "d_endpoint = %d, d_input_p = %s\n", + d_endpoint, d_input_p ? "TRUE" : "FALSE"); + + int l_endpoint = (d_input_p ? USB_ENDPOINT_IN : USB_ENDPOINT_OUT); + int pipeRef = ep_to_pipeRef (device, d_endpoint | l_endpoint); + if (pipeRef < 0) + USB_ERROR_STR (false, -EINVAL, "fusb_ephandle_darwin::start " + " invalid pipeRef.\n"); + + d_pipeRef = pipeRef; + d_interface->GetPipeProperties (d_interfaceRef, + d_pipeRef, + &direction, + &number, + &d_transferType, + &maxPacketSize, + &interval); + if (usb_debug == 3) + fprintf (stderr, "fusb_ephandle_darwin::start: %s: ep = 0x%02x, " + "pipeRef = %d, d_i = %p, d_iR = %p, if_dir = %d, if_# = %d, " + "if_int = %d, if_maxPS = %d\n", d_input_p ? "read" : "write", + d_endpoint, d_pipeRef, d_interface, d_interfaceRef, direction, + number, interval, maxPacketSize); + +// set global start boolean + d_started = true; + +// create the run thread, which allows OSX to process I/O separately + d_runThread = new mld_thread (run_thread, this); + +// wait until the threads are -really- going + d_runBlock->wait (); + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::start: %s started.\n", + d_input_p ? "read" : "write"); + + return (true); +} + +void +fusb_ephandle_darwin::run_thread (void* arg) +{ + fusb_ephandle_darwin* This = static_cast(arg); + mld_mutex_ptr l_runThreadRunning = This->d_runThreadRunning; + l_runThreadRunning->lock (); + + mld_mutex_ptr l_readRunning = This->d_readRunning; + mld_condition_ptr l_readBlock = This->d_readBlock; + + bool l_input_p = This->d_input_p; + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::run_thread: " + "starting for %s.\n", + l_input_p ? "read" : "write"); + + usb_interface_t** l_interfaceRef = This->d_interfaceRef; + usb_interface_t* l_interface = This->d_interface; + CFRunLoopSourceRef l_cfSource; + +// create async run loop + l_interface->CreateInterfaceAsyncEventSource (l_interfaceRef, &l_cfSource); + CFRunLoopAddSource (CFRunLoopGetCurrent (), l_cfSource, + kCFRunLoopDefaultMode); +// get run loop reference, to allow other threads to stop + This->d_CFRunLoopRef = CFRunLoopGetCurrent (); + + mld_thread_ptr l_rwThread = NULL; + + if (l_input_p) { + l_rwThread = new mld_thread (read_thread, arg); +// wait until the the rwThread is -really- going + l_readBlock->wait (); + } + +// now signal the run condition to release and finish ::start() + This->d_runBlock->signal (); + +// run the loop + CFRunLoopRun (); + + if (l_input_p) { +// wait for read_thread () to finish + l_readRunning->lock (); + l_readRunning->unlock (); + } + +// remove run loop stuff + CFRunLoopRemoveSource (CFRunLoopGetCurrent (), + l_cfSource, kCFRunLoopDefaultMode); + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::run_thread: finished for %s.\n", + l_input_p ? "read" : "write"); + + l_runThreadRunning->unlock (); +} + +void +fusb_ephandle_darwin::read_thread (void* arg) +{ + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::read_thread: starting.\n"); + + fusb_ephandle_darwin* This = static_cast(arg); + + mld_mutex_ptr l_readRunning = This->d_readRunning; + l_readRunning->lock (); + +// signal the read condition from run_thread() to continue + mld_condition_ptr l_readBlock = This->d_readBlock; + l_readBlock->signal (); + + s_queue_ptr l_queue = This->d_queue; + l_queue->iterate_start (); + s_node_ptr l_node = l_queue->iterate_next (); + while (l_node) { + This->read_issue (l_node->both ()); + l_node = l_queue->iterate_next (); + } + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::read_thread: finished.\n"); + + l_readRunning->unlock (); +} + +void +fusb_ephandle_darwin::read_issue (s_both_ptr l_both) +{ + if ((! l_both) || (! d_started)) + return; + +// set the node and buffer from the input "both" + s_node_ptr l_node = l_both->node (); + s_buffer_ptr l_buf = l_node->object (); + void* v_buffer = (void*) l_buf->buffer (); + +// read up to d_bufLenBytes + UInt32 bufLen = d_bufLenBytes; + l_buf->n_used (bufLen); + +// setup system call result + io_return_t result = kIOReturnSuccess; + + if (d_transferType == kUSBInterrupt) +/* This is an interrupt pipe. We can't specify a timeout. */ + result = d_interface->ReadPipeAsync + (d_interfaceRef, d_pipeRef, v_buffer, bufLen, + (IOAsyncCallback1) read_completed, (void*) l_both); + else + result = d_interface->ReadPipeAsyncTO + (d_interfaceRef, d_pipeRef, v_buffer, bufLen, 0, USB_TIMEOUT, + (IOAsyncCallback1) read_completed, (void*) l_both); + + if (result != kIOReturnSuccess) + USB_ERROR_STR_NO_RET (- darwin_to_errno (result), + "fusb_ephandle_darwin::read_issue " + "(ReadPipeAsync%s): %s", + d_transferType == kUSBInterrupt ? "" : "TO", + darwin_error_str (result)); +} + +void +fusb_ephandle_darwin::read_completed (void* refCon, + io_return_t result, + void* io_size) +{ + UInt32 l_size = (UInt32) io_size; + s_both_ptr l_both = static_cast(refCon); + fusb_ephandle_darwin* This = static_cast(l_both->This ()); + s_node_ptr l_node = l_both->node (); + circular_buffer* l_buffer = This->d_buffer; + s_buffer_ptr l_buf = l_node->object (); + UInt32 l_i_size = l_buf->n_used (); + + if (This->d_started && (l_i_size != l_size)) + fprintf (stderr, "fusb_ephandle_darwin::read_completed: " + "Expected %ld bytes; read %ld.\n", + l_i_size, l_size); + +// add this read to the transfer buffer + if (l_buffer->enqueue (l_buf->buffer (), l_size) == -1) { + fputs ("iU", stderr); + fflush (stderr); + } + +// set buffer's # data to 0 + l_buf->n_used (0); + +// issue another read for this "both" + This->read_issue (l_both); +} + +int +fusb_ephandle_darwin::read (void* buffer, int nbytes) +{ + UInt32 l_nbytes = (UInt32) nbytes; + d_buffer->dequeue ((char*) buffer, &l_nbytes); + return ((int) l_nbytes); +} + +int +fusb_ephandle_darwin::write (const void* buffer, int nbytes) +{ + UInt32 l_nbytes = (UInt32) nbytes; + + if (! d_started) return (0); + + while (l_nbytes != 0) { +// find out how much data to copy; limited to "d_bufLenBytes" per node + UInt32 t_nbytes = (l_nbytes > d_bufLenBytes) ? d_bufLenBytes : l_nbytes; + +// get next available node to write into; +// blocks internally if none available + s_node_ptr l_node = d_queue->find_next_available_node (); + +// copy the input into the node's buffer + s_buffer_ptr l_buf = l_node->object (); + l_buf->buffer ((char*) buffer, t_nbytes); + void* v_buffer = (void*) l_buf->buffer (); + +// setup callback parameter & system call return + s_both_ptr l_both = l_node->both (); + io_return_t result = kIOReturnSuccess; + + if (d_transferType == kUSBInterrupt) +/* This is an interrupt pipe ... can't specify a timeout. */ + result = d_interface->WritePipeAsync + (d_interfaceRef, d_pipeRef, v_buffer, l_nbytes, + (IOAsyncCallback1) write_completed, (void*) l_both); + else + result = d_interface->WritePipeAsyncTO + (d_interfaceRef, d_pipeRef, v_buffer, l_nbytes, 0, USB_TIMEOUT, + (IOAsyncCallback1) write_completed, (void*) l_both); + + if (result != kIOReturnSuccess) + USB_ERROR_STR (-1, - darwin_to_errno (result), + "fusb_ephandle_darwin::write_thread " + "(WritePipeAsync%s): %s", + d_transferType == kUSBInterrupt ? "" : "TO", + darwin_error_str (result)); + l_nbytes -= t_nbytes; + } + + return (nbytes); +} + +void +fusb_ephandle_darwin::write_completed (void* refCon, + io_return_t result, + void* io_size) +{ + s_both_ptr l_both = static_cast(refCon); + fusb_ephandle_darwin* This = static_cast(l_both->This ()); + UInt32 l_size = (UInt32) io_size; + s_node_ptr l_node = l_both->node (); + s_queue_ptr l_queue = This->d_queue; + s_buffer_ptr l_buf = l_node->object (); + UInt32 l_i_size = l_buf->n_used (); + + if (This->d_started && (l_i_size != l_size)) + fprintf (stderr, "fusb_ephandle_darwin::write_completed: " + "Expected %ld bytes written; wrote %ld.\n", + l_i_size, l_size); + +// set buffer's # data to 0 + l_buf->n_used (0); +// make the node available for reuse + l_queue->make_node_available (l_node); +} + +void +fusb_ephandle_darwin::abort () +{ + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::abort: starting.\n"); + + io_return_t result = d_interface->AbortPipe (d_interfaceRef, d_pipeRef); + + if (result != kIOReturnSuccess) + USB_ERROR_STR_NO_RET (- darwin_to_errno (result), + "fusb_ephandle_darwin::abort " + "(AbortPipe): %s", darwin_error_str (result)); + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::abort: finished.\n"); +} + +bool +fusb_ephandle_darwin::stop () +{ + if (! d_started) + return (true); + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::stop: stopping %s.\n", + d_input_p ? "read" : "write"); + + d_started = false; + +// abort any pending IO transfers + abort (); + +// wait for write transfer to finish + wait_for_completion (); + +// tell IO buffer to abort any waiting conditions + d_buffer->abort (); + +// stop the run loop + CFRunLoopStop (d_CFRunLoopRef); + +// wait for the runThread to stop + d_runThreadRunning->lock (); + d_runThreadRunning->unlock (); + + if (usb_debug) + fprintf (stderr, "fusb_ephandle_darwin::stop: %s stopped.\n", + d_input_p ? "read" : "write"); + + return (true); +} + +void +fusb_ephandle_darwin::wait_for_completion () +{ + if (d_queue) + while (d_queue->in_use ()) + usleep (1000); +} diff --git a/usrp/host/lib/fusb_darwin.h b/usrp/host/lib/fusb_darwin.h new file mode 100644 index 00000000..601f39ab --- /dev/null +++ b/usrp/host/lib/fusb_darwin.h @@ -0,0 +1,215 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _FUSB_DARWIN_H_ +#define _FUSB_DARWIN_H_ + +#include +#include "fusb.h" +#include +#include +#include +#include +#include "circular_linked_list.h" +#include "circular_buffer.h" + +// for MacOS X 10.4.[0-3] +#define usb_interface_t IOUSBInterfaceInterface220 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 +#define InterfaceVersion 220 + +// for MacOS X 10.3.[0-9] and 10.4.[0-3] +#define usb_device_t IOUSBDeviceInterface197 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID197 +#define DeviceVersion 197 + +extern "C" { +typedef struct usb_dev_handle { + int fd; + + struct usb_bus *bus; + struct usb_device *device; + + int config; + int interface; + int altsetting; + + /* Added by RMT so implementations can store other per-open-device data */ + void *impl_info; +} usb_dev_handle; + +/* Darwin/OS X impl does not use fd field, instead it uses this */ +typedef struct darwin_dev_handle { + usb_device_t** device; + usb_interface_t** interface; + int open; +} darwin_dev_handle; + +typedef IOReturn io_return_t; +typedef IOCFPlugInInterface *io_cf_plugin_ref_t; + +static int ep_to_pipeRef (darwin_dev_handle* device, int ep); +extern int usb_debug; +} + +class s_buffer +{ +private: + char* d_buffer; + UInt32 d_n_used, d_n_alloc; + +public: + inline s_buffer (UInt32 n_alloc = 0) { + d_n_used = 0; + d_n_alloc = n_alloc; + if (n_alloc) { + d_buffer = (char*) new char [n_alloc]; + } else { + d_buffer = 0; + } + }; + inline ~s_buffer () { + if (d_n_alloc) { + delete [] d_buffer; + } + }; + inline UInt32 n_used () { return (d_n_used); }; + inline void n_used (UInt32 bufLen) { + d_n_used = (bufLen > d_n_alloc) ? d_n_alloc : bufLen; }; + inline UInt32 n_alloc () { return (d_n_alloc); }; + void buffer (char* l_buffer, UInt32 bufLen) { + if (bufLen > d_n_alloc) { + fprintf (stderr, "s_buffer::set: Copying only allocated bytes.\n"); + bufLen = d_n_alloc; + } + if (!l_buffer) { + fprintf (stderr, "s_buffer::set: NULL buffer.\n"); + return; + } + bcopy (l_buffer, d_buffer, bufLen); + d_n_used = bufLen; + }; + inline char* buffer () { return (d_buffer); }; + inline void reset () { + bzero (d_buffer, d_n_alloc); + d_n_used = 0; + }; +}; + +typedef s_buffer* s_buffer_ptr; +typedef s_node* s_node_ptr; +typedef circular_linked_list* s_queue_ptr; +typedef s_both* s_both_ptr; + +/*! + * \brief darwin implementation of fusb_devhandle + * + * This is currently identical to the generic implementation + * and is intended as a starting point for whatever magic is + * required to make usb fly. + */ +class fusb_devhandle_darwin : public fusb_devhandle +{ +public: + // CREATORS + fusb_devhandle_darwin (usb_dev_handle* udh); + virtual ~fusb_devhandle_darwin (); + + // MANIPULATORS + virtual fusb_ephandle* make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); +}; + +/*! + * \brief darwin implementation of fusb_ephandle + * + * This is currently identical to the generic implementation + * and is intended as a starting point for whatever magic is + * required to make usb fly. + */ +class fusb_ephandle_darwin : public fusb_ephandle +{ +private: + fusb_devhandle_darwin* d_devhandle; + mld_thread_ptr d_runThread; + mld_mutex_ptr d_runThreadRunning; + + CFRunLoopRef d_CFRunLoopRef; + + static void write_completed (void* ret_io_size, + io_return_t result, + void* io_size); + static void read_completed (void* ret_io_size, + io_return_t result, + void* io_size); + static void run_thread (void* arg); + static void read_thread (void* arg); + + void read_issue (s_both_ptr l_both); + +public: + // variables, for now + UInt8 d_pipeRef, d_transferType; + usb_interface_t** d_interfaceRef; + usb_interface_t* d_interface; + s_queue_ptr d_queue; + circular_buffer* d_buffer; + UInt32 d_bufLenBytes; + mld_mutex_ptr d_readRunning; + mld_condition_ptr d_runBlock, d_readBlock; + +// CREATORS + + fusb_ephandle_darwin (fusb_devhandle_darwin *dh, int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle_darwin (); + +// MANIPULATORS + + virtual bool start (); //!< begin streaming i/o + virtual bool stop (); //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void* buffer, int nbytes); + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void* buffer, int nbytes); + + /* + * abort any pending IO transfers + */ + void abort (); + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion (); +}; + +#endif /* _FUSB_DARWIN_H_ */ diff --git a/usrp/host/lib/fusb_generic.cc b/usrp/host/lib/fusb_generic.cc new file mode 100644 index 00000000..00136322 --- /dev/null +++ b/usrp/host/lib/fusb_generic.cc @@ -0,0 +1,108 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + + +static const int USB_TIMEOUT = 1000; // in milliseconds + + +fusb_devhandle_generic::fusb_devhandle_generic (usb_dev_handle *udh) + : fusb_devhandle (udh) +{ + // that's it +} + +fusb_devhandle_generic::~fusb_devhandle_generic () +{ + // nop +} + +fusb_ephandle * +fusb_devhandle_generic::make_ephandle (int endpoint, bool input_p, + int block_size, int nblocks) +{ + return new fusb_ephandle_generic (this, endpoint, input_p, + block_size, nblocks); +} + +// ---------------------------------------------------------------- + +fusb_ephandle_generic::fusb_ephandle_generic (fusb_devhandle_generic *dh, + int endpoint, bool input_p, + int block_size, int nblocks) + : fusb_ephandle (endpoint, input_p, block_size, nblocks), + d_devhandle (dh) +{ + // that's it +} + +fusb_ephandle_generic::~fusb_ephandle_generic () +{ + // nop +} + +bool +fusb_ephandle_generic::start () +{ + d_started = true; + return true; +} + +bool +fusb_ephandle_generic::stop () +{ + d_started = false; + return true; +} + +int +fusb_ephandle_generic::write (const void *buffer, int nbytes) +{ + if (!d_started) // doesn't matter here, but keeps semantics constant + return -1; + + if (d_input_p) + return -1; + + return usb_bulk_write (d_devhandle->get_usb_dev_handle (), + d_endpoint, (char *) buffer, nbytes, USB_TIMEOUT); +} + +int +fusb_ephandle_generic::read (void *buffer, int nbytes) +{ + if (!d_started) // doesn't matter here, but keeps semantics constant + return -1; + + if (!d_input_p) + return -1; + + return usb_bulk_read (d_devhandle->get_usb_dev_handle (), + d_endpoint|USB_ENDPOINT_IN, (char *) buffer, nbytes, + USB_TIMEOUT); +} diff --git a/usrp/host/lib/fusb_generic.h b/usrp/host/lib/fusb_generic.h new file mode 100644 index 00000000..93ae77fd --- /dev/null +++ b/usrp/host/lib/fusb_generic.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _FUSB_GENERIC_H_ +#define _FUSB_GENERIC_H_ + +#include + +/*! + * \brief generic implementation of fusb_devhandle using only libusb + */ +class fusb_devhandle_generic : public fusb_devhandle +{ +public: + // CREATORS + fusb_devhandle_generic (usb_dev_handle *udh); + virtual ~fusb_devhandle_generic (); + + // MANIPULATORS + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); +}; + + +/*! + * \brief generic implementation of fusb_ephandle using only libusb + */ +class fusb_ephandle_generic : public fusb_ephandle +{ +private: + fusb_devhandle_generic *d_devhandle; + +public: + // CREATORS + fusb_ephandle_generic (fusb_devhandle_generic *dh, int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle_generic (); + + // MANIPULATORS + + virtual bool start (); //!< begin streaming i/o + virtual bool stop (); //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes); + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes); + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion () { }; +}; + +#endif /* _FUSB_GENERIC_H_ */ + diff --git a/usrp/host/lib/fusb_linux.cc b/usrp/host/lib/fusb_linux.cc new file mode 100644 index 00000000..2fe244f1 --- /dev/null +++ b/usrp/host/lib/fusb_linux.cc @@ -0,0 +1,684 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include // libusb header +#include +#include +#include // interface to kernel portion of user mode usb driver +#include +#include +#include +#include +#include +#include + +#define MINIMIZE_TX_BUFFERING 1 // must be defined to 0 or 1 + + +static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size(); // hard limit +static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE; +static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20); // 4 MB / endpoint + + +// Totally evil and fragile extraction of file descriptor from +// guts of libusb. They don't install usbi.h, which is what we'd need +// to do this nicely. +// +// FIXME if everything breaks someday in the future, look here... + +static int +fd_from_usb_dev_handle (usb_dev_handle *udh) +{ + return *((int *) udh); +} + +inline static void +urb_set_ephandle (usbdevfs_urb *urb, fusb_ephandle_linux *handle) +{ + urb->usercontext = handle; +} + +inline static fusb_ephandle_linux * +urb_get_ephandle (usbdevfs_urb *urb) +{ + return (fusb_ephandle_linux *) urb->usercontext; +} + +// ------------------------------------------------------------------------ +// USB request block (urb) allocation +// ------------------------------------------------------------------------ + +static usbdevfs_urb * +alloc_urb (fusb_ephandle_linux *self, int buffer_length, int endpoint, + bool input_p, unsigned char *write_buffer) +{ + usbdevfs_urb *urb = new usbdevfs_urb; + memset (urb, 0, sizeof (*urb)); + + urb->buffer_length = buffer_length; + + // We allocate dedicated memory only for input buffers. + // For output buffers we reuse the same buffer (the kernel + // copies the data at submital time) + + if (input_p) + urb->buffer = new unsigned char [buffer_length]; + else + urb->buffer = write_buffer; + + // init common values + + urb->type = USBDEVFS_URB_TYPE_BULK; + urb->endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0); + + // USBDEVFS_URB_QUEUE_BULK goes away in linux 2.5, but is needed if + // we are using a 2.4 usb-uhci host controller driver. This is + // unlikely since we're almost always going to be plugged into a + // high speed host controller (ehci) +#if 0 && defined (USBDEVFS_URB_QUEUE_BULK) + urb->flags = USBDEVFS_URB_QUEUE_BULK; +#endif + + urb->signr = 0; + urb_set_ephandle (urb, self); + + return urb; +} + +static void +free_urb (usbdevfs_urb *urb) +{ + // if this was an input urb, free the buffer + if (urb->endpoint & 0x80) + delete [] ((unsigned char *) urb->buffer); + + delete urb; +} + +// ------------------------------------------------------------------------ +// device handle +// ------------------------------------------------------------------------ + +fusb_devhandle_linux::fusb_devhandle_linux (usb_dev_handle *udh) + : fusb_devhandle (udh) +{ + // that's all +} + +fusb_devhandle_linux::~fusb_devhandle_linux () +{ + // if there are any pending requests, cancel them and free the urbs. + + std::list::reverse_iterator it; + + for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){ + _cancel_urb (*it); + free_urb (*it); + } +} + +fusb_ephandle * +fusb_devhandle_linux::make_ephandle (int endpoint, bool input_p, + int block_size, int nblocks) +{ + return new fusb_ephandle_linux (this, endpoint, input_p, + block_size, nblocks); +} + + +// Attempt to cancel all transactions associated with eph. + +void +fusb_devhandle_linux::_cancel_pending_rqsts (fusb_ephandle_linux *eph) +{ + std::list::reverse_iterator it; + + for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){ + if (urb_get_ephandle (*it) == eph) + _cancel_urb (*it); + } +} + +void +fusb_devhandle_linux::pending_add (usbdevfs_urb *urb) +{ + d_pending_rqsts.push_back (urb); +} + +usbdevfs_urb * +fusb_devhandle_linux::pending_get () +{ + if (d_pending_rqsts.empty ()) + return 0; + + usbdevfs_urb *urb = d_pending_rqsts.front (); + d_pending_rqsts.pop_front (); + return urb; +} + +bool +fusb_devhandle_linux::pending_remove (usbdevfs_urb *urb) +{ + std::list::iterator result = find (d_pending_rqsts.begin (), + d_pending_rqsts.end (), + urb); + if (result == d_pending_rqsts.end ()){ + fprintf (stderr, "fusb::pending_remove: failed to find urb in pending_rqsts: %p\n", urb); + return false; + } + d_pending_rqsts.erase (result); + return true; +} + +/* + * Submit the urb to the kernel. + * iff successful, the urb will be placed on the devhandle's pending list. + */ +bool +fusb_devhandle_linux::_submit_urb (usbdevfs_urb *urb) +{ + int ret; + + ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_SUBMITURB, urb); + if (ret < 0){ + perror ("fusb::_submit_urb"); + return false; + } + + pending_add (urb); + return true; +} + +/* + * Attempt to cancel the in pending or in-progress urb transaction. + * Return true iff transaction was sucessfully cancelled. + * + * Failure to cancel should not be considered a problem. This frequently + * occurs if the transaction has already completed in the kernel but hasn't + * yet been reaped by the user mode code. + * + * urbs which were cancelled have their status field set to -ENOENT when + * they are reaped. + */ +bool +fusb_devhandle_linux::_cancel_urb (usbdevfs_urb *urb) +{ + int ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_DISCARDURB, urb); + if (ret < 0){ + // perror ("fusb::_cancel_urb"); + return false; + } + return true; +} + +/* + * Check with the kernel and see if any of our outstanding requests + * have completed. For each completed transaction, remove it from the + * devhandle's pending list and append it to the completed list for + * the corresponding endpoint. + * + * If any transactions are reaped return true. + * + * If ok_to_block_p is true, then this will block until at least one + * transaction completes. + */ +bool +fusb_devhandle_linux::_reap (bool ok_to_block_p) +{ + int ret; + int nreaped = 0; + usbdevfs_urb *urb = 0; + + int fd = fd_from_usb_dev_handle (d_udh); + + // try to reap as many as possible without blocking... + + while ((ret = ioctl (fd, USBDEVFS_REAPURBNDELAY, &urb)) == 0){ + if (urb->status != 0 && urb->status != -ENOENT){ + fprintf (stderr, "_reap: usb->status = %d, actual_length = %5d\n", + urb->status, urb->actual_length); + } + pending_remove (urb); + urb_get_ephandle (urb)->completed_list_add (urb); + nreaped++; + } + + if (nreaped > 0) // if we got any, return w/o blocking + return true; + + if (!ok_to_block_p) + return false; + + ret = ioctl (fd, USBDEVFS_REAPURB, &urb); + if (ret < 0){ + perror ("fusb::_reap"); + return false; + } + + pending_remove (urb); + urb_get_ephandle (urb)->completed_list_add (urb); + return true; +} + +void +fusb_devhandle_linux::_wait_for_completion () +{ + while (!d_pending_rqsts.empty ()) + _reap (true); +} + // ------------------------------------------------------------------------ +// end point handle +// ------------------------------------------------------------------------ + +fusb_ephandle_linux::fusb_ephandle_linux (fusb_devhandle_linux *devhandle, + int endpoint, + bool input_p, + int block_size, int nblocks) + : fusb_ephandle (endpoint, input_p, block_size, nblocks), + d_devhandle (devhandle), + d_write_work_in_progress (0), d_write_buffer (0), + d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0) +{ + + if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE) + throw std::out_of_range ("fusb_ephandle_linux: block_size"); + + if (d_nblocks < 0) + throw std::out_of_range ("fusb_ephandle_linux: nblocks"); + + if (d_block_size == 0) + d_block_size = DEFAULT_BLOCK_SIZE; + + if (d_nblocks == 0) + d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size); + + if (!d_input_p) + if (!MINIMIZE_TX_BUFFERING) + d_write_buffer = new unsigned char [d_block_size]; + + if (0) + fprintf(stderr, "fusb_ephandle_linux::ctor: d_block_size = %d d_nblocks = %d\n", + d_block_size, d_nblocks); + + // allocate urbs + + for (int i = 0; i < d_nblocks; i++) + d_free_list.push_back (alloc_urb (this, d_block_size, d_endpoint, + d_input_p, d_write_buffer)); +} + +fusb_ephandle_linux::~fusb_ephandle_linux () +{ + stop (); + + usbdevfs_urb *urb; + + while ((urb = free_list_get ()) != 0) + free_urb (urb); + + while ((urb = completed_list_get ()) != 0) + free_urb (urb); + + if (d_write_work_in_progress) + free_urb (d_write_work_in_progress); + + delete [] d_write_buffer; + + if (d_read_work_in_progress) + free_urb (d_read_work_in_progress); +} + +// ---------------------------------------------------------------- + +bool +fusb_ephandle_linux::start () +{ + if (d_started) + return true; // already running + + d_started = true; + + if (d_input_p){ // fire off all the reads + usbdevfs_urb *urb; + + int nerrors = 0; + while ((urb = free_list_get ()) != 0 && nerrors < d_nblocks){ + if (!submit_urb (urb)) + nerrors++; + } + } + + return true; +} + +// +// kill all i/o in progress. +// kill any completed but unprocessed transactions. +// +bool +fusb_ephandle_linux::stop () +{ + if (!d_started) + return true; + + d_devhandle->_cancel_pending_rqsts (this); + d_devhandle->_reap (false); + + + usbdevfs_urb *urb; + while ((urb = completed_list_get ()) != 0) + free_list_add (urb); + + if (d_write_work_in_progress){ + free_list_add (d_write_work_in_progress); + d_write_work_in_progress = 0; + } + + if (d_read_work_in_progress){ + free_list_add (d_read_work_in_progress); + d_read_work_in_progress = 0; + d_read_buffer = 0; + d_read_buffer_end = 0; + } + + if (d_free_list.size () != (unsigned) d_nblocks) + fprintf (stderr, "d_free_list.size () = %d, d_nblocks = %d\n", + d_free_list.size (), d_nblocks); + + assert (d_free_list.size () == (unsigned) d_nblocks); + + d_started = false; + return true; +} + +// ---------------------------------------------------------------- +// routines for writing +// ---------------------------------------------------------------- + +#if (MINIMIZE_TX_BUFFERING) + +int +fusb_ephandle_linux::write(const void *buffer, int nbytes) +{ + if (!d_started) + return -1; + + if (d_input_p) + return -1; + + assert(nbytes % 512 == 0); + + unsigned char *src = (unsigned char *) buffer; + + int n = 0; + while (n < nbytes){ + + usbdevfs_urb *urb = get_write_work_in_progress(); + assert(urb->actual_length == 0); + int m = std::min(nbytes - n, MAX_BLOCK_SIZE); + urb->buffer = src; + urb->buffer_length = m; + + n += m; + src += m; + + if (!submit_urb(urb)) + return -1; + + d_write_work_in_progress = 0; + } + + return n; +} + +#else + +int +fusb_ephandle_linux::write (const void *buffer, int nbytes) +{ + if (!d_started) + return -1; + + if (d_input_p) + return -1; + + unsigned char *src = (unsigned char *) buffer; + + int n = 0; + while (n < nbytes){ + + usbdevfs_urb *urb = get_write_work_in_progress (); + unsigned char *dst = (unsigned char *) urb->buffer; + int m = std::min (nbytes - n, urb->buffer_length - urb->actual_length); + + memcpy (&dst[urb->actual_length], &src[n], m); + urb->actual_length += m; + n += m; + + if (urb->actual_length == urb->buffer_length){ + if (!submit_urb (urb)) + return -1; + d_write_work_in_progress = 0; + } + } + + return n; +} + +#endif + +usbdevfs_urb * +fusb_ephandle_linux::get_write_work_in_progress () +{ + // if we've already got some work in progress, return it + + if (d_write_work_in_progress) + return d_write_work_in_progress; + + while (1){ + + reap_complete_writes (); + + usbdevfs_urb *urb = free_list_get (); + + if (urb != 0){ + assert (urb->actual_length == 0); + d_write_work_in_progress = urb; + return urb; + } + + // The free list is empty. Tell the device handle to reap. + // Anything it reaps for us will end up on our completed list. + + d_devhandle->_reap (true); + } +} + +void +fusb_ephandle_linux::reap_complete_writes () +{ + // take a look at the completed_list and xfer to free list after + // checking for errors. + + usbdevfs_urb *urb; + + while ((urb = completed_list_get ()) != 0){ + + // Check for any errors or short writes that were reported in the urb. + // The kernel sets status, actual_length and error_count. + // error_count is only used for ISO xfers. + // status is 0 if successful, else is an errno kind of thing + + if (urb->status != 0){ + fprintf (stderr, "fusb: (status %d) %s\n", urb->status, strerror (-urb->status)); + } + else if (urb->actual_length != urb->buffer_length){ + fprintf (stderr, "fusb: short write xfer: %d != %d\n", + urb->actual_length, urb->buffer_length); + } + + free_list_add (urb); + } +} + +void +fusb_ephandle_linux::wait_for_completion () +{ + d_devhandle->_wait_for_completion (); +} + +// ---------------------------------------------------------------- +// routines for reading +// ---------------------------------------------------------------- + +int +fusb_ephandle_linux::read (void *buffer, int nbytes) +{ + if (!d_started) + return -1; + + if (!d_input_p) + return -1; + + unsigned char *dst = (unsigned char *) buffer; + + int n = 0; + while (n < nbytes){ + + if (d_read_buffer >= d_read_buffer_end) + if (!reload_read_buffer ()) + return -1; + + int m = std::min (nbytes - n, (int) (d_read_buffer_end - d_read_buffer)); + + memcpy (&dst[n], d_read_buffer, m); + d_read_buffer += m; + n += m; + } + + return n; +} + +bool +fusb_ephandle_linux::reload_read_buffer () +{ + assert (d_read_buffer >= d_read_buffer_end); + + usbdevfs_urb *urb; + + if (d_read_work_in_progress){ + // We're done with this urb. Fire off a read to refill it. + urb = d_read_work_in_progress; + d_read_work_in_progress = 0; + d_read_buffer = 0; + d_read_buffer_end = 0; + urb->actual_length = 0; + if (!submit_urb (urb)) + return false; + } + + while (1){ + + while ((urb = completed_list_get ()) == 0) + d_devhandle->_reap (true); + + // check result of completed read + + if (urb->status != 0){ + // We've got a problem. + // Report the problem and resubmit. + fprintf (stderr, "fusb: (rd status %d) %s\n", urb->status, strerror (-urb->status)); + urb->actual_length = 0; + if (!submit_urb (urb)) + return false; + + continue; + } + + // we've got a happy urb, full of data... + + d_read_work_in_progress = urb; + d_read_buffer = (unsigned char *) urb->buffer; + d_read_buffer_end = d_read_buffer + urb->actual_length; + + return true; + } +} + +// ---------------------------------------------------------------- + +void +fusb_ephandle_linux::free_list_add (usbdevfs_urb *urb) +{ + assert (urb_get_ephandle (urb) == this); + urb->actual_length = 0; + d_free_list.push_back (urb); +} + +usbdevfs_urb * +fusb_ephandle_linux::free_list_get () +{ + if (d_free_list.empty ()) + return 0; + + usbdevfs_urb *urb = d_free_list.front (); + d_free_list.pop_front (); + return urb; +} + +void +fusb_ephandle_linux::completed_list_add (usbdevfs_urb *urb) +{ + assert (urb_get_ephandle (urb) == this); + d_completed_list.push_back (urb); +} + +usbdevfs_urb * +fusb_ephandle_linux::completed_list_get () +{ + if (d_completed_list.empty ()) + return 0; + + usbdevfs_urb *urb = d_completed_list.front (); + d_completed_list.pop_front (); + return urb; +} + +/* + * Submit the urb. If successful the urb ends up on the devhandle's + * pending list, otherwise, it's back on our free list. + */ +bool +fusb_ephandle_linux::submit_urb (usbdevfs_urb *urb) +{ + if (!d_devhandle->_submit_urb (urb)){ // FIXME record the problem somewhere + fprintf (stderr, "_submit_urb failed\n"); + free_list_add (urb); + return false; + } + return true; +} diff --git a/usrp/host/lib/fusb_linux.h b/usrp/host/lib/fusb_linux.h new file mode 100644 index 00000000..9b709180 --- /dev/null +++ b/usrp/host/lib/fusb_linux.h @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Fast USB interface + +#ifndef _FUSB_LINUX_H_ +#define _FUSB_LINUX_H_ + +#include +#include + +struct usbdevfs_urb; +class fusb_ephandle_linux; + +/*! + * \brief linux specific implementation of fusb_devhandle using usbdevice_fs + */ +class fusb_devhandle_linux : public fusb_devhandle { +private: + std::list d_pending_rqsts; + + void pending_add (usbdevfs_urb *urb); + bool pending_remove (usbdevfs_urb *urb); + usbdevfs_urb * pending_get (); + + +public: + // CREATORS + fusb_devhandle_linux (usb_dev_handle *udh); + virtual ~fusb_devhandle_linux (); + + // MANIPULATORS + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + + // internal use only + bool _submit_urb (usbdevfs_urb *urb); + bool _cancel_urb (usbdevfs_urb *urb); + void _cancel_pending_rqsts (fusb_ephandle_linux *eph); + bool _reap (bool ok_to_block_p); + void _wait_for_completion (); +}; + + /*! + * \brief linux specific implementation of fusb_ephandle using usbdevice_fs + */ + +class fusb_ephandle_linux : public fusb_ephandle { +private: + fusb_devhandle_linux *d_devhandle; + std::list d_free_list; + std::list d_completed_list; + usbdevfs_urb *d_write_work_in_progress; + unsigned char *d_write_buffer; + usbdevfs_urb *d_read_work_in_progress; + unsigned char *d_read_buffer; + unsigned char *d_read_buffer_end; + + usbdevfs_urb *get_write_work_in_progress (); + void reap_complete_writes (); + bool reload_read_buffer (); + bool submit_urb (usbdevfs_urb *urb); + +public: + fusb_ephandle_linux (fusb_devhandle_linux *dh, int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle_linux (); + + virtual bool start (); //!< begin streaming i/o + virtual bool stop (); //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes); + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes); + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion (); + + // internal use only + void free_list_add (usbdevfs_urb *urb); + void completed_list_add (usbdevfs_urb *urb); + usbdevfs_urb *free_list_get (); // pop and return head of list or 0 + usbdevfs_urb *completed_list_get (); // pop and return head of list or 0 +}; + +#endif /* _FUSB_LINUX_H_ */ diff --git a/usrp/host/lib/fusb_sysconfig_darwin.cc b/usrp/host/lib/fusb_sysconfig_darwin.cc new file mode 100644 index 00000000..3a4fcf98 --- /dev/null +++ b/usrp/host/lib/fusb_sysconfig_darwin.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +static const int MAX_BLOCK_SIZE = 32 * 1024; // hard limit + +fusb_devhandle * +fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +{ + return new fusb_devhandle_darwin (udh); +} + +int fusb_sysconfig::max_block_size () +{ + return MAX_BLOCK_SIZE; +} diff --git a/usrp/host/lib/fusb_sysconfig_generic.cc b/usrp/host/lib/fusb_sysconfig_generic.cc new file mode 100644 index 00000000..6fa2e48b --- /dev/null +++ b/usrp/host/lib/fusb_sysconfig_generic.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit + +fusb_devhandle * +fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +{ + return new fusb_devhandle_generic (udh); +} + +int fusb_sysconfig::max_block_size () +{ + return MAX_BLOCK_SIZE; +} diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc new file mode 100644 index 00000000..f7fc5d63 --- /dev/null +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit + +fusb_devhandle * +fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +{ + return new fusb_devhandle_linux (udh); +} + +int fusb_sysconfig::max_block_size () +{ + return MAX_BLOCK_SIZE; +} diff --git a/usrp/host/lib/fusb_sysconfig_win32.cc b/usrp/host/lib/fusb_sysconfig_win32.cc new file mode 100644 index 00000000..b2b6cb14 --- /dev/null +++ b/usrp/host/lib/fusb_sysconfig_win32.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +static const int MAX_BLOCK_SIZE = 64 * 1024; // Windows kernel hard limit + +fusb_devhandle * +fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +{ + return new fusb_devhandle_win32 (udh); +} + +int fusb_sysconfig::max_block_size () +{ + return MAX_BLOCK_SIZE; +} diff --git a/usrp/host/lib/fusb_win32.cc b/usrp/host/lib/fusb_win32.cc new file mode 100644 index 00000000..494a6beb --- /dev/null +++ b/usrp/host/lib/fusb_win32.cc @@ -0,0 +1,265 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE; +static const int DEFAULT_BUFFER_SIZE = 16 * (1L << 20); // 16 MB / endpoint + + +static const int USB_TIMEOUT = 1000; // in milliseconds + + +fusb_devhandle_win32::fusb_devhandle_win32 (usb_dev_handle *udh) + : fusb_devhandle (udh) +{ + // that's it +} + +fusb_devhandle_win32::~fusb_devhandle_win32 () +{ + // nop +} + +fusb_ephandle * +fusb_devhandle_win32::make_ephandle (int endpoint, bool input_p, + int block_size, int nblocks) +{ + return new fusb_ephandle_win32 (this, endpoint, input_p, + block_size, nblocks); +} + +// ---------------------------------------------------------------- + +fusb_ephandle_win32::fusb_ephandle_win32 (fusb_devhandle_win32 *dh, + int endpoint, bool input_p, + int block_size, int nblocks) + : fusb_ephandle (endpoint, input_p, block_size, nblocks), + d_devhandle (dh), d_input_leftover(0),d_output_short(0) +{ + if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE) + throw std::out_of_range ("fusb_ephandle_win32: block_size"); + + if (d_nblocks < 0) + throw std::out_of_range ("fusb_ephandle_win32: nblocks"); + + if (d_block_size == 0) + d_block_size = DEFAULT_BLOCK_SIZE; + + if (d_nblocks == 0) + d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size); + + d_buffer = new char [d_block_size*d_nblocks]; + d_context = new void * [d_nblocks]; + + // allocate contexts + + usb_dev_handle *dev = dh->get_usb_dev_handle (); + int i; + + if (d_input_p) + endpoint |= USB_ENDPOINT_IN; + + for (i=0; i + +/*! + * \brief win32 implementation of fusb_devhandle using libusb-win32 + */ +class fusb_devhandle_win32 : public fusb_devhandle +{ +public: + // CREATORS + fusb_devhandle_win32 (usb_dev_handle *udh); + virtual ~fusb_devhandle_win32 (); + + // MANIPULATORS + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); +}; + + +/*! + * \brief win32 implementation of fusb_ephandle using libusb-win32 + */ +class fusb_ephandle_win32 : public fusb_ephandle +{ +private: + fusb_devhandle_win32 *d_devhandle; + + unsigned d_curr; + unsigned d_outstanding_write; + int d_output_short; + int d_input_leftover; + void ** d_context; + char * d_buffer; + +public: + // CREATORS + fusb_ephandle_win32 (fusb_devhandle_win32 *dh, int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle_win32 (); + + // MANIPULATORS + + virtual bool start (); //!< begin streaming i/o + virtual bool stop (); //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes); + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes); + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion (); +}; + +#endif /* _FUSB_WIN32_H_ */ + diff --git a/usrp/host/lib/gen-ratios b/usrp/host/lib/gen-ratios new file mode 100755 index 00000000..2250090d --- /dev/null +++ b/usrp/host/lib/gen-ratios @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- python -*- + +def how_good (x): + pof2 = [1,2,4,8,16] + if x in pof2: + return 0 + if x in map (lambda x: x+1, pof2): + return -10 + if x in map (lambda x: x-1, pof2): + return -5 + return -2 + + +def better (v1, v2): + return abs ((v1 & 0xf) - ((v1 >> 4) & 0xf)) < abs ((v2 & 0xf) - ((v2 >> 4) & 0xf)) + + +def foo (): + result = {} + for i in range (1,17): + for j in range (1,17): + i_goodness = how_good (i) + j_goodness = how_good (j) + goodness = i_goodness + j_goodness + v = ((i - 1) << 4) | (j - 1) + + key = i * j + prev = result.get (key, None) + # print "i=%3d j=%3d key=%3d good=%3d v=0x%02x prev=%s" % (i, j, key, goodness, v, prev) + + if not prev: + result[key] = (goodness, v) + elif goodness > prev[0]: + result[key] = (goodness, v) + elif goodness == prev[0] and better(v, prev[1]): + result[key] = (goodness, v) + + r = result.items () + r.sort () + for k, d in r: + print "(%3d, 0x%02x)" % (k, d[1]) + + + +foo () + + diff --git a/usrp/host/lib/gen_usrp_dbid.py b/usrp/host/lib/gen_usrp_dbid.py new file mode 100755 index 00000000..34a994f9 --- /dev/null +++ b/usrp/host/lib/gen_usrp_dbid.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python + +import sys +import os +import os.path +import re +from optparse import OptionParser + +def write_header(f, comment_char): + f.write(comment_char); f.write('\n') + f.write(comment_char); f.write(' Machine generated by gen_usrp_dbid.py from usrp_dbid.dat\n') + f.write(comment_char); f.write(' Do not edit by hand. All edits will be overwritten.\n') + f.write(comment_char); f.write('\n') + f.write('\n') + +def gen_dbid_py(r): + f = open('usrp_dbid.py', 'w') + comment_char = '#' + write_header(f, comment_char) + f.write(comment_char); f.write('\n') + f.write(comment_char); f.write(" USRP Daughterboard ID's\n") + f.write(comment_char); f.write('\n') + f.write('\n') + for x in r: + f.write('%-16s = %s\n' % (x[1], x[2])) + +def gen_dbid_h(r): + f = open('usrp_dbid.h', 'w') + comment_char = '//' + write_header(f, comment_char) + f.write(comment_char); f.write('\n') + f.write(comment_char); f.write(" USRP Daughterboard ID's\n") + f.write(comment_char); f.write('\n') + f.write('\n') + f.write('#ifndef INCLUDED_USRP_DBID_H\n') + f.write('#define INCLUDED_USRP_DBID_H\n') + f.write('\n') + for x in r: + f.write('#define %-25s %s\n' % ('USRP_DBID_' + x[1], x[2])) + f.write('\n') + f.write('#endif /* INCLUDED_USRP_DBID_H */\n') + +def gen_dbid_cc(r): + f = open('usrp_dbid.cc', 'w') + write_header(f, '//') + head = '''/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#define NELEM(x) sizeof(x)/sizeof(x[0]) + +static struct { + unsigned short dbid; + const char *name; +} dbid_map[] = { +''' + + tail = '''}; + +const std::string +usrp_dbid_to_string (int dbid) +{ + if (dbid == -1) + return ""; + + if (dbid == -2) + return ""; + + for (unsigned i = 0; i < NELEM (dbid_map); i++) + if (dbid == dbid_map[i].dbid) + return dbid_map[i].name; + + char tmp[64]; + snprintf (tmp, sizeof (tmp), "Unknown (0x%04x)", dbid); + return tmp; +} +''' + f.write(head) + for x in r: + f.write(' { %-27s "%s" },\n' % ( + 'USRP_DBID_' + x[1] + ',', x[0])) + f.write(tail) + +def gen_all(src_filename): + src_file = open(src_filename, 'r') + r = [] + for line in src_file: + line = line.strip() + line = re.sub(r'\s*#.*$','', line) + if len(line) == 0: + continue + mo = re.match('"([^"]+)"\s*(0x[0-9a-fA-F]+)', line) + if mo: + str_name = mo.group(1) + id_name = str_name.upper().replace(' ', '_') + id_val = mo.group(2) + r.append((str_name, id_name, id_val)) + #sys.stdout.write('%-16s\t%-16s\t%s\n' % ('"'+str_name+'"', id_name, id_val)) + + gen_dbid_h(r) + gen_dbid_py(r) + gen_dbid_cc(r) + + +def main(): + usage = "usage: %prog [options] usrp_dbid.dat" + parser = OptionParser(usage=usage) + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + sys.exit(1) + + gen_all(args[0]) + +if __name__ == '__main__': + main() diff --git a/usrp/host/lib/md5.c b/usrp/host/lib/md5.c new file mode 100644 index 00000000..9fbed5b3 --- /dev/null +++ b/usrp/host/lib/md5.c @@ -0,0 +1,452 @@ +/* md5.c - Functions to compute MD5 message digest of files or memory blocks + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995, 1996, 2001, 2003 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ulrich Drepper , 1995. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "md5.h" + +#include + +#include +#include + +// #include "unlocked-io.h" + +#ifdef _LIBC +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_read_ctx __md5_read_ctx +# define md5_stream __md5_stream +# define md5_buffer __md5_buffer +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + +#define BLOCKSIZE 4096 +/* Ensure that BLOCKSIZE is a multiple of 64. */ +#if BLOCKSIZE % 64 != 0 +/* FIXME-someday (soon?): use #error instead of this kludge. */ +"invalid BLOCKSIZE" +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (struct md5_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (FILE *stream, void *resblock) +{ + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + + if (sum == BLOCKSIZE) + break; + + if (n == 0) + { + /* Check for the error flag IFF N == 0, so that we don't + exit the loop after a partial read due to e.g., EAGAIN + or EWOULDBLOCK. */ + if (ferror (stream)) + return 1; + goto process_partial_block; + } + + /* We've read at least one byte, so ignore errors. But always + check for EOF, since feof may be true even though N > 0. + Otherwise, we could end up calling fread after EOF. */ + if (feof (stream)) + goto process_partial_block; + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + + process_partial_block:; + + /* Process any remaining bytes. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (const char *buffer, size_t len, void *resblock) +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) +# else +# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/usrp/host/lib/md5.h b/usrp/host/lib/md5.h new file mode 100644 index 00000000..2b336073 --- /dev/null +++ b/usrp/host/lib/md5.h @@ -0,0 +1,129 @@ +/* md5.h - Declaration of functions and data types used for MD5 sum + computing library functions. + Copyright (C) 1995, 1996, 1999, 2000, 2003 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include +#include + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + doing that would require that the configure script compile and *run* + the resulting executable. Locally running cross-compiled executables + is usually not possible. */ + +#ifdef _LIBC +# include +typedef uint32_t md5_uint32; +typedef uintptr_t md5_uintptr; +#else +# define UINT_MAX_32_BITS 4294967295U + +# if UINT_MAX == UINT_MAX_32_BITS + typedef unsigned int md5_uint32; +# else +# if USHRT_MAX == UINT_MAX_32_BITS + typedef unsigned short md5_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS + typedef unsigned long md5_uint32; +# else + /* The following line is intended to evoke an error. + Using #error is not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +# endif +/* We have to make a guess about the integer type equivalent in size + to pointers which should always be correct. */ +typedef unsigned long int md5_uintptr; +#endif + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128]; +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void md5_init_ctx (struct md5_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void md5_process_block (const void *buffer, size_t len, + struct md5_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int md5_stream (FILE *stream, void *resblock); + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *md5_buffer (const char *buffer, size_t len, void *resblock); + +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +#endif diff --git a/usrp/host/lib/mld_threads.h b/usrp/host/lib/mld_threads.h new file mode 100644 index 00000000..ae6253e6 --- /dev/null +++ b/usrp/host/lib/mld_threads.h @@ -0,0 +1,257 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio. + * + * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _INCLUDED_MLD_THREADS_H_ +#define _INCLUDED_MLD_THREADS_H_ + +/* classes which allow for either pthreads or omni_threads */ + +#ifdef _USE_OMNI_THREADS_ +#include +#else +#include +#endif + +#include + +#define __INLINE__ inline + +class mld_condition_t; + +class mld_mutex_t { +#ifdef _USE_OMNI_THREADS_ + typedef omni_mutex l_mutex, *l_mutex_ptr; +#else + typedef pthread_mutex_t l_mutex, *l_mutex_ptr; +#endif + + friend class mld_condition_t; + +private: + l_mutex_ptr d_mutex; + +protected: + inline l_mutex_ptr mutex () { return (d_mutex); }; + +public: + __INLINE__ mld_mutex_t () { +#ifdef _USE_OMNI_THREADS_ + d_mutex = new omni_mutex (); +#else + d_mutex = (l_mutex_ptr) new l_mutex; + int l_ret = pthread_mutex_init (d_mutex, NULL); + if (l_ret != 0) { + fprintf (stderr, "Error %d creating mutex.\n", l_ret); + throw std::runtime_error ("mld_mutex_t::mld_mutex_t()\n"); + } +#endif + }; + + __INLINE__ ~mld_mutex_t () { + unlock (); +#ifndef _USE_OMNI_THREADS_ + int l_ret = pthread_mutex_destroy (d_mutex); + if (l_ret != 0) { + fprintf (stderr, "mld_mutex_t::~mld_mutex_t(): " + "Error %d destroying mutex.\n", l_ret); + } +#endif + delete d_mutex; + d_mutex = NULL; + }; + + __INLINE__ void lock () { +#ifdef _USE_OMNI_THREADS_ + d_mutex->lock (); +#else + int l_ret = pthread_mutex_lock (d_mutex); + if (l_ret != 0) { + fprintf (stderr, "mld_mutex_t::lock(): " + "Error %d locking mutex.\n", l_ret); + } +#endif + }; + + __INLINE__ void unlock () { +#ifdef _USE_OMNI_THREADS_ + d_mutex->unlock (); +#else + int l_ret = pthread_mutex_unlock (d_mutex); + if (l_ret != 0) { + fprintf (stderr, "mld_mutex_t::unlock(): " + "Error %d locking mutex.\n", l_ret); + } +#endif + }; + + __INLINE__ bool trylock () { +#ifdef _USE_OMNI_THREADS_ + int l_ret = d_mutex->trylock (); +#else + int l_ret = pthread_mutex_unlock (d_mutex); +#endif + return (l_ret == 0 ? true : false); + }; + + inline void acquire () { lock(); }; + inline void release () { unlock(); }; + inline void wait () { lock(); }; + inline void post () { unlock(); }; +}; + +typedef mld_mutex_t mld_mutex, *mld_mutex_ptr; + +class mld_condition_t { +#ifdef _USE_OMNI_THREADS_ + typedef omni_condition l_condition, *l_condition_ptr; +#else + typedef pthread_cond_t l_condition, *l_condition_ptr; +#endif + +private: + l_condition_ptr d_condition; + mld_mutex_ptr d_mutex; + bool d_waiting; + +public: + __INLINE__ mld_condition_t () { + d_waiting = false; + d_mutex = new mld_mutex (); +#ifdef _USE_OMNI_THREADS_ + d_condition = new omni_condition (d_mutex->mutex ()); +#else + d_condition = (l_condition_ptr) new l_condition; + int l_ret = pthread_cond_init (d_condition, NULL); + if (l_ret != 0) { + fprintf (stderr, "Error %d creating condition.\n", l_ret); + throw std::runtime_error ("mld_condition_t::mld_condition_t()\n"); + } +#endif + }; + + __INLINE__ ~mld_condition_t () { + signal (); +#ifndef _USE_OMNI_THREADS_ + int l_ret = pthread_cond_destroy (d_condition); + if (l_ret != 0) { + fprintf (stderr, "mld_condition_t::mld_condition_t(): " + "Error %d destroying condition.\n", l_ret); + } +#endif + delete d_condition; + d_condition = NULL; + delete d_mutex; + d_mutex = NULL; + }; + + __INLINE__ void signal () { + if (d_waiting == true) { +#ifdef _USE_OMNI_THREADS_ + d_condition->signal (); +#else + int l_ret = pthread_cond_signal (d_condition); + if (l_ret != 0) { + fprintf (stderr, "mld_condition_t::signal(): " + "Error %d.\n", l_ret); + } +#endif + d_waiting = false; + } + }; + + __INLINE__ void wait () { + if (d_waiting == false) { + d_waiting = true; +#ifdef _USE_OMNI_THREADS_ + d_condition->wait (); +#else + int l_ret = pthread_cond_wait (d_condition, d_mutex->mutex ()); + if (l_ret != 0) { + fprintf (stderr, "mld_condition_t::wait(): " + "Error %d.\n", l_ret); + } +#endif + } + }; +}; + +typedef mld_condition_t mld_condition, *mld_condition_ptr; + +class mld_thread_t { +#ifdef _USE_OMNI_THREADS_ + typedef omni_thread l_thread, *l_thread_ptr; +#else + typedef pthread_t l_thread, *l_thread_ptr; +#endif + +private: +#ifndef _USE_OMNI_THREADS_ + l_thread d_thread; + void (*d_start_routine)(void*); + void *d_arg; +#else + l_thread_ptr d_thread; +#endif + +#ifndef _USE_OMNI_THREADS_ + static void* local_start_routine (void *arg) { + mld_thread_t* This = (mld_thread_t*) arg; + (*(This->d_start_routine))(This->d_arg); + return (NULL); + }; +#endif + +public: + __INLINE__ mld_thread_t (void (*start_routine)(void *), void *arg) { +#ifdef _USE_OMNI_THREADS_ + d_thread = new omni_thread (start_routine, arg); + d_thread->start (); +#else + d_start_routine = start_routine; + d_arg = arg; + int l_ret = pthread_create (&d_thread, NULL, local_start_routine, this); + if (l_ret != 0) { + fprintf (stderr, "Error %d creating thread.\n", l_ret); + throw std::runtime_error ("mld_thread_t::mld_thread_t()\n"); + } +#endif + }; + + __INLINE__ ~mld_thread_t () { +#ifdef _USE_OMNI_THREADS_ +// delete d_thread; + d_thread = NULL; +#else + int l_ret = pthread_detach (d_thread); + if (l_ret != 0) { + fprintf (stderr, "Error %d detaching thread.\n", l_ret); + throw std::runtime_error ("mld_thread_t::~mld_thread_t()\n"); + } +#endif + }; +}; + +typedef mld_thread_t mld_thread, *mld_thread_ptr; + +#endif /* _INCLUDED_MLD_THREADS_H_ */ diff --git a/usrp/host/lib/rate_to_regval.h b/usrp/host/lib/rate_to_regval.h new file mode 100644 index 00000000..1ffdc0f6 --- /dev/null +++ b/usrp/host/lib/rate_to_regval.h @@ -0,0 +1,97 @@ + { 1, 0x00 }, + { 2, 0x01 }, + { 3, 0x02 }, + { 4, 0x11 }, + { 5, 0x04 }, + { 6, 0x05 }, + { 7, 0x06 }, + { 8, 0x13 }, + { 9, 0x08 }, + { 10, 0x09 }, + { 11, 0x0a }, + { 12, 0x15 }, + { 13, 0x0c }, + { 14, 0x0d }, + { 15, 0x0e }, + { 16, 0x33 }, + { 18, 0x18 }, + { 20, 0x19 }, + { 21, 0x26 }, + { 22, 0x1a }, + { 24, 0x35 }, + { 25, 0x44 }, + { 26, 0x1c }, + { 27, 0x28 }, + { 28, 0x1d }, + { 30, 0x1e }, + { 32, 0x37 }, + { 33, 0x2a }, + { 35, 0x46 }, + { 36, 0x55 }, + { 39, 0x2c }, + { 40, 0x39 }, + { 42, 0x56 }, + { 44, 0x3a }, + { 45, 0x2e }, + { 48, 0x57 }, + { 49, 0x66 }, + { 50, 0x49 }, + { 52, 0x3c }, + { 54, 0x58 }, + { 55, 0x4a }, + { 56, 0x3d }, + { 60, 0x59 }, + { 63, 0x68 }, + { 64, 0x77 }, + { 65, 0x4c }, + { 66, 0x5a }, + { 70, 0x69 }, + { 72, 0x5b }, + { 75, 0x4e }, + { 77, 0x6a }, + { 78, 0x5c }, + { 80, 0x79 }, + { 81, 0x88 }, + { 84, 0x5d }, + { 88, 0x7a }, + { 90, 0x5e }, + { 91, 0x6c }, + { 96, 0x7b }, + { 98, 0x6d }, + { 99, 0x8a }, + { 100, 0x99 }, + { 104, 0x7c }, + { 105, 0x6e }, + { 108, 0x8b }, + { 110, 0x9a }, + { 112, 0x7d }, + { 117, 0x8c }, + { 120, 0x9b }, + { 121, 0xaa }, + { 126, 0x8d }, + { 128, 0x7f }, + { 130, 0x9c }, + { 132, 0xab }, + { 135, 0x8e }, + { 140, 0x9d }, + { 143, 0xac }, + { 144, 0xbb }, + { 150, 0x9e }, + { 154, 0xad }, + { 156, 0xbc }, + { 160, 0x9f }, + { 165, 0xae }, + { 168, 0xbd }, + { 169, 0xcc }, + { 176, 0xaf }, + { 180, 0xbe }, + { 182, 0xcd }, + { 192, 0xbf }, + { 195, 0xce }, + { 196, 0xdd }, + { 208, 0xcf }, + { 210, 0xde }, + { 224, 0xdf }, + { 225, 0xee }, + { 240, 0xef }, + { 256, 0xff } diff --git a/usrp/host/lib/std_paths.h.in b/usrp/host/lib/std_paths.h.in new file mode 100644 index 00000000..fe973e3c --- /dev/null +++ b/usrp/host/lib/std_paths.h.in @@ -0,0 +1,27 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +static char *std_paths[] = { + "@prefix@/share/usrp", + "/usr/local/share/usrp", + 0 +}; diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic.cc new file mode 100644 index 00000000..2029480a --- /dev/null +++ b/usrp/host/lib/usrp_basic.cc @@ -0,0 +1,1239 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp_basic.h" +#include "usrp_prims.h" +#include "usrp_interfaces.h" +#include "fpga_regs_common.h" +#include "fusb.h" +#include +#include +#include +#include +#include + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// These set the buffer size used for each end point using the fast +// usb interface. The kernel ends up locking down this much memory. + +static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB (was 8 MB) +//static const int FUSB_BUFFER_SIZE = 256 * (1L << 10); // 256 kB +static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; + + +static const double POLLING_INTERVAL = 0.1; // seconds + +//////////////////////////////////////////////////////////////// + +static struct usb_dev_handle * +open_rx_interface (struct usb_device *dev) +{ + struct usb_dev_handle *udh = usrp_open_rx_interface (dev); + if (udh == 0){ + fprintf (stderr, "usrp_basic_rx: can't open rx interface\n"); + usb_strerror (); + } + return udh; +} + +static struct usb_dev_handle * +open_tx_interface (struct usb_device *dev) +{ + struct usb_dev_handle *udh = usrp_open_tx_interface (dev); + if (udh == 0){ + fprintf (stderr, "usrp_basic_tx: can't open tx interface\n"); + usb_strerror (); + } + return udh; +} + + +////////////////////////////////////////////////////////////////// +// +// usrp_basic +// +//////////////////////////////////////////////////////////////// + + +// Given: +// CLKIN = 64 MHz +// CLKSEL pin = high +// +// These settings give us: +// CLKOUT1 = CLKIN = 64 MHz +// CLKOUT2 = CLKIN = 64 MHz +// ADC is clocked at 64 MHz +// DAC is clocked at 128 MHz + +static unsigned char common_regs[] = { + REG_GENERAL, 0, + REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC + | DLL_MULT_2X + | DLL_FAST), + REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, + REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 +}; + + +usrp_basic::usrp_basic (int which_board, + struct usb_dev_handle * + open_interface (struct usb_device *dev), + const std::string fpga_filename, + const std::string firmware_filename) + : d_udh (0), + d_usb_data_rate (16000000), // SWAG, see below + d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), + d_verbose (false) +{ + /* + * SWAG: Scientific Wild Ass Guess. + * + * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the + * actual rate. This doesn't change our throughput, that's determined by the signal + * processing code in the FPGA (which we know nothing about), and the system limits + * determined by libusb, fusb_*, and the underlying drivers. + */ + memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); + + usrp_one_time_init (); + + if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) + throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); + + struct usb_device *dev = usrp_find_device (which_board); + if (dev == 0){ + fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); + throw std::runtime_error ("usrp_basic/usrp_find_device"); + } + + if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ + fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); + throw std::runtime_error ("usrp_basic/bad_rev"); + } + + if ((d_udh = open_interface (dev)) == 0) + throw std::runtime_error ("usrp_basic/open_interface"); + + // initialize registers that are common to rx and tx + + if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ + fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); + throw std::runtime_error ("usrp_basic/init_9862"); + } + + _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode + _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs +} + +usrp_basic::~usrp_basic () +{ + if (d_udh) + usb_close (d_udh); +} + +bool +usrp_basic::start () +{ + return true; // nop +} + +bool +usrp_basic::stop () +{ + return true; // nop +} + +void +usrp_basic::set_usb_data_rate (int usb_data_rate) +{ + d_usb_data_rate = usb_data_rate; + d_bytes_per_poll = (int) (usb_data_rate * POLLING_INTERVAL); +} + +bool +usrp_basic::write_aux_dac (int slot, int which_dac, int value) +{ + return usrp_write_aux_dac (d_udh, slot, which_dac, value); +} + +bool +usrp_basic::read_aux_adc (int slot, int which_adc, int *value) +{ + return usrp_read_aux_adc (d_udh, slot, which_adc, value); +} + +int +usrp_basic::read_aux_adc (int slot, int which_adc) +{ + int value; + if (!read_aux_adc (slot, which_adc, &value)) + return READ_FAILED; + + return value; +} + +bool +usrp_basic::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) +{ + return usrp_eeprom_write (d_udh, i2c_addr, eeprom_offset, buf.data (), buf.size ()); +} + +std::string +usrp_basic::read_eeprom (int i2c_addr, int eeprom_offset, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_eeprom_read (d_udh, i2c_addr, eeprom_offset, buf, len)) + return ""; + + return std::string (buf, len); +} + +bool +usrp_basic::write_i2c (int i2c_addr, const std::string buf) +{ + return usrp_i2c_write (d_udh, i2c_addr, buf.data (), buf.size ()); +} + +std::string +usrp_basic::read_i2c (int i2c_addr, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_i2c_read (d_udh, i2c_addr, buf, len)) + return ""; + + return std::string (buf, len); +} + +std::string +usrp_basic::serial_number() +{ + return usrp_serial_number(d_udh); +} + +// ---------------------------------------------------------------- + +bool +usrp_basic::set_adc_offset (int which, int offset) +{ + if (which < 0 || which > 3) + return false; + + return _write_fpga_reg (FR_ADC_OFFSET_0 + which, offset); +} + +bool +usrp_basic::set_dac_offset (int which, int offset, int offset_pin) +{ + if (which < 0 || which > 3) + return false; + + int which_codec = which >> 1; + int tx_a = (which & 0x1) == 0; + int lo = ((offset & 0x3) << 6) | (offset_pin & 0x1); + int hi = (offset >> 2); + bool ok; + + if (tx_a){ + ok = _write_9862 (which_codec, REG_TX_A_OFFSET_LO, lo); + ok &= _write_9862 (which_codec, REG_TX_A_OFFSET_HI, hi); + } + else { + ok = _write_9862 (which_codec, REG_TX_B_OFFSET_LO, lo); + ok &= _write_9862 (which_codec, REG_TX_B_OFFSET_HI, hi); + } + return ok; +} + +bool +usrp_basic::set_adc_buffer_bypass (int which, bool bypass) +{ + if (which < 0 || which > 3) + return false; + + int codec = which >> 1; + int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B; + + unsigned char cur_rx; + unsigned char cur_pwr_dn; + + // If the input buffer is bypassed, we need to power it down too. + + bool ok = _read_9862 (codec, reg, &cur_rx); + ok &= _read_9862 (codec, REG_RX_PWR_DN, &cur_pwr_dn); + if (!ok) + return false; + + if (bypass){ + cur_rx |= RX_X_BYPASS_INPUT_BUFFER; + cur_pwr_dn |= ((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B; + } + else { + cur_rx &= ~RX_X_BYPASS_INPUT_BUFFER; + cur_pwr_dn &= ~(((which & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B); + } + + ok &= _write_9862 (codec, reg, cur_rx); + ok &= _write_9862 (codec, REG_RX_PWR_DN, cur_pwr_dn); + return ok; +} + +// ---------------------------------------------------------------- + +bool +usrp_basic::_write_fpga_reg (int regno, int value) +{ + if (d_verbose){ + fprintf (stdout, "_write_fpga_reg(%3d, 0x%08x)\n", regno, value); + fflush (stdout); + } + + if (regno >= 0 && regno < MAX_REGS) + d_fpga_shadows[regno] = value; + + return usrp_write_fpga_reg (d_udh, regno, value); +} + +bool +usrp_basic::_write_fpga_reg_masked (int regno, int value, int mask) +{ + //Only use this for registers who actually use a mask in the verilog firmware, like FR_RX_MASTER_SLAVE + //value is a 16 bits value and mask is a 16 bits mask + if (d_verbose){ + fprintf (stdout, "_write_fpga_reg_masked(%3d, 0x%04x,0x%04x)\n", regno, value, mask); + fflush (stdout); + } + + if (regno >= 0 && regno < MAX_REGS) + d_fpga_shadows[regno] = value; + + return usrp_write_fpga_reg (d_udh, regno, (value & 0xffff) | ((mask & 0xffff)<<16)); +} + + +bool +usrp_basic::_read_fpga_reg (int regno, int *value) +{ + return usrp_read_fpga_reg (d_udh, regno, value); +} + +int +usrp_basic::_read_fpga_reg (int regno) +{ + int value; + if (!_read_fpga_reg (regno, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic::_write_9862 (int which_codec, int regno, unsigned char value) +{ + if (0 && d_verbose){ + // FIXME really want to enable logging in usrp_prims:usrp_9862_write + fprintf(stdout, "_write_9862(codec = %d, regno = %2d, val = 0x%02x)\n", which_codec, regno, value); + fflush(stdout); + } + + return usrp_9862_write (d_udh, which_codec, regno, value); +} + + +bool +usrp_basic::_read_9862 (int which_codec, int regno, unsigned char *value) const +{ + return usrp_9862_read (d_udh, which_codec, regno, value); +} + +int +usrp_basic::_read_9862 (int which_codec, int regno) const +{ + unsigned char value; + if (!_read_9862 (which_codec, regno, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic::_write_spi (int optional_header, int enables, int format, std::string buf) +{ + return usrp_spi_write (d_udh, optional_header, enables, format, + buf.data(), buf.size()); +} + +std::string +usrp_basic::_read_spi (int optional_header, int enables, int format, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len)) + return ""; + + return std::string (buf, len); +} + + +bool +usrp_basic::_set_led (int which, bool on) +{ + return usrp_set_led (d_udh, which, on); +} + +//////////////////////////////////////////////////////////////// +// +// usrp_basic_rx +// +//////////////////////////////////////////////////////////////// + +static unsigned char rx_init_regs[] = { + REG_RX_PWR_DN, 0, + REG_RX_A, 0, // minimum gain = 0x00 (max gain = 0x14) + REG_RX_B, 0, // minimum gain = 0x00 (max gain = 0x14) + REG_RX_MISC, (RX_MISC_HS_DUTY_CYCLE | RX_MISC_CLK_DUTY), + REG_RX_IF, (RX_IF_USE_CLKOUT1 + | RX_IF_2S_COMP), + REG_RX_DIGITAL, (RX_DIGITAL_2_CHAN) +}; + + +usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) + : usrp_basic (which_board, open_rx_interface, fpga_filename, firmware_filename), + d_devhandle (0), d_ephandle (0), + d_bytes_seen (0), d_first_read (true), + d_rx_enable (false) +{ + // initialize rx specific registers + + if (!usrp_9862_write_many_all (d_udh, rx_init_regs, sizeof (rx_init_regs))){ + fprintf (stderr, "usrp_basic_rx: failed to init AD9862 RX regs\n"); + throw std::runtime_error ("usrp_basic_rx/init_9862"); + } + + if (0){ + // FIXME power down 2nd codec rx path + usrp_9862_write (d_udh, 1, REG_RX_PWR_DN, 0x1); // power down everything + } + + // Reset the rx path and leave it disabled. + set_rx_enable (false); + usrp_set_fpga_rx_reset (d_udh, true); + usrp_set_fpga_rx_reset (d_udh, false); + + set_fpga_rx_sample_rate_divisor (2); // usually correct + + set_dc_offset_cl_enable(0xf, 0xf); // enable DC offset removal control loops + + probe_rx_slots (false); + + // check fusb buffering parameters + + if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); + + if (fusb_nblocks < 0) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); + + if (fusb_block_size == 0) + fusb_block_size = FUSB_BLOCK_SIZE; + + if (fusb_nblocks == 0) + fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); + + d_devhandle = fusb_sysconfig::make_devhandle (d_udh); + d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true, + fusb_block_size, fusb_nblocks); + + _write_fpga_reg(FR_ATR_MASK_1, 0); // zero Rx side Auto Transmit/Receive regs + _write_fpga_reg(FR_ATR_TXVAL_1, 0); + _write_fpga_reg(FR_ATR_RXVAL_1, 0); + _write_fpga_reg(FR_ATR_MASK_3, 0); + _write_fpga_reg(FR_ATR_TXVAL_3, 0); + _write_fpga_reg(FR_ATR_RXVAL_3, 0); +} + +static unsigned char rx_fini_regs[] = { + REG_RX_PWR_DN, 0x1 // power down everything +}; + +usrp_basic_rx::~usrp_basic_rx () +{ + if (!set_rx_enable (false)){ + fprintf (stderr, "usrp_basic_rx: set_fpga_rx_enable failed\n"); + usb_strerror (); + } + + d_ephandle->stop (); + delete d_ephandle; + delete d_devhandle; + + if (!usrp_9862_write_many_all (d_udh, rx_fini_regs, sizeof (rx_fini_regs))){ + fprintf (stderr, "usrp_basic_rx: failed to fini AD9862 RX regs\n"); + } +} + + +bool +usrp_basic_rx::start () +{ + if (!usrp_basic::start ()) // invoke parent's method + return false; + + // fire off reads before asserting rx_enable + + if (!d_ephandle->start ()){ + fprintf (stderr, "usrp_basic_rx: failed to start end point streaming"); + usb_strerror (); + return false; + } + + if (!set_rx_enable (true)){ + fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n"); + usb_strerror (); + return false; + } + + return true; +} + +bool +usrp_basic_rx::stop () +{ + bool ok = usrp_basic::stop(); + + if (!d_ephandle->stop()){ + fprintf (stderr, "usrp_basic_rx: failed to stop end point streaming"); + usb_strerror (); + ok = false; + } + if (!set_rx_enable(false)){ + fprintf (stderr, "usrp_basic_rx: set_rx_enable(false) failed\n"); + usb_strerror (); + ok = false; + } + return false; +} + +usrp_basic_rx * +usrp_basic_rx::make (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename) +{ + usrp_basic_rx *u = 0; + + try { + u = new usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename); + return u; + } + catch (...){ + delete u; + return 0; + } + + return u; +} + +bool +usrp_basic_rx::set_fpga_rx_sample_rate_divisor (unsigned int div) +{ + return _write_fpga_reg (FR_RX_SAMPLE_RATE_DIV, div - 1); +} + + +/* + * \brief read data from the D/A's via the FPGA. + * \p len must be a multiple of 512 bytes. + * + * \returns the number of bytes read, or -1 on error. + * + * If overrun is non-NULL it will be set true iff an RX overrun is detected. + */ +int +usrp_basic_rx::read (void *buf, int len, bool *overrun) +{ + int r; + + if (overrun) + *overrun = false; + + if (len < 0 || (len % 512) != 0){ + fprintf (stderr, "usrp_basic_rx::read: invalid length = %d\n", len); + return -1; + } + + r = d_ephandle->read (buf, len); + if (r > 0) + d_bytes_seen += r; + + /* + * In many cases, the FPGA reports an rx overrun right after we + * enable the Rx path. If this is our first read, check for the + * overrun to clear the condition, then ignore the result. + */ + if (0 && d_first_read){ // FIXME + d_first_read = false; + bool bogus_overrun; + usrp_check_rx_overrun (d_udh, &bogus_overrun); + } + + if (overrun != 0 && d_bytes_seen >= d_bytes_per_poll){ + d_bytes_seen = 0; + if (!usrp_check_rx_overrun (d_udh, overrun)){ + fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n"); + usb_strerror (); + } + } + + return r; +} + +bool +usrp_basic_rx::set_rx_enable (bool on) +{ + d_rx_enable = on; + return usrp_set_fpga_rx_enable (d_udh, on); +} + +// conditional disable, return prev state +bool +usrp_basic_rx::disable_rx () +{ + bool enabled = rx_enable (); + if (enabled) + set_rx_enable (false); + return enabled; +} + +// conditional set +void +usrp_basic_rx::restore_rx (bool on) +{ + if (on != rx_enable ()) + set_rx_enable (on); +} + +bool +usrp_basic_rx::set_pga (int which, double gain) +{ + if (which < 0 || which > 3) + return false; + + gain = std::max (pga_min (), gain); + gain = std::min (pga_max (), gain); + + int codec = which >> 1; + int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B; + + // read current value to get input buffer bypass flag. + unsigned char cur_rx; + if (!_read_9862 (codec, reg, &cur_rx)) + return false; + + int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step()); + + cur_rx = (cur_rx & RX_X_BYPASS_INPUT_BUFFER) | (int_gain & 0x7f); + return _write_9862 (codec, reg, cur_rx); +} + +double +usrp_basic_rx::pga (int which) const +{ + if (which < 0 || which > 3) + return READ_FAILED; + + int codec = which >> 1; + int reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B; + unsigned char v; + bool ok = _read_9862 (codec, reg, &v); + if (!ok) + return READ_FAILED; + + return (pga_db_per_step() * (v & 0x1f)) + pga_min(); +} + +static int +slot_id_to_oe_reg (int slot_id) +{ + static int reg[4] = { FR_OE_0, FR_OE_1, FR_OE_2, FR_OE_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +slot_id_to_io_reg (int slot_id) +{ + static int reg[4] = { FR_IO_0, FR_IO_1, FR_IO_2, FR_IO_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +void +usrp_basic_rx::probe_rx_slots (bool verbose) +{ + struct usrp_dboard_eeprom eeprom; + static int slot_id_map[2] = { SLOT_RX_A, SLOT_RX_B }; + static const char *slot_name[2] = { "RX d'board A", "RX d'board B" }; + + for (int i = 0; i < 2; i++){ + int slot_id = slot_id_map [i]; + const char *msg = 0; + usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); + + switch (s){ + case UDBE_OK: + d_dbid[i] = eeprom.id; + msg = usrp_dbid_to_string (eeprom.id).c_str (); + set_adc_offset (2*i+0, eeprom.offset[0]); + set_adc_offset (2*i+1, eeprom.offset[1]); + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_NO_EEPROM: + d_dbid[i] = -1; + msg = ""; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_INVALID_EEPROM: + d_dbid[i] = -2; + msg = "Invalid EEPROM contents"; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_BAD_SLOT: + default: + assert (0); + } + + if (verbose){ + fflush (stdout); + fprintf (stderr, "%s: %s\n", slot_name[i], msg); + } + } +} + +bool +usrp_basic_rx::_write_oe (int which_dboard, int value, int mask) +{ + if (! (0 <= which_dboard && which_dboard <= 1)) + return false; + + return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)), + (mask << 16) | (value & 0xffff)); +} + +bool +usrp_basic_rx::write_io (int which_dboard, int value, int mask) +{ + if (! (0 <= which_dboard && which_dboard <= 1)) + return false; + + return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)), + (mask << 16) | (value & 0xffff)); +} + +bool +usrp_basic_rx::read_io (int which_dboard, int *value) +{ + if (! (0 <= which_dboard && which_dboard <= 1)) + return false; + + int t; + int reg = which_dboard + 1; // FIXME, *very* magic number (fix in serial_io.v) + bool ok = _read_fpga_reg (reg, &t); + if (!ok) + return false; + + *value = (t >> 16) & 0xffff; // FIXME, more magic + return true; +} + +int +usrp_basic_rx::read_io (int which_dboard) +{ + int value; + if (!read_io (which_dboard, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic_rx::write_aux_dac (int which_dboard, int which_dac, int value) +{ + return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard), + which_dac, value); +} + +bool +usrp_basic_rx::read_aux_adc (int which_dboard, int which_adc, int *value) +{ + return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), + which_adc, value); +} + +int +usrp_basic_rx::read_aux_adc (int which_dboard, int which_adc) +{ + return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc); +} + +int +usrp_basic_rx::block_size () const { return d_ephandle->block_size(); } + +bool +usrp_basic_rx::set_dc_offset_cl_enable(int bits, int mask) +{ + return _write_fpga_reg(FR_DC_OFFSET_CL_EN, + (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask)); +} + +//////////////////////////////////////////////////////////////// +// +// usrp_basic_tx +// +//////////////////////////////////////////////////////////////// + + +// +// DAC input rate 64 MHz interleaved for a total input rate of 128 MHz +// DAC input is latched on rising edge of CLKOUT2 +// NCO is disabled +// interpolate 2x +// coarse modulator disabled +// + +static unsigned char tx_init_regs[] = { + REG_TX_PWR_DN, 0, + REG_TX_A_OFFSET_LO, 0, + REG_TX_A_OFFSET_HI, 0, + REG_TX_B_OFFSET_LO, 0, + REG_TX_B_OFFSET_HI, 0, + REG_TX_A_GAIN, (TX_X_GAIN_COARSE_FULL | 0), + REG_TX_B_GAIN, (TX_X_GAIN_COARSE_FULL | 0), + REG_TX_PGA, 0xff, // maximum gain (0 dB) + REG_TX_MISC, 0, + REG_TX_IF, (TX_IF_USE_CLKOUT1 + | TX_IF_I_FIRST + | TX_IF_INV_TX_SYNC + | TX_IF_2S_COMP + | TX_IF_INTERLEAVED), + REG_TX_DIGITAL, (TX_DIGITAL_2_DATA_PATHS + | TX_DIGITAL_INTERPOLATE_4X), + REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO + | TX_MODULATOR_COARSE_MODULATION_NONE), + REG_TX_NCO_FTW_7_0, 0, + REG_TX_NCO_FTW_15_8, 0, + REG_TX_NCO_FTW_23_16, 0 +}; + +usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename) + : usrp_basic (which_board, open_tx_interface, fpga_filename, firmware_filename), + d_devhandle (0), d_ephandle (0), + d_bytes_seen (0), d_first_write (true), + d_tx_enable (false) +{ + if (!usrp_9862_write_many_all (d_udh, tx_init_regs, sizeof (tx_init_regs))){ + fprintf (stderr, "usrp_basic_tx: failed to init AD9862 TX regs\n"); + throw std::runtime_error ("usrp_basic_tx/init_9862"); + } + + if (0){ + // FIXME power down 2nd codec tx path + usrp_9862_write (d_udh, 1, REG_TX_PWR_DN, + (TX_PWR_DN_TX_DIGITAL + | TX_PWR_DN_TX_ANALOG_BOTH)); + } + + // Reset the tx path and leave it disabled. + set_tx_enable (false); + usrp_set_fpga_tx_reset (d_udh, true); + usrp_set_fpga_tx_reset (d_udh, false); + + set_fpga_tx_sample_rate_divisor (4); // we're using interp x4 + + probe_tx_slots (false); + + // check fusb buffering parameters + + if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); + + if (fusb_nblocks < 0) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); + + if (fusb_block_size == 0) + fusb_block_size = FUSB_BLOCK_SIZE; + + if (fusb_nblocks == 0) + fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); + + d_devhandle = fusb_sysconfig::make_devhandle (d_udh); + d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false, + fusb_block_size, fusb_nblocks); + + _write_fpga_reg(FR_ATR_MASK_0, 0); // zero Tx side Auto Transmit/Receive regs + _write_fpga_reg(FR_ATR_TXVAL_0, 0); + _write_fpga_reg(FR_ATR_RXVAL_0, 0); + _write_fpga_reg(FR_ATR_MASK_2, 0); + _write_fpga_reg(FR_ATR_TXVAL_2, 0); + _write_fpga_reg(FR_ATR_RXVAL_2, 0); +} + + +static unsigned char tx_fini_regs[] = { + REG_TX_PWR_DN, (TX_PWR_DN_TX_DIGITAL + | TX_PWR_DN_TX_ANALOG_BOTH), + REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO + | TX_MODULATOR_COARSE_MODULATION_NONE) +}; + +usrp_basic_tx::~usrp_basic_tx () +{ + d_ephandle->stop (); + delete d_ephandle; + delete d_devhandle; + + if (!usrp_9862_write_many_all (d_udh, tx_fini_regs, sizeof (tx_fini_regs))){ + fprintf (stderr, "usrp_basic_tx: failed to fini AD9862 TX regs\n"); + } +} + +bool +usrp_basic_tx::start () +{ + if (!usrp_basic::start ()) + return false; + + if (!set_tx_enable (true)){ + fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n"); + usb_strerror (); + return false; + } + + if (!d_ephandle->start ()){ + fprintf (stderr, "usrp_basic_tx: failed to start end point streaming"); + usb_strerror (); + return false; + } + + return true; +} + +bool +usrp_basic_tx::stop () +{ + bool ok = usrp_basic::stop (); + + if (!set_tx_enable (false)){ + fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n"); + usb_strerror (); + ok = false; + } + if (!d_ephandle->stop ()){ + fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming"); + usb_strerror (); + ok = false; + } + return ok; +} + +usrp_basic_tx * +usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename) +{ + usrp_basic_tx *u = 0; + + try { + u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename); + return u; + } + catch (...){ + delete u; + return 0; + } + + return u; +} + +bool +usrp_basic_tx::set_fpga_tx_sample_rate_divisor (unsigned int div) +{ + return _write_fpga_reg (FR_TX_SAMPLE_RATE_DIV, div - 1); +} + +/*! + * \brief Write data to the A/D's via the FPGA. + * + * \p len must be a multiple of 512 bytes. + * \returns number of bytes written or -1 on error. + * + * if \p underrun is non-NULL, it will be set to true iff + * a transmit underrun condition is detected. + */ +int +usrp_basic_tx::write (const void *buf, int len, bool *underrun) +{ + int r; + + if (underrun) + *underrun = false; + + if (len < 0 || (len % 512) != 0){ + fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len); + return -1; + } + + r = d_ephandle->write (buf, len); + if (r > 0) + d_bytes_seen += r; + + /* + * In many cases, the FPGA reports an tx underrun right after we + * enable the Tx path. If this is our first write, check for the + * underrun to clear the condition, then ignore the result. + */ + if (d_first_write && d_bytes_seen >= 4 * FUSB_BLOCK_SIZE){ + d_first_write = false; + bool bogus_underrun; + usrp_check_tx_underrun (d_udh, &bogus_underrun); + } + + if (underrun != 0 && d_bytes_seen >= d_bytes_per_poll){ + d_bytes_seen = 0; + if (!usrp_check_tx_underrun (d_udh, underrun)){ + fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n"); + usb_strerror (); + } + } + + return r; +} + +void +usrp_basic_tx::wait_for_completion () +{ + d_ephandle->wait_for_completion (); +} + +bool +usrp_basic_tx::set_tx_enable (bool on) +{ + d_tx_enable = on; + // fprintf (stderr, "set_tx_enable %d\n", on); + return usrp_set_fpga_tx_enable (d_udh, on); +} + +// conditional disable, return prev state +bool +usrp_basic_tx::disable_tx () +{ + bool enabled = tx_enable (); + if (enabled) + set_tx_enable (false); + return enabled; +} + +// conditional set +void +usrp_basic_tx::restore_tx (bool on) +{ + if (on != tx_enable ()) + set_tx_enable (on); +} + +bool +usrp_basic_tx::set_pga (int which, double gain) +{ + if (which < 0 || which > 3) + return false; + + gain = std::max (pga_min (), gain); + gain = std::min (pga_max (), gain); + + int codec = which >> 1; // 0 and 1 are same, as are 2 and 3 + + int int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step()); + + return _write_9862 (codec, REG_TX_PGA, int_gain); +} + +double +usrp_basic_tx::pga (int which) const +{ + if (which < 0 || which > 3) + return READ_FAILED; + + int codec = which >> 1; + unsigned char v; + bool ok = _read_9862 (codec, REG_TX_PGA, &v); + if (!ok) + return READ_FAILED; + + return (pga_db_per_step() * v) + pga_min(); +} + +void +usrp_basic_tx::probe_tx_slots (bool verbose) +{ + struct usrp_dboard_eeprom eeprom; + static int slot_id_map[2] = { SLOT_TX_A, SLOT_TX_B }; + static const char *slot_name[2] = { "TX d'board A", "TX d'board B" }; + + for (int i = 0; i < 2; i++){ + int slot_id = slot_id_map [i]; + const char *msg = 0; + usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); + + switch (s){ + case UDBE_OK: + d_dbid[i] = eeprom.id; + msg = usrp_dbid_to_string (eeprom.id).c_str (); + // FIXME, figure out interpretation of dc offset for TX d'boards + // offset = (eeprom.offset[1] << 16) | (eeprom.offset[0] & 0xffff); + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_NO_EEPROM: + d_dbid[i] = -1; + msg = ""; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_INVALID_EEPROM: + d_dbid[i] = -2; + msg = "Invalid EEPROM contents"; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_BAD_SLOT: + default: + assert (0); + } + + if (verbose){ + fflush (stdout); + fprintf (stderr, "%s: %s\n", slot_name[i], msg); + } + } +} + +bool +usrp_basic_tx::_write_oe (int which_dboard, int value, int mask) +{ + if (! (0 <= which_dboard && which_dboard <= 1)) + return false; + + return _write_fpga_reg (slot_id_to_oe_reg (dboard_to_slot (which_dboard)), + (mask << 16) | (value & 0xffff)); +} + +bool +usrp_basic_tx::write_io (int which_dboard, int value, int mask) +{ + if (! (0 <= which_dboard && which_dboard <= 1)) + return false; + + return _write_fpga_reg (slot_id_to_io_reg (dboard_to_slot (which_dboard)), + (mask << 16) | (value & 0xffff)); +} + +bool +usrp_basic_tx::read_io (int which_dboard, int *value) +{ + if (! (0 <= which_dboard && which_dboard <= 1)) + return false; + + int t; + int reg = which_dboard + 1; // FIXME, *very* magic number (fix in serial_io.v) + bool ok = _read_fpga_reg (reg, &t); + if (!ok) + return false; + + *value = t & 0xffff; // FIXME, more magic + return true; +} + +int +usrp_basic_tx::read_io (int which_dboard) +{ + int value; + if (!read_io (which_dboard, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic_tx::write_aux_dac (int which_dboard, int which_dac, int value) +{ + return usrp_basic::write_aux_dac (dboard_to_slot (which_dboard), + which_dac, value); +} + +bool +usrp_basic_tx::read_aux_adc (int which_dboard, int which_adc, int *value) +{ + return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), + which_adc, value); +} + +int +usrp_basic_tx::read_aux_adc (int which_dboard, int which_adc) +{ + return usrp_basic::read_aux_adc (dboard_to_slot (which_dboard), which_adc); +} + +int +usrp_basic_tx::block_size () const { return d_ephandle->block_size(); } + diff --git a/usrp/host/lib/usrp_basic.h b/usrp/host/lib/usrp_basic.h new file mode 100644 index 00000000..df775c5e --- /dev/null +++ b/usrp/host/lib/usrp_basic.h @@ -0,0 +1,776 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * ---------------------------------------------------------------------- + * Mid level interface to the Universal Software Radio Peripheral (Rev 1) + * + * These classes implement the basic functionality for talking to the + * USRP. They try to be as independent of the signal processing code + * in FPGA as possible. They implement access to the low level + * peripherals on the board, provide a common way for reading and + * writing registers in the FPGA, and provide the high speed interface + * to streaming data across the USB. + * + * It is expected that subclasses will be derived that provide + * access to the functionality to a particular FPGA configuration. + * ---------------------------------------------------------------------- + */ + +#ifndef INCLUDED_USRP_BASIC_H +#define INCLUDED_USRP_BASIC_H + +#include +#include + +struct usb_dev_handle; +class fusb_devhandle; +class fusb_ephandle; + +/*! + * \brief base class for usrp operations + */ +class usrp_basic +{ +private: + // NOT IMPLEMENTED + usrp_basic (const usrp_basic &rhs); // no copy constructor + usrp_basic &operator= (const usrp_basic &rhs); // no assignment operator + + +protected: + struct usb_dev_handle *d_udh; + int d_usb_data_rate; // bytes/sec + int d_bytes_per_poll; // how often to poll for overruns + bool d_verbose; + + static const int MAX_REGS = 128; + unsigned int d_fpga_shadows[MAX_REGS]; + + usrp_basic (int which_board, + struct usb_dev_handle *open_interface (struct usb_device *dev), + const std::string fpga_filename = "", + const std::string firmware_filename = ""); + + /*! + * \brief advise usrp_basic of usb data rate (bytes/sec) + * + * N.B., this doesn't tweak any hardware. Derived classes + * should call this to inform us of the data rate whenever it's + * first set or if it changes. + * + * \param usb_data_rate bytes/sec + */ + void set_usb_data_rate (int usb_data_rate); + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param slot Which Tx or Rx slot to write. + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. + * \param which_dac [0,3] RX slots must use only 0 and 1. TX slots must use only 2 and 3. + * \param value [0,4095] + * \returns true iff successful + */ + bool write_aux_dac (int slot, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param slot 2-bit slot number. E.g., SLOT_TX_A + * \param which_adc [0,1] + * \param value return 12-bit value [0,4095] + * \returns true iff successful + */ + bool read_aux_adc (int slot, int which_adc, int *value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param slot 2-bit slot number. E.g., SLOT_TX_A + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + int read_aux_adc (int slot, int which_adc); + +public: + virtual ~usrp_basic (); + + /*! + * \brief return frequency of master oscillator on USRP + */ + long fpga_master_clock_freq () const { return 64000000; } + + /*! + * \returns usb data rate in bytes/sec + */ + int usb_data_rate () const { return d_usb_data_rate; } + + void set_verbose (bool on) { d_verbose = on; } + + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; + + /*! + * \brief Write EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin writing + * \param buf the data to write + * \returns true iff sucessful + */ + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); + + /*! + * \brief Read EEPROM on motherboard or any daughterboard. + * \param i2c_addr I2C bus address of EEPROM + * \param eeprom_offset byte offset in EEPROM to begin reading + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + */ + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + + /*! + * \brief Write to I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of of 64 bytes. + */ + bool write_i2c (int i2c_addr, const std::string buf); + + /*! + * \brief Read from I2C peripheral + * \param i2c_addr I2C bus address (7-bits) + * \param len number of bytes to read + * \returns the data read if successful, else a zero length string. + * Reads are limited to a maximum of 64 bytes. + */ + std::string read_i2c (int i2c_addr, int len); + + /*! + * \brief Set ADC offset correction + * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... + * \param offset 16-bit value to subtract from raw ADC input. + */ + bool set_adc_offset (int which, int offset); + + /*! + * \brief Set DAC offset correction + * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... + * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). + * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; + * If 1 offset applied to +ve differential pin. + */ + bool set_dac_offset (int which, int offset, int offset_pin); + + /*! + * \brief Control ADC input buffer + * \param which which ADC[0,3] + * \param bypass if non-zero, bypass input buffer and connect input + * directly to switched cap SHA input of RxPGA. + */ + bool set_adc_buffer_bypass (int which, bool bypass); + + + /*! + * \brief return the usrp's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + // ---------------------------------------------------------------- + // Low level implementation routines. + // You probably shouldn't be using these... + // + + bool _set_led (int which, bool on); + + /*! + * \brief Write FPGA register. + * \param regno 7-bit register number + * \param value 32-bit value + * \returns true iff successful + */ + bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value + + /*! + * \brief Read FPGA register. + * \param regno 7-bit register number + * \param value 32-bit value + * \returns true iff successful + */ + bool _read_fpga_reg (int regno, int *value); //< 7-bit regno, 32-bit value + + /*! + * \brief Read FPGA register. + * \param regno 7-bit register number + * \returns register value if successful, else READ_FAILED + */ + int _read_fpga_reg (int regno); + + + /*! + * \brief Write FPGA register with mask. + * \param regno 7-bit register number + * \param value 16-bit value + * \param mask 16-bit value + * \returns true if successful + * Only use this for registers who actually implement a mask in the verilog firmware, like FR_RX_MASTER_SLAVE + */ + bool _write_fpga_reg_masked (int regno, int value, int mask); + + /*! + * \brief Write AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \param value 8-bit value + * \returns true iff successful + */ + bool _write_9862 (int which_codec, int regno, unsigned char value); + + /*! + * \brief Read AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \param value 8-bit value + * \returns true iff successful + */ + bool _read_9862 (int which_codec, int regno, unsigned char *value) const; + + /*! + * \brief Read AD9862 register. + * \param which_codec 0 or 1 + * \param regno 6-bit register number + * \returns register value if successful, else READ_FAILED + */ + int _read_9862 (int which_codec, int regno) const; + + /*! + * \brief Write data to SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripherals to write. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param buf the data to write + * \returns true iff successful + * Writes are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they are + * written to the peripheral immediately prior to writing \p buf. + */ + bool _write_spi (int optional_header, int enables, int format, std::string buf); + + /* + * \brief Read data from SPI bus peripheral. + * + * \param optional_header 0,1 or 2 bytes to write before buf. + * \param enables bitmask of peripheral to read. See usrp_spi_defs.h + * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* + * \param len number of bytes to read. Must be in [0,64]. + * \returns the data read if sucessful, else a zero length string. + * + * Reads are limited to a maximum of 64 bytes. + * + * If \p format specifies that optional_header bytes are present, they + * are written to the peripheral first. Then \p len bytes are read from + * the peripheral and returned. + */ + std::string _read_spi (int optional_header, int enables, int format, int len); + + /*! + * \brief Start data transfers. + * Called in base class to derived class order. + */ + bool start (); + + /*! + * \brief Stop data transfers. + * Called in base class to derived class order. + */ + bool stop (); +}; + + /*! + * \brief class for accessing the receive side of the USRP + */ +class usrp_basic_rx : public usrp_basic +{ +private: + fusb_devhandle *d_devhandle; + fusb_ephandle *d_ephandle; + int d_bytes_seen; // how many bytes we've seen + bool d_first_read; + bool d_rx_enable; + +protected: + int d_dbid[2]; // Rx daughterboard ID's + + /*! + * \param which_board Which USRP board on usb (not particularly useful; use 0) + * \param fusb_block_size fast usb xfer block size. Must be a multiple of 512. + * Use zero for a reasonable default. + * \param fusb_nblocks number of fast usb URBs to allocate. Use zero for a reasonable default. + */ + usrp_basic_rx (int which_board, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); // throws if trouble + + bool set_rx_enable (bool on); + bool rx_enable () const { return d_rx_enable; } + + bool disable_rx (); // conditional disable, return prev state + void restore_rx (bool on); // conditional set + + void probe_rx_slots (bool verbose); + int dboard_to_slot (int dboard) { return (dboard << 1) | 1; } + +public: + ~usrp_basic_rx (); + + /*! + * \brief invokes constructor, returns instance or 0 if trouble + * + * \param which_board Which USRP board on usb (not particularly useful; use 0) + * \param fusb_block_size fast usb xfer block size. Must be a multiple of 512. + * Use zero for a reasonable default. + * \param fusb_nblocks number of fast usb URBs to allocate. Use zero for a reasonable default. + */ + static usrp_basic_rx *make (int which_board, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); + + // MANIPULATORS + + /*! + * \brief tell the fpga the rate rx samples are coming from the A/D's + * + * div = fpga_master_clock_freq () / sample_rate + * + * sample_rate is determined by a myriad of registers + * in the 9862. That's why you have to tell us, so + * we can tell the fpga. + */ + bool set_fpga_rx_sample_rate_divisor (unsigned int div); + + /*! + * \brief read data from the D/A's via the FPGA. + * \p len must be a multiple of 512 bytes. + * + * \returns the number of bytes read, or -1 on error. + * + * If overrun is non-NULL it will be set true iff an RX overrun is detected. + */ + int read (void *buf, int len, bool *overrun); + + // ACCESSORS + + //! sampling rate of A/D converter + virtual long converter_rate() const { return fpga_master_clock_freq(); } // 64M + long adc_rate() const { return converter_rate(); } + long adc_freq() const { return converter_rate(); } //!< deprecated method name + + /*! + * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. + * + * \param which_dboard [0,1] which Rx daughterboard + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; } + + // ---------------------------------------------------------------- + // routines for controlling the Programmable Gain Amplifier + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which A/D [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param which which A/D [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + double pga_min () const { return 0.0; } + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + double pga_max () const { return 20.0; } + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const { return 20.0 / 20; } + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + * + * Each d'board has 16-bits of general purpose i/o. + * Setting the bit makes it an output from the FPGA to the d'board. + * + * This register is initialized based on a value stored in the + * d'board EEPROM. In general, you shouldn't be using this routine + * without a very good reason. Using this method incorrectly will + * kill your USRP motherboard and/or daughterboard. + */ + bool _write_oe (int which_dboard, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool write_io (int which_dboard, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value output + */ + bool read_io (int which_dboard, int *value); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int read_io (int which_dboard); + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param which_dboard [0,1] which d'board + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. + * \param which_dac [2,3] TX slots must use only 2 and 3. + * \param value [0,4095] + * \returns true iff successful + */ + bool write_aux_dac (int which_board, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_dboard [0,1] which d'board + * \param which_adc [0,1] + * \param value return 12-bit value [0,4095] + * \returns true iff successful + */ + bool read_aux_adc (int which_dboard, int which_adc, int *value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_dboard [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + int read_aux_adc (int which_dboard, int which_adc); + + /*! + * \brief returns current fusb block size + */ + int block_size() const; + + /*! + * \brief Enable/disable automatic DC offset removal control loop in FPGA + * + * \param bits which control loops to enable + * \param mask which \p bits to pay attention to + * + * If the corresponding bit is set, enable the automatic DC + * offset correction control loop. + * + *
+   * The 4 low bits are significant:
+   *
+   *   ADC0 = (1 << 0)
+   *   ADC1 = (1 << 1)
+   *   ADC2 = (1 << 2)
+   *   ADC3 = (1 << 3)
+   * 
+ * + * By default the control loop is enabled on all ADC's. + */ + bool set_dc_offset_cl_enable(int bits, int mask); + + // called in base class to derived class order + bool start (); + bool stop (); +}; + + /*! + * \brief class for accessing the transmit side of the USRP + */ +class usrp_basic_tx : public usrp_basic +{ +private: + fusb_devhandle *d_devhandle; + fusb_ephandle *d_ephandle; + int d_bytes_seen; // how many bytes we've seen + bool d_first_write; + bool d_tx_enable; + + protected: + int d_dbid[2]; // Tx daughterboard ID's + + /*! + * \param which_board Which USRP board on usb (not particularly useful; use 0) + * \param fusb_block_size fast usb xfer block size. Must be a multiple of 512. + * Use zero for a reasonable default. + * \param fusb_nblocks number of fast usb URBs to allocate. Use zero for a reasonable default. + */ + usrp_basic_tx (int which_board, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); // throws if trouble + + bool set_tx_enable (bool on); + bool tx_enable () const { return d_tx_enable; } + + bool disable_tx (); // conditional disable, return prev state + void restore_tx (bool on); // conditional set + + void probe_tx_slots (bool verbose); + int dboard_to_slot (int dboard) { return (dboard << 1) | 0; } + +public: + + ~usrp_basic_tx (); + + /*! + * \brief invokes constructor, returns instance or 0 if trouble + * + * \param which_board Which USRP board on usb (not particularly useful; use 0) + * \param fusb_block_size fast usb xfer block size. Must be a multiple of 512. + * Use zero for a reasonable default. + * \param fusb_nblocks number of fast usb URBs to allocate. Use zero for a reasonable default. + */ + static usrp_basic_tx *make (int which_board, int fusb_block_size=0, int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); + + // MANIPULATORS + + /*! + * \brief tell the fpga the rate tx samples are going to the D/A's + * + * div = fpga_master_clock_freq () * 2 + * + * sample_rate is determined by a myriad of registers + * in the 9862. That's why you have to tell us, so + * we can tell the fpga. + */ + bool set_fpga_tx_sample_rate_divisor (unsigned int div); + + /*! + * \brief Write data to the A/D's via the FPGA. + * + * \p len must be a multiple of 512 bytes. + * \returns number of bytes written or -1 on error. + * + * if \p underrun is non-NULL, it will be set to true iff + * a transmit underrun condition is detected. + */ + int write (const void *buf, int len, bool *underrun); + + /* + * Block until all outstanding writes have completed. + * This is typically used to assist with benchmarking + */ + void wait_for_completion (); + + // ACCESSORS + + //! sampling rate of D/A converter + virtual long converter_rate() const { return fpga_master_clock_freq () * 2; } // 128M + long dac_rate() const { return converter_rate(); } + long dac_freq() const { return converter_rate(); } //!< deprecated method name + + /*! + * \brief Return daughterboard ID for given Tx daughterboard slot [0,1]. + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; } + + // ---------------------------------------------------------------- + // routines for controlling the Programmable Gain Amplifier + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which which D/A [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3. + * Setting DAC 0 affects DAC 1 and vice versa. Same with DAC 2 and DAC 3. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain in dB. + * + * \param which which D/A [0,3] + */ + double pga (int which) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + double pga_min () const { return -20.0; } + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + double pga_max () const { return 0.0; } + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const { return 20.0/255; } + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + * + * Each d'board has 16-bits of general purpose i/o. + * Setting the bit makes it an output from the FPGA to the d'board. + * + * This register is initialized based on a value stored in the + * d'board EEPROM. In general, you shouldn't be using this routine + * without a very good reason. Using this method incorrectly will + * kill your USRP motherboard and/or daughterboard. + */ + bool _write_oe (int which_dboard, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool write_io (int which_dboard, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \param value return value + */ + bool read_io (int which_dboard, int *value); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_dboard [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int read_io (int which_dboard); + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param which_dboard [0,1] which d'board + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. + * \param which_dac [2,3] TX slots must use only 2 and 3. + * \param value [0,4095] + * \returns true iff successful + */ + bool write_aux_dac (int which_board, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_dboard [0,1] which d'board + * \param which_adc [0,1] + * \param value return 12-bit value [0,4095] + * \returns true iff successful + */ + bool read_aux_adc (int which_dboard, int which_adc, int *value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_dboard [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + int read_aux_adc (int which_dboard, int which_adc); + + /*! + * \brief returns current fusb block size + */ + int block_size() const; + + // called in base class to derived class order + bool start (); + bool stop (); +}; + +#endif diff --git a/usrp/host/lib/usrp_bytesex.h b/usrp/host/lib/usrp_bytesex.h new file mode 100644 index 00000000..de34c053 --- /dev/null +++ b/usrp/host/lib/usrp_bytesex.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_USRP_BYTESEX_H +#define INCLUDED_USRP_BYTESEX_H + +/*! + * \brief routines for convertering between host and usrp byte order + * + * Prior to including this file, the user must include "config.h" + * which will or won't define WORDS_BIGENDIAN based on the + * result of the AC_C_BIGENDIAN autoconf test. + */ + +#ifdef HAVE_BYTESWAP_H +#include +#else +static inline unsigned short int +bswap_16 (unsigned short int x) +{ + return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)); +} +#endif + + +#ifdef WORDS_BIGENDIAN + +static inline short int +host_to_usrp_short (short int x) +{ + return bswap_16 (x); +} + +static inline short int +usrp_to_host_short (short int x) +{ + return bswap_16 (x); +} + +#else + +static inline short int +host_to_usrp_short (short int x) +{ + return x; +} + +static inline short int +usrp_to_host_short (unsigned short int x) +{ + return x; +} + +#endif + +#endif /* INCLUDED_USRP_BYTESEX_H */ diff --git a/usrp/host/lib/usrp_config.cc b/usrp/host/lib/usrp_config.cc new file mode 100644 index 00000000..04303cd8 --- /dev/null +++ b/usrp/host/lib/usrp_config.cc @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "usrp_config.h" + +int +usrp_rx_config_stream_count (unsigned int usrp_rx_config) +{ + return 1; +} + +int +usrp_tx_config_stream_count (unsigned int usrp_tx_config) +{ + return 1; +} diff --git a/usrp/host/lib/usrp_config.h b/usrp/host/lib/usrp_config.h new file mode 100644 index 00000000..3675a108 --- /dev/null +++ b/usrp/host/lib/usrp_config.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _USRP_CONFIG_H_ +#define _USRP_CONFIG_H_ + +/* + * ---------------------------------------------------------------- + * USRP Rx configurations. + * + * For now this is a placeholder, but will eventually specify the + * mapping from A/D outputs to DDC inputs (I & Q). + * + * What's implemented today is a single DDC that has its I input + * connected to ADC0 and its Q input connected to ADC1 + * ---------------------------------------------------------------- + */ + +#define USRP_RX_CONFIG_DEFAULT 0 + +/*! + * given a usrp_rx_config word, return the number of I & Q streams that + * are interleaved on the USB. + */ + +int usrp_rx_config_stream_count (unsigned int usrp_rx_config); + +/* + * USRP Tx configurations. + * + * For now this is a placeholder, but will eventually specify the + * mapping from DUC outputs to D/A inputs. + * + * What's implemented today is a single DUC that has its I output + * connected to DAC0 and its Q output connected to DAC1 + */ + +#define USRP_TX_CONFIG_DEFAULT 0 + +/*! + * given a usrp_tx_config word, return the number of I & Q streams that + * are interleaved on the USB. + */ + +int usrp_tx_config_stream_count (unsigned int usrp_tx_config); + + +#endif /* _USRP_CONFIG_H_ */ diff --git a/usrp/host/lib/usrp_dbid.dat b/usrp/host/lib/usrp_dbid.dat new file mode 100644 index 00000000..fe3ed1e0 --- /dev/null +++ b/usrp/host/lib/usrp_dbid.dat @@ -0,0 +1,75 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# This file is used to generate usrp_dbid.h, usrp_dbid.cc and usrp_dbid.py + +"Basic Tx" 0x0000 +"Basic Rx" 0x0001 +"DBS Rx" 0x0002 +"TV Rx" 0x0003 + +"Flex 400 Rx" 0x0004 +"Flex 900 Rx" 0x0005 +"Flex 1200 Rx" 0x0006 +"Flex 2400 Rx" 0x0007 + +"Flex 400 Tx" 0x0008 +"Flex 900 Tx" 0x0009 +"Flex 1200 Tx" 0x000a +"Flex 2400 Tx" 0x000b + +"TV Rx Rev 2" 0x000c +"DBS Rx Rev 2_1" 0x000d + +"LF Tx" 0x000e +"LF Rx" 0x000f + +"Flex 400 Rx MIMO A" 0x0014 +"Flex 900 Rx MIMO A" 0x0015 +"Flex 1200 Rx MIMO A" 0x0016 +"Flex 2400 Rx MIMO A" 0x0017 + +"Flex 400 Tx MIMO A" 0x0018 +"Flex 900 Tx MIMO A" 0x0019 +"Flex 1200 Tx MIMO A" 0x001a +"Flex 2400 Tx MIMO A" 0x001b + +"Flex 400 Rx MIMO B" 0x0024 +"Flex 900 Rx MIMO B" 0x0025 +"Flex 1200 Rx MIMO B" 0x0026 +"Flex 2400 Rx MIMO B" 0x0027 + +"Flex 400 Tx MIMO B" 0x0028 +"Flex 900 Tx MIMO B" 0x0029 +"Flex 1200 Tx MIMO B" 0x002a +"Flex 2400 Tx MIMO B" 0x002b + +"Flex 1800 Rx" 0x0030 +"Flex 1800 Tx" 0x0031 +"Flex 1800 Rx MIMO A" 0x0032 +"Flex 1800 Tx MIMO A" 0x0033 +"Flex 1800 Rx MIMO B" 0x0034 +"Flex 1800 Tx MIMO B" 0x0035 + +"TV Rx Rev 3" 0x0040 + +"Experimental Tx" 0xfffe +"Experimental Rx" 0xffff diff --git a/usrp/host/lib/usrp_local_sighandler.cc b/usrp/host/lib/usrp_local_sighandler.cc new file mode 100644 index 00000000..567d7d06 --- /dev/null +++ b/usrp/host/lib/usrp_local_sighandler.cc @@ -0,0 +1,190 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This is actually the same as gr_local_signhandler, but with a different name. + * We don't have a common library to put this in, so... + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +usrp_local_sighandler::usrp_local_sighandler (int signum, + void (*new_handler)(int)) + : d_signum (signum) +{ +#ifdef HAVE_SIGACTION + struct sigaction new_action; + memset (&new_action, 0, sizeof (new_action)); + + new_action.sa_handler = new_handler; + sigemptyset (&new_action.sa_mask); + new_action.sa_flags = 0; + + if (sigaction (d_signum, &new_action, &d_old_action) < 0){ + perror ("sigaction (install new)"); + throw std::runtime_error ("sigaction"); + } +#endif +} + +usrp_local_sighandler::~usrp_local_sighandler () +{ +#ifdef HAVE_SIGACTION + if (sigaction (d_signum, &d_old_action, 0) < 0){ + perror ("sigaction (restore old)"); + throw std::runtime_error ("sigaction"); + } +#endif +} + +void +usrp_local_sighandler::throw_signal(int signum) throw(usrp_signal) +{ + throw usrp_signal (signum); +} + +/* + * Semi-hideous way to may a signal number into a signal name + */ + +#define SIGNAME(x) case x: return #x + +std::string +usrp_signal::name () const +{ + char tmp[128]; + + switch (signal ()){ +#ifdef SIGHUP + SIGNAME (SIGHUP); +#endif +#ifdef SIGINT + SIGNAME (SIGINT); +#endif +#ifdef SIGQUIT + SIGNAME (SIGQUIT); +#endif +#ifdef SIGILL + SIGNAME (SIGILL); +#endif +#ifdef SIGTRAP + SIGNAME (SIGTRAP); +#endif +#ifdef SIGABRT + SIGNAME (SIGABRT); +#endif +#ifdef SIGBUS + SIGNAME (SIGBUS); +#endif +#ifdef SIGFPE + SIGNAME (SIGFPE); +#endif +#ifdef SIGKILL + SIGNAME (SIGKILL); +#endif +#ifdef SIGUSR1 + SIGNAME (SIGUSR1); +#endif +#ifdef SIGSEGV + SIGNAME (SIGSEGV); +#endif +#ifdef SIGUSR2 + SIGNAME (SIGUSR2); +#endif +#ifdef SIGPIPE + SIGNAME (SIGPIPE); +#endif +#ifdef SIGALRM + SIGNAME (SIGALRM); +#endif +#ifdef SIGTERM + SIGNAME (SIGTERM); +#endif +#ifdef SIGSTKFLT + SIGNAME (SIGSTKFLT); +#endif +#ifdef SIGCHLD + SIGNAME (SIGCHLD); +#endif +#ifdef SIGCONT + SIGNAME (SIGCONT); +#endif +#ifdef SIGSTOP + SIGNAME (SIGSTOP); +#endif +#ifdef SIGTSTP + SIGNAME (SIGTSTP); +#endif +#ifdef SIGTTIN + SIGNAME (SIGTTIN); +#endif +#ifdef SIGTTOU + SIGNAME (SIGTTOU); +#endif +#ifdef SIGURG + SIGNAME (SIGURG); +#endif +#ifdef SIGXCPU + SIGNAME (SIGXCPU); +#endif +#ifdef SIGXFSZ + SIGNAME (SIGXFSZ); +#endif +#ifdef SIGVTALRM + SIGNAME (SIGVTALRM); +#endif +#ifdef SIGPROF + SIGNAME (SIGPROF); +#endif +#ifdef SIGWINCH + SIGNAME (SIGWINCH); +#endif +#ifdef SIGIO + SIGNAME (SIGIO); +#endif +#ifdef SIGPWR + SIGNAME (SIGPWR); +#endif +#ifdef SIGSYS + SIGNAME (SIGSYS); +#endif + default: +#if defined (HAVE_SNPRINTF) +#if defined (SIGRTMIN) && defined (SIGRTMAX) + if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){ + snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ()); + return tmp; + } +#endif + snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ()); + return tmp; +#else + return "Unknown signal"; +#endif + } +} diff --git a/usrp/host/lib/usrp_local_sighandler.h b/usrp/host/lib/usrp_local_sighandler.h new file mode 100644 index 00000000..0bb29c2b --- /dev/null +++ b/usrp/host/lib/usrp_local_sighandler.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP_LOCAL_SIGHANDLER_H +#define INCLUDED_USRP_LOCAL_SIGHANDLER_H + +#include +#include + +/*! + * \brief Representation of signal. + */ +class usrp_signal +{ + int d_signum; +public: + usrp_signal (int signum) : d_signum (signum) {} + int signal () const { return d_signum; } + std::string name () const; +}; + + +/*! + * \brief Get and set signal handler. + * + * Constructor installs new handler, destructor reinstalls + * original value. + */ +class usrp_local_sighandler { + int d_signum; +#ifdef HAVE_SIGACTION + struct sigaction d_old_action; +#endif +public: + usrp_local_sighandler (int signum, void (*new_handler)(int)); + ~usrp_local_sighandler (); + + /* throw usrp_signal (signum) */ + static void throw_signal (int signum) throw (usrp_signal); +}; + +#endif /* INCLUDED_USRP_LOCAL_SIGHANDLER_H */ diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims.cc new file mode 100644 index 00000000..5d1c26da --- /dev/null +++ b/usrp/host/lib/usrp_prims.cc @@ -0,0 +1,1355 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp_prims.h" +#include "usrp_commands.h" +#include "usrp_ids.h" +#include "usrp_i2c_addr.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include +#include +#include +#include +#include +#include +#include +#include // FIXME should check with autoconf (nanosleep) +#include +#include +#include + +extern "C" { +#include "md5.h" +}; + +#define VERBOSE 0 + +using namespace ad9862; + +static const int FIRMWARE_HASH_SLOT = 0; +static const int FPGA_HASH_SLOT = 1; + +static const int hash_slot_addr[2] = { + USRP_HASH_SLOT_0_ADDR, + USRP_HASH_SLOT_1_ADDR +}; + +static char *default_firmware_filename = "std.ihx"; +static char *default_fpga_filename = "std_2rxhb_2tx.rbf"; + +#include "std_paths.h" + +static char * +find_file (const char *filename, int hw_rev) +{ + char **sp = std_paths; + static char path[1000]; + char *s; + + s = getenv("USRP_PATH"); + if (s) { + snprintf (path, sizeof (path), "%s/rev%d/%s", s, hw_rev, filename); + if (access (path, R_OK) == 0) + return path; + } + + while (*sp){ + snprintf (path, sizeof (path), "%s/rev%d/%s", *sp, hw_rev, filename); + if (access (path, R_OK) == 0) + return path; + sp++; + } + return 0; +} + +static const char * +get_proto_filename(const std::string user_filename, const char *env_var, const char *def) +{ + if (user_filename.length() != 0) + return user_filename.c_str(); + + char *s = getenv(env_var); + if (s && *s) + return s; + + return def; +} + + +static void power_down_9862s (struct usb_dev_handle *udh); + +void +usrp_one_time_init () +{ + static bool first = true; + + if (first){ + first = false; + usb_init (); // usb library init + usb_find_busses (); + usb_find_devices (); + } +} + +void +usrp_rescan () +{ + usb_find_busses (); + usb_find_devices (); +} + + +// ---------------------------------------------------------------- +// Danger, big, fragile KLUDGE. The problem is that we want to be +// able to get from a usb_dev_handle back to a usb_device, and the +// right way to do this is buried in a non-installed include file. + +static struct usb_device * +dev_handle_to_dev (usb_dev_handle *udh) +{ + struct usb_dev_handle_kludge { + int fd; + struct usb_bus *bus; + struct usb_device *device; + }; + + return ((struct usb_dev_handle_kludge *) udh)->device; +} + +// ---------------------------------------------------------------- + +/* + * q must be a real USRP, not an FX2. Return its hardware rev number. + */ +int +usrp_hw_rev (struct usb_device *q) +{ + return q->descriptor.bcdDevice & 0x00FF; +} + +/* + * q must be a real USRP, not an FX2. Return true if it's configured. + */ +static bool +_usrp_configured_p (struct usb_device *q) +{ + return (q->descriptor.bcdDevice & 0xFF00) != 0; +} + +bool +usrp_usrp_p (struct usb_device *q) +{ + return (q->descriptor.idVendor == USB_VID_FSF + && q->descriptor.idProduct == USB_PID_FSF_USRP); +} + +bool +usrp_fx2_p (struct usb_device *q) +{ + return (q->descriptor.idVendor == USB_VID_CYPRESS + && q->descriptor.idProduct == USB_PID_CYPRESS_FX2); +} + +bool +usrp_usrp0_p (struct usb_device *q) +{ + return usrp_usrp_p (q) && usrp_hw_rev (q) == 0; +} + +bool +usrp_usrp1_p (struct usb_device *q) +{ + return usrp_usrp_p (q) && usrp_hw_rev (q) == 1; +} + +bool +usrp_usrp2_p (struct usb_device *q) +{ + return usrp_usrp_p (q) && usrp_hw_rev (q) == 2; +} + + +bool +usrp_unconfigured_usrp_p (struct usb_device *q) +{ + return usrp_usrp_p (q) && !_usrp_configured_p (q); +} + +bool +usrp_configured_usrp_p (struct usb_device *q) +{ + return usrp_usrp_p (q) && _usrp_configured_p (q); +} + +// ---------------------------------------------------------------- + +struct usb_device * +usrp_find_device (int nth, bool fx2_ok_p) +{ + struct usb_bus *p; + struct usb_device *q; + int n_found = 0; + + usrp_one_time_init (); + + p = usb_get_busses(); + while (p != NULL){ + q = p->devices; + while (q != NULL){ + if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){ + if (n_found == nth) // return this one + return q; + n_found++; // keep looking + } + q = q->next; + } + p = p->next; + } + return 0; // not found +} + +static struct usb_dev_handle * +usrp_open_interface (struct usb_device *dev, int interface, int altinterface) +{ + struct usb_dev_handle *udh = usb_open (dev); + if (udh == 0) + return 0; + + if (dev != dev_handle_to_dev (udh)){ + fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); + abort (); + } + +#if defined(WIN32) + // There's no get get_configuration function, and with some of the newer kernels + // setting the configuration, even if to the same value, hoses any other processes + // that have it open. Hence we opt to not set it at all (We've only + // got a single configuration anyway). This may hose the win32 stuff... + + if (usb_set_configuration (udh, 1) < 0){ + /* + * Ignore this error. + * + * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that + * it returns -EBUSY if _any_ of the interfaces of a device are open. + * We've only got a single configuration, so setting it doesn't even seem + * like it should be required. + */ + } +#endif + + if (usb_claim_interface (udh, interface) < 0){ + fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); + fprintf (stderr, "%s\n", usb_strerror()); + usb_close (udh); + return 0; + } + + if (usb_set_altinterface (udh, altinterface) < 0){ + fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); + fprintf (stderr, "%s\n", usb_strerror()); + usb_release_interface (udh, interface); + usb_close (udh); + return 0; + } + + return udh; +} + +struct usb_dev_handle * +usrp_open_cmd_interface (struct usb_device *dev) +{ + return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE); +} + +struct usb_dev_handle * +usrp_open_rx_interface (struct usb_device *dev) +{ + return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE); +} + +struct usb_dev_handle * +usrp_open_tx_interface (struct usb_device *dev) +{ + return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE); +} + +bool +usrp_close_interface (struct usb_dev_handle *udh) +{ + // we're assuming that closing an interface automatically releases it. + return usb_close (udh) == 0; +} + +// ---------------------------------------------------------------- +// write internal ram using Cypress vendor extension + +static bool +write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, + int start_addr, size_t len) +{ + int addr; + int n; + int a; + int quanta = MAX_EP0_PKTSIZE; + + for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ + n = len + start_addr - addr; + if (n > quanta) + n = quanta; + + a = usb_control_msg (udh, 0x40, 0xA0, + addr, 0, (char *)(buf + (addr - start_addr)), n, 1000); + + if (a < 0){ + fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror()); + return false; + } + } + return true; +} + +// ---------------------------------------------------------------- +// whack the CPUCS register using the upload RAM vendor extension + +static bool +reset_cpu (struct usb_dev_handle *udh, bool reset_p) +{ + unsigned char v; + + if (reset_p) + v = 1; // hold processor in reset + else + v = 0; // release reset + + return write_internal_ram (udh, &v, 0xE600, 1); +} + +// ---------------------------------------------------------------- +// Load intel format file into cypress FX2 (8051) + +static bool +_usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, + unsigned char hash[USRP_HASH_SIZE]) +{ + FILE *f = fopen (filename, "ra"); + if (f == 0){ + perror (filename); + return false; + } + + if (!reset_cpu (udh, true)) // hold CPU in reset while loading firmware + goto fail; + + + char s[1024]; + int length; + int addr; + int type; + unsigned char data[256]; + unsigned char checksum, a; + unsigned int b; + int i; + + while (!feof(f)){ + fgets(s, sizeof (s), f); /* we should not use more than 263 bytes normally */ + if(s[0]!=':'){ + fprintf(stderr,"%s: invalid line: \"%s\"\n", filename, s); + goto fail; + } + sscanf(s+1, "%02x", &length); + sscanf(s+3, "%04x", &addr); + sscanf(s+7, "%02x", &type); + + if(type==0){ + + a=length+(addr &0xff)+(addr>>8)+type; + for(i=0;i 0){ + if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_XFER, buf, n) != n) + goto fail; + } + + if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_END, 0, 0) != 0) + goto fail; + + fclose (fp); + + if (!usrp_set_hash (udh, FPGA_HASH_SLOT, hash)) + fprintf (stderr, "usrp: failed to write fpga hash slot\n"); + + // On the rev1 USRP, the {tx,rx}_{enable,reset} bits are + // controlled over the serial bus, and hence aren't observed until + // we've got a good fpga bitstream loaded. + + usrp_set_fpga_reset (udh, 0); // fpga out of master reset + + // now these commands will work + + ok &= usrp_set_fpga_tx_enable (udh, 0); + ok &= usrp_set_fpga_rx_enable (udh, 0); + + ok &= usrp_set_fpga_tx_reset (udh, 1); // reset tx and rx paths + ok &= usrp_set_fpga_rx_reset (udh, 1); + ok &= usrp_set_fpga_tx_reset (udh, 0); // reset tx and rx paths + ok &= usrp_set_fpga_rx_reset (udh, 0); + + if (!ok) + fprintf (stderr, "usrp: failed to reset tx and/or rx path\n"); + + // Manually reset all regs except master control to zero. + // FIXME may want to remove this when we rework FPGA reset strategy. + // In the mean while, this gets us reproducible behavior. + for (int i = 0; i < FR_USER_0; i++){ + if (i == FR_MASTER_CTRL) + continue; + usrp_write_fpga_reg(udh, i, 0); + } + + power_down_9862s (udh); // on the rev1, power these down! + usrp_set_led (udh, 1, 0); // led 1 off + + return true; + + fail: + power_down_9862s (udh); // on the rev1, power these down! + fclose (fp); + return false; +} + +// ---------------------------------------------------------------- + +bool +usrp_set_led (struct usb_dev_handle *udh, int which, bool on) +{ + int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0); + + return r == 0; +} + +bool +usrp_set_hash (struct usb_dev_handle *udh, int which, + const unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware down load command to jam it in. + int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + (char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_get_hash (struct usb_dev_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware upload command to fetch it. + int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + (char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +static bool +usrp_set_switch (struct usb_dev_handle *udh, int cmd_byte, bool on) +{ + return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; +} + + +static bool +usrp1_fpga_write (struct usb_dev_handle *udh, + int regno, int value) +{ + // on the rev1 usrp, we use the generic spi_write interface + + unsigned char buf[4]; + + buf[0] = (value >> 24) & 0xff; // MSB first + buf[1] = (value >> 16) & 0xff; + buf[2] = (value >> 8) & 0xff; + buf[3] = (value >> 0) & 0xff; + + return usrp_spi_write (udh, 0x00 | (regno & 0x7f), + SPI_ENABLE_FPGA, + SPI_FMT_MSB | SPI_FMT_HDR_1, + buf, sizeof (buf)); +} + +static bool +usrp1_fpga_read (struct usb_dev_handle *udh, + int regno, int *value) +{ + *value = 0; + unsigned char buf[4]; + + bool ok = usrp_spi_read (udh, 0x80 | (regno & 0x7f), + SPI_ENABLE_FPGA, + SPI_FMT_MSB | SPI_FMT_HDR_1, + buf, sizeof (buf)); + + if (ok) + *value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + return ok; +} + + +bool +usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value) +{ + switch (usrp_hw_rev (dev_handle_to_dev (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_write (udh, reg, value); + } +} + +bool +usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) +{ + switch (usrp_hw_rev (dev_handle_to_dev (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_read (udh, reg, value); + } +} + +bool +usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on); +} + +bool +usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on); +} + +bool +usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on); +} + +bool +usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on); +} + +bool +usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on); +} + + +// ---------------------------------------------------------------- +// conditional load stuff + +static bool +compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE]) +{ + assert (USRP_HASH_SIZE == 16); + memset (hash, 0, USRP_HASH_SIZE); + + FILE *fp = fopen (filename, "rb"); + if (fp == 0){ + perror (filename); + return false; + } + int r = md5_stream (fp, hash); + fclose (fp); + + return r == 0; +} + +static usrp_load_status_t +usrp_conditionally_load_something (struct usb_dev_handle *udh, + const char *filename, + bool force, + int slot, + bool loader (struct usb_dev_handle *, + const char *, + unsigned char [USRP_HASH_SIZE])) +{ + unsigned char file_hash[USRP_HASH_SIZE]; + unsigned char usrp_hash[USRP_HASH_SIZE]; + + if (access (filename, R_OK) != 0){ + perror (filename); + return ULS_ERROR; + } + + if (!compute_hash (filename, file_hash)) + return ULS_ERROR; + + if (!force + && usrp_get_hash (udh, slot, usrp_hash) + && memcmp (file_hash, usrp_hash, USRP_HASH_SIZE) == 0) + return ULS_ALREADY_LOADED; + + bool r = loader (udh, filename, file_hash); + + if (!r) + return ULS_ERROR; + + return ULS_OK; +} + +usrp_load_status_t +usrp_load_firmware (struct usb_dev_handle *udh, + const char *filename, + bool force) +{ + return usrp_conditionally_load_something (udh, filename, force, + FIRMWARE_HASH_SLOT, + _usrp_load_firmware); +} + +usrp_load_status_t +usrp_load_fpga (struct usb_dev_handle *udh, + const char *filename, + bool force) +{ + return usrp_conditionally_load_something (udh, filename, force, + FPGA_HASH_SLOT, + _usrp_load_fpga); +} + +static usb_dev_handle * +open_nth_cmd_interface (int nth) +{ + struct usb_device *udev = usrp_find_device (nth); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return 0; + } + + struct usb_dev_handle *udh; + + udh = usrp_open_cmd_interface (udev); + if (udh == 0){ + // FIXME this could be because somebody else has it open. + // We should delay and retry... + fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); + usb_strerror (); + return 0; + } + + return udh; + } + +static bool +our_nanosleep (const struct timespec *delay) +{ + struct timespec new_delay = *delay; + struct timespec remainder; + + while (1){ + int r = nanosleep (&new_delay, &remainder); + if (r == 0) + return true; + if (errno == EINTR) + new_delay = remainder; + else { + perror ("nanosleep"); + return false; + } + } +} + +static bool +mdelay (int millisecs) +{ + struct timespec ts; + ts.tv_sec = millisecs / 1000; + ts.tv_nsec = (millisecs - (1000 * ts.tv_sec)) * 1000000; + return our_nanosleep (&ts); +} + +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force){ + struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + if (udh == 0) + return ULS_ERROR; + + usrp_load_status_t s = usrp_load_firmware (udh, filename, force); + usrp_close_interface (udh); + + switch (s){ + + case ULS_ALREADY_LOADED: // nothing changed... + return ULS_ALREADY_LOADED; + break; + + case ULS_OK: + // we loaded firmware successfully. + + // It's highly likely that the board will renumerate (simulate a + // disconnect/reconnect sequence), invalidating our current + // handle. + + // FIXME. Turn this into a loop that rescans until we refind ourselves + + struct timespec t; // delay for 1 second + t.tv_sec = 2; + t.tv_nsec = 0; + our_nanosleep (&t); + + usb_find_busses (); // rescan busses and devices + usb_find_devices (); + + return ULS_OK; + + default: + case ULS_ERROR: // some kind of problem + return ULS_ERROR; + } +} + +static void +load_status_msg (usrp_load_status_t s, const char *type, const char *filename) +{ + char *e = getenv("USRP_VERBOSE"); + bool verbose = e != 0; + + switch (s){ + case ULS_ERROR: + fprintf (stderr, "usrp: failed to load %s %s.\n", type, filename); + break; + + case ULS_ALREADY_LOADED: + if (verbose) + fprintf (stderr, "usrp: %s %s already loaded.\n", type, filename); + break; + + case ULS_OK: + if (verbose) + fprintf (stderr, "usrp: %s %s loaded successfully.\n", type, filename); + break; + } +} + +bool +usrp_load_standard_bits (int nth, bool force, + const std::string fpga_filename, + const std::string firmware_filename) +{ + usrp_load_status_t s; + const char *filename; + const char *proto_filename; + int hw_rev; + + // first, figure out what hardware rev we're dealing with + { + struct usb_device *udev = usrp_find_device (nth); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return false; + } + hw_rev = usrp_hw_rev (udev); + } + + // start by loading the firmware + + proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", + default_firmware_filename); + filename = find_file(proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find firmware: %s\n", proto_filename); + return false; + } + + s = usrp_load_firmware_nth (nth, filename, force); + load_status_msg (s, "firmware", filename); + + if (s == ULS_ERROR) + return false; + + // if we actually loaded firmware, we must reload fpga ... + if (s == ULS_OK) + force = true; + + // now move on to the fpga configuration bitstream + + proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", + default_fpga_filename); + filename = find_file (proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); + return false; + } + + struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + if (udh == 0) + return false; + + s = usrp_load_fpga (udh, filename, force); + usrp_close_interface (udh); + load_status_msg (s, "fpga bitstream", filename); + + if (s == ULS_ERROR) + return false; + + return true; +} + +bool +_usrp_get_status (struct usb_dev_handle *udh, int which, bool *trouble) +{ + unsigned char status; + *trouble = true; + + if (write_cmd (udh, VRQ_GET_STATUS, 0, which, + &status, sizeof (status)) != sizeof (status)) + return false; + + *trouble = status; + return true; +} + +bool +usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p) +{ + return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p); +} + +bool +usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p) +{ + return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p); +} + + +bool +usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr, + const void *buf, int len) +{ + if (len < 1 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_I2C_WRITE, i2c_addr, 0, + (unsigned char *) buf, len) == len; +} + + +bool +usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, + void *buf, int len) +{ + if (len < 1 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_I2C_READ, i2c_addr, 0, + (unsigned char *) buf, len) == len; +} + +bool +usrp_spi_write (struct usb_dev_handle *udh, + int optional_header, int enables, int format, + const void *buf, int len) +{ + if (len < 0 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_SPI_WRITE, + optional_header, + ((enables & 0xff) << 8) | (format & 0xff), + (unsigned char *) buf, len) == len; +} + + +bool +usrp_spi_read (struct usb_dev_handle *udh, + int optional_header, int enables, int format, + void *buf, int len) +{ + if (len < 0 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_SPI_READ, + optional_header, + ((enables & 0xff) << 8) | (format & 0xff), + (unsigned char *) buf, len) == len; +} + +bool +usrp_9862_write (struct usb_dev_handle *udh, int which_codec, + int regno, int value) +{ + if (0) + fprintf (stderr, "usrp_9862_write which = %d, reg = %2d, val = %3d (0x%02x)\n", + which_codec, regno, value, value); + + unsigned char buf[1]; + + buf[0] = value; + + return usrp_spi_write (udh, 0x00 | (regno & 0x3f), + which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + buf, 1); +} + +bool +usrp_9862_read (struct usb_dev_handle *udh, int which_codec, + int regno, unsigned char *value) +{ + return usrp_spi_read (udh, 0x80 | (regno & 0x3f), + which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + value, 1); +} + +bool +usrp_9862_write_many (struct usb_dev_handle *udh, + int which_codec, + const unsigned char *buf, + int len) +{ + if (len & 0x1) + return false; // must be even + + bool result = true; + + while (len > 0){ + result &= usrp_9862_write (udh, which_codec, buf[0], buf[1]); + len -= 2; + buf += 2; + } + + return result; +} + + +bool +usrp_9862_write_many_all (struct usb_dev_handle *udh, + const unsigned char *buf, int len) +{ + // FIXME handle 2/2 and 4/4 versions + + bool result; + result = usrp_9862_write_many (udh, 0, buf, len); + result &= usrp_9862_write_many (udh, 1, buf, len); + return result; +} + +static void +power_down_9862s (struct usb_dev_handle *udh) +{ + static const unsigned char regs[] = { + REG_RX_PWR_DN, 0x01, // everything + REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both + REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled + }; + + switch (usrp_hw_rev (dev_handle_to_dev (udh))){ + case 0: + break; + + default: + usrp_9862_write_many_all (udh, regs, sizeof (regs)); + break; + } +} + + + +static const int EEPROM_PAGESIZE = 16; + +bool +usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, + int eeprom_offset, const void *buf, int len) +{ + unsigned char cmd[2]; + const unsigned char *p = (unsigned char *) buf; + + // The simplest thing that could possibly work: + // all writes are single byte writes. + // + // We could speed this up using the page write feature, + // but we write so infrequently, why bother... + + while (len-- > 0){ + cmd[0] = eeprom_offset++; + cmd[1] = *p++; + bool r = usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd)); + mdelay (10); // delay 10ms worst case write time + if (!r) + return false; + } + + return true; +} + +bool +usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, + int eeprom_offset, void *buf, int len) +{ + unsigned char *p = (unsigned char *) buf; + + // We setup a random read by first doing a "zero byte write". + // Writes carry an address. Reads use an implicit address. + + unsigned char cmd[1]; + cmd[0] = eeprom_offset; + if (!usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd))) + return false; + + while (len > 0){ + int n = std::min (len, MAX_EP0_PKTSIZE); + if (!usrp_i2c_read (udh, i2c_addr, p, n)) + return false; + len -= n; + p += n; + } + return true; +} + +// ---------------------------------------------------------------- + +static bool +slot_to_codec (int slot, int *which_codec) +{ + *which_codec = 0; + + switch (slot){ + case SLOT_TX_A: + case SLOT_RX_A: + *which_codec = 0; + break; + + case SLOT_TX_B: + case SLOT_RX_B: + *which_codec = 1; + break; + + default: + fprintf (stderr, "usrp_prims:slot_to_codec: invalid slot = %d\n", slot); + return false; + } + return true; +} + +static bool +tx_slot_p (int slot) +{ + switch (slot){ + case SLOT_TX_A: + case SLOT_TX_B: + return true; + + default: + return false; + } +} + +bool +usrp_write_aux_dac (struct usb_dev_handle *udh, int slot, + int which_dac, int value) +{ + int which_codec; + + if (!slot_to_codec (slot, &which_codec)) + return false; + + if (!(0 <= which_dac && which_dac < 4)){ + fprintf (stderr, "usrp_write_aux_dac: invalid dac = %d\n", which_dac); + return false; + } + + value &= 0x0fff; // mask to 12-bits + + if (which_dac == 3){ + // dac 3 is really 12-bits. Use value as is. + bool r = true; + r &= usrp_9862_write (udh, which_codec, 43, (value >> 4)); // most sig + r &= usrp_9862_write (udh, which_codec, 42, (value & 0xf) << 4); // least sig + return r; + } + else { + // dac 0, 1, and 2 are really 8 bits. + value = value >> 4; // shift value appropriately + return usrp_9862_write (udh, which_codec, 36 + which_dac, value); + } +} + + +bool +usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, + int which_adc, int *value) +{ + *value = 0; + int which_codec; + + if (!slot_to_codec (slot, &which_codec)) + return false; + + if (!(0 <= which_codec && which_codec < 2)){ + fprintf (stderr, "usrp_read_aux_adc: invalid adc = %d\n", which_adc); + return false; + } + + unsigned char aux_adc_control = + AUX_ADC_CTRL_REFSEL_A // on chip reference + | AUX_ADC_CTRL_REFSEL_B; // on chip reference + + int rd_reg = 26; // base address of two regs to read for result + + // program the ADC mux bits + if (tx_slot_p (slot)) + aux_adc_control |= AUX_ADC_CTRL_SELECT_A2 | AUX_ADC_CTRL_SELECT_B2; + else { + rd_reg += 2; + aux_adc_control |= AUX_ADC_CTRL_SELECT_A1 | AUX_ADC_CTRL_SELECT_B1; + } + + // I'm not sure if we can set the mux and issue a start conversion + // in the same cycle, so let's do them one at a time. + + usrp_9862_write (udh, which_codec, 34, aux_adc_control); + + if (which_adc == 0) + aux_adc_control |= AUX_ADC_CTRL_START_A; + else { + rd_reg += 4; + aux_adc_control |= AUX_ADC_CTRL_START_B; + } + + // start the conversion + usrp_9862_write (udh, which_codec, 34, aux_adc_control); + + // read the 10-bit result back + unsigned char v_lo = 0; + unsigned char v_hi = 0; + bool r = usrp_9862_read (udh, which_codec, rd_reg, &v_lo); + r &= usrp_9862_read (udh, which_codec, rd_reg + 1, &v_hi); + + if (r) + *value = ((v_hi << 2) | ((v_lo >> 6) & 0x3)) << 2; // format as 12-bit + + return r; +} + +// ---------------------------------------------------------------- + +static int slot_to_i2c_addr (int slot) +{ + switch (slot){ + case SLOT_TX_A: return I2C_ADDR_TX_A; + case SLOT_RX_A: return I2C_ADDR_RX_A; + case SLOT_TX_B: return I2C_ADDR_TX_B; + case SLOT_RX_B: return I2C_ADDR_RX_B; + default: return -1; + } +} + +static void +set_chksum (unsigned char *buf) +{ + int sum = 0; + unsigned int i; + for (i = 0; i < DB_EEPROM_CLEN - 1; i++) + sum += buf[i]; + buf[i] = -sum; +} + +static usrp_dbeeprom_status_t +read_dboard_eeprom (struct usb_dev_handle *udh, + int slot_id, unsigned char *buf) +{ + int i2c_addr = slot_to_i2c_addr (slot_id); + if (i2c_addr == -1) + return UDBE_BAD_SLOT; + + if (!usrp_eeprom_read (udh, i2c_addr, 0, buf, DB_EEPROM_CLEN)) + return UDBE_NO_EEPROM; + + if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE) + return UDBE_INVALID_EEPROM; + + int sum = 0; + for (unsigned int i = 0; i < DB_EEPROM_CLEN; i++) + sum += buf[i]; + + if ((sum & 0xff) != 0) + return UDBE_INVALID_EEPROM; + + return UDBE_OK; +} + +usrp_dbeeprom_status_t +usrp_read_dboard_eeprom (struct usb_dev_handle *udh, + int slot_id, usrp_dboard_eeprom *eeprom) +{ + unsigned char buf[DB_EEPROM_CLEN]; + + memset (eeprom, 0, sizeof (*eeprom)); + + usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf); + if (s != UDBE_OK) + return s; + + eeprom->id = (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB]; + eeprom->oe = (buf[DB_EEPROM_OE_MSB] << 8) | buf[DB_EEPROM_OE_LSB]; + eeprom->offset[0] = (buf[DB_EEPROM_OFFSET_0_MSB] << 8) | buf[DB_EEPROM_OFFSET_0_LSB]; + eeprom->offset[1] = (buf[DB_EEPROM_OFFSET_1_MSB] << 8) | buf[DB_EEPROM_OFFSET_1_LSB]; + + return UDBE_OK; +} + +bool +usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id, + short offset0, short offset1) +{ + unsigned char buf[DB_EEPROM_CLEN]; + + usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf); + if (s != UDBE_OK) + return false; + + buf[DB_EEPROM_OFFSET_0_LSB] = (offset0 >> 0) & 0xff; + buf[DB_EEPROM_OFFSET_0_MSB] = (offset0 >> 8) & 0xff; + buf[DB_EEPROM_OFFSET_1_LSB] = (offset1 >> 0) & 0xff; + buf[DB_EEPROM_OFFSET_1_MSB] = (offset1 >> 8) & 0xff; + set_chksum (buf); + + return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id), + 0, buf, sizeof (buf)); +} + +std::string +usrp_serial_number(struct usb_dev_handle *udh) +{ + u_int8_t iserial = usb_device(udh)->descriptor.iSerialNumber; + if (iserial == 0) + return ""; + + char buf[1024]; + if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0) + return ""; + + return buf; +} diff --git a/usrp/host/lib/usrp_prims.h b/usrp/host/lib/usrp_prims.h new file mode 100644 index 00000000..a4bbb620 --- /dev/null +++ b/usrp/host/lib/usrp_prims.h @@ -0,0 +1,294 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Low level primitives for directly messing with USRP hardware. + * + * If you're trying to use the USRP, you'll probably want to take a look + * at the usrp_rx and usrp_tx classes. They hide a bunch of low level details + * and provide high performance streaming i/o. + * + * This interface is built on top of libusb, which allegedly works under + * Linux, *BSD and Mac OS/X. http://libusb.sourceforge.net + */ + +#ifndef _USRP_PRIMS_H_ +#define _USRP_PRIMS_H_ + +#include +#include + +static const int USRP_HASH_SIZE = 16; + +enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; + +struct usb_dev_handle; +struct usb_device; + +/*! + * \brief initialize libusb; probe busses and devices. + * Safe to call more than once. + */ +void usrp_one_time_init (); + +/* + * force a rescan of the buses and devices + */ +void usrp_rescan (); + +/*! + * \brief locate Nth (zero based) USRP device in system. + * Return pointer or 0 if not found. + * + * The following kinds of devices are considered USRPs: + * + * unconfigured USRP (no firwmare loaded) + * configured USRP (firmware loaded) + * unconfigured Cypress FX2 (only if fx2_ok_p is true) + */ +struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false); + +bool usrp_usrp_p (struct usb_device *q); //< is this a USRP +bool usrp_usrp0_p (struct usb_device *q); //< is this a USRP Rev 0 +bool usrp_usrp1_p (struct usb_device *q); //< is this a USRP Rev 1 +bool usrp_usrp2_p (struct usb_device *q); //< is this a USRP Rev 2 +int usrp_hw_rev (struct usb_device *q); //< return h/w rev code + +bool usrp_fx2_p (struct usb_device *q); //< is this an unconfigured Cypress FX2 + +bool usrp_unconfigured_usrp_p (struct usb_device *q); //< some kind of unconfigured USRP +bool usrp_configured_usrp_p (struct usb_device *q); //< some kind of configured USRP + +/*! + * \brief given a usb_device return an instance of the appropriate usb_dev_handle + * + * These routines claim the specified interface and select the + * correct alternate interface. (USB nomenclature is totally screwed!) + * + * If interface can't be opened, or is already claimed by some other + * process, 0 is returned. + */ +struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev); +struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev); +struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev); + +/*! + * \brief close interface. + */ +bool usrp_close_interface (struct usb_dev_handle *udh); + +/*! + * \brief load intel hex format file into USRP/Cypress FX2 (8051). + * + * The filename extension is typically *.ihx + * + * Note that loading firmware may cause the device to renumerate. I.e., + * change its configuration, invalidating the current device handle. + */ + +usrp_load_status_t +usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force); + +/*! + * \brief load intel hex format file into USRP FX2 (8051). + * + * The filename extension is typically *.ihx + * + * Note that loading firmware may cause the device to renumerate. I.e., + * change its configuration, invalidating the current device handle. + * If the result is ULS_OK, usrp_load_firmware_nth delays 1 second + * then rescans the busses and devices. + */ +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force); + +/*! + * \brief load fpga configuration bitstream + */ +usrp_load_status_t +usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force); + +/*! + * \brief load the regular firmware and fpga bitstream in the Nth USRP. + * + * This is the normal starting point... + */ +bool usrp_load_standard_bits (int nth, bool force, + const std::string fpga_filename = "", + const std::string firmware_filename = ""); + +/*! + * \brief copy the given \p hash into the USRP hash slot \p which. + * The usrp implements two hash slots, 0 and 1. + */ +bool usrp_set_hash (struct usb_dev_handle *udh, int which, + const unsigned char hash[USRP_HASH_SIZE]); + +/*! + * \brief retrieve the \p hash from the USRP hash slot \p which. + * The usrp implements two hash slots, 0 and 1. + */ +bool usrp_get_hash (struct usb_dev_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]); + +bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value); +bool usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value); +bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on); + +bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p); +bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p); + +// i2c_read and i2c_write are limited to a maximum len of 64 bytes. + +bool usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr, + const void *buf, int len); + +bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, + void *buf, int len); + +// spi_read and spi_write are limited to a maximum of 64 bytes +// See usrp_spi_defs.h for more info + +bool usrp_spi_write (struct usb_dev_handle *udh, + int optional_header, int enables, int format, + const void *buf, int len); + +bool usrp_spi_read (struct usb_dev_handle *udh, + int optional_header, int enables, int format, + void *buf, int len); + + +bool usrp_9862_write (struct usb_dev_handle *udh, + int which_codec, // [0, 1] + int regno, // [0, 63] + int value); // [0, 255] + +bool usrp_9862_read (struct usb_dev_handle *udh, + int which_codec, // [0, 1] + int regno, // [0, 63] + unsigned char *value); // [0, 255] + +/*! + * \brief Write multiple 9862 regs at once. + * + * \p buf contains alternating register_number, register_value pairs. + * \p len must be even and is the length of buf in bytes. + */ +bool usrp_9862_write_many (struct usb_dev_handle *udh, int which_codec, + const unsigned char *buf, int len); + + +/*! + * \brief write specified regs to all 9862's in the system + */ +bool usrp_9862_write_many_all (struct usb_dev_handle *udh, + const unsigned char *buf, int len); + + +// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. +// Which EEPROM is determined by i2c_addr. See i2c_addr.h + +bool usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, + int eeprom_offset, const void *buf, int len); + + +// Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. +// Which EEPROM is determined by i2c_addr. See i2c_addr.h + +bool usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, + int eeprom_offset, void *buf, int len); + + +// Slot specific i/o routines + +/*! + * \brief write to the specified aux dac. + * + * \p slot: which Tx or Rx slot to write. + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's + * + * \p which_dac: [0,3] RX slots must use only 0 and 1. + * TX slots must use only 2 and 3. + * + * AUX DAC 3 is really the 9862 sigma delta output. + * + * \p value to write to aux dac. All dacs take straight + * binary values. Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit, + * the interface is in terms of 12-bit values [0,4095] + */ +bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot, + int which_dac, int value); + +/*! + * \brief Read the specified aux adc + * + * \p slot: which Tx or Rx slot to read aux dac + * \p which_adc: [0,1] which of the two adcs to read + * \p *value: return value, 12-bit straight binary. + */ +bool usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, + int which_adc, int *value); + + +/*! + * \brief usrp daughterboard id to name mapping + */ +const std::string usrp_dbid_to_string (int dbid); + + +enum usrp_dbeeprom_status_t { UDBE_OK, UDBE_BAD_SLOT, UDBE_NO_EEPROM, UDBE_INVALID_EEPROM }; + +struct usrp_dboard_eeprom { + unsigned short id; // d'board identifier code + unsigned short oe; // fpga output enables: + // If bit set, i/o pin is an output from FPGA. + short offset[2]; // ADC/DAC offset correction +}; + +/*! + * \brief Read and return parsed daughterboard eeprom + */ +usrp_dbeeprom_status_t +usrp_read_dboard_eeprom (struct usb_dev_handle *udh, + int slot_id, usrp_dboard_eeprom *eeprom); + +/*! + * \brief write ADC/DAC offset calibration constants to d'board eeprom + */ +bool usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id, + short offset0, short offset1); + +/*! + * \brief return a usrp's serial number. + * + * Note that this only works on a configured usrp. + * \returns non-zero length string iff successful. + */ +std::string usrp_serial_number(struct usb_dev_handle *udh); + +#endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/usrp_slots.h b/usrp/host/lib/usrp_slots.h new file mode 100644 index 00000000..1568ce72 --- /dev/null +++ b/usrp/host/lib/usrp_slots.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP_SLOTS_H +#define INCLUDED_USRP_SLOTS_H + +// daughterboard slot numbers used in some calls + +static const int SLOT_TX_A = 0; +static const int SLOT_RX_A = 1; +static const int SLOT_TX_B = 2; +static const int SLOT_RX_B = 3; + +#endif /* INCLUDED_USRP_SLOTS_H */ diff --git a/usrp/host/lib/usrp_standard.cc b/usrp/host/lib/usrp_standard.cc new file mode 100644 index 00000000..d59920fd --- /dev/null +++ b/usrp/host/lib/usrp_standard.cc @@ -0,0 +1,831 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "usrp_prims.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include +#include +#include +#include + + +static const int OLD_CAPS_VAL = 0xaa55ff77; +static const int DEFAULT_CAPS_VAL = ((2 << bmFR_RB_CAPS_NDUC_SHIFT) + | (2 << bmFR_RB_CAPS_NDDC_SHIFT) + | bmFR_RB_CAPS_RX_HAS_HALFBAND); + +// #define USE_FPGA_TX_CORDIC + + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static unsigned int +compute_freq_control_word_fpga (double master_freq, double target_freq, + double *actual_freq, bool verbose) +{ + static const int NBITS = 14; + + int v = (int) rint (target_freq / master_freq * pow (2.0, 32.0)); + + if (0) + v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS + + *actual_freq = v * master_freq / pow (2.0, 32.0); + + if (verbose) + fprintf (stderr, + "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n", + target_freq, *actual_freq, *actual_freq - target_freq); + + return (unsigned int) v; +} + +// The 9862 uses an unsigned 24-bit frequency tuning word and +// a separate register to control the sign. + +static unsigned int +compute_freq_control_word_9862 (double master_freq, double target_freq, + double *actual_freq, bool verbose) +{ + double sign = 1.0; + + if (target_freq < 0) + sign = -1.0; + + int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0)); + *actual_freq = v * master_freq / pow (2.0, 24.0) * sign; + + if (verbose) + fprintf (stderr, + "compute_freq_control_word_9862: target = %g actual = %g delta = %g v = %8d\n", + target_freq, *actual_freq, *actual_freq - target_freq, v); + + return (unsigned int) v; +} + +// ---------------------------------------------------------------- + +usrp_standard_common::usrp_standard_common(usrp_basic *parent) +{ + // read new FPGA capability register + if (!parent->_read_fpga_reg(FR_RB_CAPS, &d_fpga_caps)){ + fprintf (stderr, "usrp_standard_common: failed to read FPGA cap register.\n"); + throw std::runtime_error ("usrp_standard_common::ctor"); + } + // If we don't have the cap register, set the value to what it would + // have had if we did have one ;) + if (d_fpga_caps == OLD_CAPS_VAL) + d_fpga_caps = DEFAULT_CAPS_VAL; + + if (0){ + fprintf(stdout, "has_rx_halfband = %d\n", has_rx_halfband()); + fprintf(stdout, "nddcs = %d\n", nddcs()); + fprintf(stdout, "has_tx_halfband = %d\n", has_tx_halfband()); + fprintf(stdout, "nducs = %d\n", nducs()); + } +} + +bool +usrp_standard_common::has_rx_halfband() const +{ + return (d_fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND) ? true : false; +} + +int +usrp_standard_common::nddcs() const +{ + return (d_fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT; +} + +bool +usrp_standard_common::has_tx_halfband() const +{ + return (d_fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND) ? true : false; +} + +int +usrp_standard_common::nducs() const +{ + return (d_fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT; +} + +// ---------------------------------------------------------------- + +static int +real_rx_mux_value (int mux, int nchan) +{ + if (mux != -1) + return mux; + + return 0x32103210; +} + +usrp_standard_rx::usrp_standard_rx (int which_board, + unsigned int decim_rate, + int nchan, int mux, int mode, + int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) + : usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename), + usrp_standard_common(this), + d_nchan (1), d_sw_mux (0x0), d_hw_mux (0x0) +{ + if (!set_format(make_format())){ + fprintf (stderr, "usrp_standard_rx: set_format failed\n"); + throw std::runtime_error ("usrp_standard_rx::ctor"); + } + if (!set_nchannels (nchan)){ + fprintf (stderr, "usrp_standard_rx: set_nchannels failed\n"); + throw std::runtime_error ("usrp_standard_rx::ctor"); + } + if (!set_decim_rate (decim_rate)){ + fprintf (stderr, "usrp_standard_rx: set_decim_rate failed\n"); + throw std::runtime_error ("usrp_standard_rx::ctor"); + } + if (!set_mux (real_rx_mux_value (mux, nchan))){ + fprintf (stderr, "usrp_standard_rx: set_mux failed\n"); + throw std::runtime_error ("usrp_standard_rx::ctor"); + } + if (!set_fpga_mode (mode)){ + fprintf (stderr, "usrp_standard_rx: set_fpga_mode failed\n"); + throw std::runtime_error ("usrp_standard_rx::ctor"); + } + + for (int i = 0; i < MAX_CHAN; i++){ + set_rx_freq(i, 0); + set_ddc_phase(i, 0); + } +} + +usrp_standard_rx::~usrp_standard_rx () +{ + // fprintf(stderr, "\nusrp_standard_rx: dtor\n"); +} + +bool +usrp_standard_rx::start () +{ + if (!usrp_basic_rx::start ()) + return false; + + // add our code here + + return true; +} + +bool +usrp_standard_rx::stop () +{ + bool ok = usrp_basic_rx::stop (); + + // add our code here + + return ok; +} + +usrp_standard_rx * +usrp_standard_rx::make (int which_board, + unsigned int decim_rate, + int nchan, int mux, int mode, + int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) +{ + usrp_standard_rx *u = 0; + + try { + u = new usrp_standard_rx (which_board, decim_rate, + nchan, mux, mode, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename); + return u; + } + catch (...){ + delete u; + return 0; + } + + return u; +} + +bool +usrp_standard_rx::set_decim_rate(unsigned int rate) +{ + if ((rate & 0x1) || rate < 4 || rate > 256){ + fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be EVEN and in [4, 256]\n"); + return false; + } + + d_decim_rate = rate; + set_usb_data_rate ((adc_rate () / rate * nchannels ()) + * (2 * sizeof (short))); + + bool s = disable_rx (); + int v = has_rx_halfband() ? d_decim_rate/2 - 1 : d_decim_rate - 1; + bool ok = _write_fpga_reg (FR_DECIM_RATE, v); + restore_rx (s); + return ok; +} + +bool usrp_standard_rx::set_nchannels (int nchan) +{ + if (!(nchan == 1 || nchan == 2 || nchan == 4)) + return false; + + if (nchan > nddcs()) + return false; + + d_nchan = nchan; + + return write_hw_mux_reg (); +} + + +// map software mux value to hw mux value +// +// Software mux value: +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-------+-------+-------+-------+-------+-------+-------+-------+ +// | Q3 | I3 | Q2 | I2 | Q1 | I1 | Q0 | I0 | +// +-------+-------+-------+-------+-------+-------+-------+-------+ +// +// Each 4-bit I field is either 0,1,2,3 +// Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero) +// All Q's must be 0xf or none of them may be 0xf +// +// +// Hardware mux value: +// +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-----------------------+-------+-------+-------+-------+-+-----+ +// | must be zero | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH | +// +-----------------------+-------+-------+-------+-------+-+-----+ + + +static bool +map_sw_mux_to_hw_mux (int sw_mux, int *hw_mux_ptr) +{ + // confirm that all I's are either 0,1,2,3 + + for (int i = 0; i < 8; i += 2){ + int t = (sw_mux >> (4 * i)) & 0xf; + if (!(0 <= t && t <= 3)) + return false; + } + + // confirm that all Q's are either 0,1,2,3 or 0xf + + for (int i = 1; i < 8; i += 2){ + int t = (sw_mux >> (4 * i)) & 0xf; + if (!(t == 0xf || (0 <= t && t <= 3))) + return false; + } + + // confirm that all Q inputs are 0xf (const zero input), + // or none of them are 0xf + + int q_and = 1; + int q_or = 0; + + for (int i = 0; i < 4; i++){ + int qx_is_0xf = ((sw_mux >> (8 * i + 4)) & 0xf) == 0xf; + q_and &= qx_is_0xf; + q_or |= qx_is_0xf; + } + + if (q_and || !q_or){ // OK + int hw_mux_value = 0; + + for (int i = 0; i < 8; i++){ + int t = (sw_mux >> (4 * i)) & 0x3; + hw_mux_value |= t << (2 * i + 4); + } + + if (q_and) + hw_mux_value |= 0x8; // all Q's zero + + *hw_mux_ptr = hw_mux_value; + return true; + } + else + return false; +} + +bool +usrp_standard_rx::set_mux (int mux) +{ + if (!map_sw_mux_to_hw_mux (mux, &d_hw_mux)) + return false; + + // fprintf (stderr, "sw_mux = 0x%08x hw_mux = 0x%08x\n", mux, d_hw_mux); + + d_sw_mux = mux; + return write_hw_mux_reg (); +} + +bool +usrp_standard_rx::write_hw_mux_reg () +{ + bool s = disable_rx (); + bool ok = _write_fpga_reg (FR_RX_MUX, d_hw_mux | d_nchan); + restore_rx (s); + return ok; +} + + +bool +usrp_standard_rx::set_rx_freq (int channel, double freq) +{ + if (channel < 0 || channel > MAX_CHAN) + return false; + + unsigned int v = + compute_freq_control_word_fpga (adc_freq(), + freq, &d_rx_freq[channel], + d_verbose); + + return _write_fpga_reg (FR_RX_FREQ_0 + channel, v); +} + +unsigned int +usrp_standard_rx::decim_rate () const { return d_decim_rate; } + +int +usrp_standard_rx::nchannels () const { return d_nchan; } + +int +usrp_standard_rx::mux () const { return d_sw_mux; } + +double +usrp_standard_rx::rx_freq (int channel) const +{ + if (channel < 0 || channel >= MAX_CHAN) + return 0; + + return d_rx_freq[channel]; +} + +bool +usrp_standard_rx::set_fpga_mode (int mode) +{ + return _write_fpga_reg (FR_MODE, mode); +} + +bool +usrp_standard_rx::set_ddc_phase(int channel, int phase) +{ + if (channel < 0 || channel >= MAX_CHAN) + return false; + + return _write_fpga_reg(FR_RX_PHASE_0 + channel, phase); +} + + +// To avoid quiet failures, check for things that our code cares about. + +static bool +rx_format_is_valid(unsigned int format) +{ + int width = usrp_standard_rx::format_width(format); + int want_q = usrp_standard_rx::format_want_q(format); + + if (!(width == 8 || width == 16)) // FIXME add other widths when valid + return false; + + if (!want_q) // FIXME remove check when the rest of the code can handle I only + return false; + + return true; +} + +bool +usrp_standard_rx::set_format(unsigned int format) +{ + if (!rx_format_is_valid(format)) + return false; + + return _write_fpga_reg(FR_RX_FORMAT, format); +} + +unsigned int +usrp_standard_rx::format() const +{ + return d_fpga_shadows[FR_RX_FORMAT]; +} + +// ---------------------------------------------------------------- + +unsigned int +usrp_standard_rx::make_format(int width, int shift, bool want_q, bool bypass_halfband) +{ + unsigned int format = + (((width << bmFR_RX_FORMAT_WIDTH_SHIFT) & bmFR_RX_FORMAT_WIDTH_MASK) + | (shift << bmFR_RX_FORMAT_SHIFT_SHIFT) & bmFR_RX_FORMAT_SHIFT_MASK); + + if (want_q) + format |= bmFR_RX_FORMAT_WANT_Q; + if (bypass_halfband) + format |= bmFR_RX_FORMAT_BYPASS_HB; + + return format; +} + +int +usrp_standard_rx::format_width(unsigned int format) +{ + return (format & bmFR_RX_FORMAT_WIDTH_MASK) >> bmFR_RX_FORMAT_WIDTH_SHIFT; +} + +int +usrp_standard_rx::format_shift(unsigned int format) +{ + return (format & bmFR_RX_FORMAT_SHIFT_MASK) >> bmFR_RX_FORMAT_SHIFT_SHIFT; +} + +bool +usrp_standard_rx::format_want_q(unsigned int format) +{ + return (format & bmFR_RX_FORMAT_WANT_Q) != 0; +} + +bool +usrp_standard_rx::format_bypass_halfband(unsigned int format) +{ + return (format & bmFR_RX_FORMAT_BYPASS_HB) != 0; +} + +////////////////////////////////////////////////////////////////// + + +// tx data is timed to CLKOUT1 (64 MHz) +// interpolate 4x +// fine modulator enabled + + +static unsigned char tx_regs_use_nco[] = { + REG_TX_IF, (TX_IF_USE_CLKOUT1 + | TX_IF_I_FIRST + | TX_IF_2S_COMP + | TX_IF_INTERLEAVED), + REG_TX_DIGITAL, (TX_DIGITAL_2_DATA_PATHS + | TX_DIGITAL_INTERPOLATE_4X) +}; + + +static int +real_tx_mux_value (int mux, int nchan) +{ + if (mux != -1) + return mux; + + switch (nchan){ + case 1: + return 0x0098; + case 2: + return 0xba98; + default: + assert (0); + } +} + +usrp_standard_tx::usrp_standard_tx (int which_board, + unsigned int interp_rate, + int nchan, int mux, + int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) + : usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename), + usrp_standard_common(this), + d_sw_mux (0x8), d_hw_mux (0x81) +{ + if (!usrp_9862_write_many_all (d_udh, tx_regs_use_nco, sizeof (tx_regs_use_nco))){ + fprintf (stderr, "usrp_standard_tx: failed to init AD9862 TX regs\n"); + throw std::runtime_error ("usrp_standard_tx::ctor"); + } + if (!set_nchannels (nchan)){ + fprintf (stderr, "usrp_standard_tx: set_nchannels failed\n"); + throw std::runtime_error ("usrp_standard_tx::ctor"); + } + if (!set_interp_rate (interp_rate)){ + fprintf (stderr, "usrp_standard_tx: set_interp_rate failed\n"); + throw std::runtime_error ("usrp_standard_tx::ctor"); + } + if (!set_mux (real_tx_mux_value (mux, nchan))){ + fprintf (stderr, "usrp_standard_tx: set_mux failed\n"); + throw std::runtime_error ("usrp_standard_tx::ctor"); + } + + for (int i = 0; i < MAX_CHAN; i++){ + d_tx_modulator_shadow[i] = (TX_MODULATOR_DISABLE_NCO + | TX_MODULATOR_COARSE_MODULATION_NONE); + d_coarse_mod[i] = CM_OFF; + set_tx_freq (i, 0); + } +} + +usrp_standard_tx::~usrp_standard_tx () +{ + // fprintf(stderr, "\nusrp_standard_tx: dtor\n"); +} + +bool +usrp_standard_tx::start () +{ + if (!usrp_basic_tx::start ()) + return false; + + // add our code here + + return true; +} + +bool +usrp_standard_tx::stop () +{ + bool ok = usrp_basic_tx::stop (); + + // add our code here + + return ok; +} + +usrp_standard_tx * +usrp_standard_tx::make (int which_board, + unsigned int interp_rate, + int nchan, int mux, + int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) +{ + usrp_standard_tx *u = 0; + + try { + u = new usrp_standard_tx (which_board, interp_rate, nchan, mux, + fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename); + return u; + } + catch (...){ + delete u; + return 0; + } + + return u; +} + +bool +usrp_standard_tx::set_interp_rate (unsigned int rate) +{ + // fprintf (stderr, "usrp_standard_tx::set_interp_rate\n"); + + if ((rate & 0x3) || rate < 4 || rate > 512){ + fprintf (stderr, "usrp_standard_tx::set_interp_rate: rate must be in [4, 512] and a multiple of 4.\n"); + return false; + } + + d_interp_rate = rate; + set_usb_data_rate ((dac_rate () / rate * nchannels ()) + * (2 * sizeof (short))); + + // We're using the interp by 4 feature of the 9862 so that we can + // use its fine modulator. Thus, we reduce the FPGA's interpolation rate + // by a factor of 4. + + bool s = disable_tx (); + bool ok = _write_fpga_reg (FR_INTERP_RATE, d_interp_rate/4 - 1); + restore_tx (s); + return ok; +} + +bool +usrp_standard_tx::set_nchannels (int nchan) +{ + if (!(nchan == 1 || nchan == 2)) + return false; + + if (nchan > nducs()) + return false; + + d_nchan = nchan; + return write_hw_mux_reg (); +} + +bool +usrp_standard_tx::set_mux (int mux) +{ + d_sw_mux = mux; + d_hw_mux = mux << 4; + return write_hw_mux_reg (); +} + +bool +usrp_standard_tx::write_hw_mux_reg () +{ + bool s = disable_tx (); + bool ok = _write_fpga_reg (FR_TX_MUX, d_hw_mux | d_nchan); + restore_tx (s); + return ok; +} + +#ifdef USE_FPGA_TX_CORDIC + +bool +usrp_standard_tx::set_tx_freq (int channel, double freq) +{ + if (channel < 0 || channel >= MAX_CHAN) + return false; + + // This assumes we're running the 4x on-chip interpolator. + + unsigned int v = + compute_freq_control_word_fpga (dac_freq () / 4, + freq, &d_tx_freq[channel], + d_verbose); + + return _write_fpga_reg (FR_TX_FREQ_0 + channel, v); +} + + +#else + +bool +usrp_standard_tx::set_tx_freq (int channel, double freq) +{ + if (channel < 0 || channel >= MAX_CHAN) + return false; + + // split freq into fine and coarse components + + coarse_mod_t cm; + double coarse; + + assert (dac_freq () == 128000000); + + if (freq < -44e6) // too low + return false; + else if (freq < -24e6){ // [-44, -24) + cm = CM_NEG_FDAC_OVER_4; + coarse = -dac_freq () / 4; + } + else if (freq < -8e6){ // [-24, -8) + cm = CM_NEG_FDAC_OVER_8; + coarse = -dac_freq () / 8; + } + else if (freq < 8e6){ // [-8, 8) + cm = CM_OFF; + coarse = 0; + } + else if (freq < 24e6){ // [8, 24) + cm = CM_POS_FDAC_OVER_8; + coarse = dac_freq () / 8; + } + else if (freq <= 44e6){ // [24, 44] + cm = CM_POS_FDAC_OVER_4; + coarse = dac_freq () / 4; + } + else // too high + return false; + + + set_coarse_modulator (channel, cm); // set bits in d_tx_modulator_shadow + + double fine = freq - coarse; + + + // Compute fine tuning word... + // This assumes we're running the 4x on-chip interpolator. + // (This is required to use the fine modulator.) + + unsigned int v = + compute_freq_control_word_9862 (dac_freq () / 4, + fine, &d_tx_freq[channel], d_verbose); + + d_tx_freq[channel] += coarse; // adjust actual + + unsigned char high, mid, low; + + high = (v >> 16) & 0xff; + mid = (v >> 8) & 0xff; + low = (v >> 0) & 0xff; + + bool ok = true; + + // write the fine tuning word + ok &= _write_9862 (channel, REG_TX_NCO_FTW_23_16, high); + ok &= _write_9862 (channel, REG_TX_NCO_FTW_15_8, mid); + ok &= _write_9862 (channel, REG_TX_NCO_FTW_7_0, low); + + + d_tx_modulator_shadow[channel] |= TX_MODULATOR_ENABLE_NCO; + + if (fine < 0) + d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_FINE_TUNE; + else + d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_NEG_FINE_TUNE; + + ok &=_write_9862 (channel, REG_TX_MODULATOR, d_tx_modulator_shadow[channel]); + + return ok; +} +#endif + +bool +usrp_standard_tx::set_coarse_modulator (int channel, coarse_mod_t cm) +{ + if (channel < 0 || channel >= MAX_CHAN) + return false; + + switch (cm){ + case CM_NEG_FDAC_OVER_4: + d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK; + d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4; + d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE; + break; + + case CM_NEG_FDAC_OVER_8: + d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK; + d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8; + d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE; + break; + + case CM_OFF: + d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK; + break; + + case CM_POS_FDAC_OVER_8: + d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK; + d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8; + break; + + case CM_POS_FDAC_OVER_4: + d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK; + d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4; + break; + + default: + return false; + } + + d_coarse_mod[channel] = cm; + return true; +} + +unsigned int +usrp_standard_tx::interp_rate () const { return d_interp_rate; } + +int +usrp_standard_tx::nchannels () const { return d_nchan; } + +int +usrp_standard_tx::mux () const { return d_sw_mux; } + +double +usrp_standard_tx::tx_freq (int channel) const +{ + if (channel < 0 || channel >= MAX_CHAN) + return 0; + + return d_tx_freq[channel]; +} + +usrp_standard_tx::coarse_mod_t +usrp_standard_tx::coarse_modulator (int channel) const +{ + if (channel < 0 || channel >= MAX_CHAN) + return CM_OFF; + + return d_coarse_mod[channel]; +} diff --git a/usrp/host/lib/usrp_standard.h b/usrp/host/lib/usrp_standard.h new file mode 100644 index 00000000..9f468a68 --- /dev/null +++ b/usrp/host/lib/usrp_standard.h @@ -0,0 +1,366 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_USRP_STANDARD_H +#define INCLUDED_USRP_STANDARD_H + +#include + +class usrp_standard_common +{ + int d_fpga_caps; // capability register val + +protected: + usrp_standard_common(usrp_basic *parent); + +public: + /*! + *\brief does the FPGA implement the final Rx half-band filter? + * If it doesn't, the maximum decimation factor with proper gain + * is 1/2 of what it would otherwise be. + */ + bool has_rx_halfband() const; + + /*! + * \brief number of digital downconverters implemented in the FPGA + * This will be 0, 1, 2 or 4. + */ + int nddcs() const; + + /*! + *\brief does the FPGA implement the initial Tx half-band filter? + */ + bool has_tx_halfband() const; + + /*! + * \brief number of digital upconverters implemented in the FPGA + * This will be 0, 1, or 2. + */ + int nducs() const; +}; + +/*! + * \brief standard usrp RX class. + * + * Assumes digital down converter in FPGA + */ +class usrp_standard_rx : public usrp_basic_rx, usrp_standard_common +{ + private: + static const int MAX_CHAN = 4; + unsigned int d_decim_rate; + int d_nchan; + int d_sw_mux; + int d_hw_mux; + double d_rx_freq[MAX_CHAN]; + + protected: + usrp_standard_rx (int which_board, + unsigned int decim_rate, + int nchan = 1, + int mux = -1, + int mode = 0, + int fusb_block_size = 0, + int fusb_nblocks = 0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); // throws if trouble + + bool write_hw_mux_reg (); + + public: + + enum { + FPGA_MODE_NORMAL = 0x00, + FPGA_MODE_LOOPBACK = 0x01, + FPGA_MODE_COUNTING = 0x02, + FPGA_MODE_COUNTING_32BIT = 0x04 + }; + + ~usrp_standard_rx (); + + /*! + * \brief invokes constructor, returns instance or 0 if trouble + * + * \param which_board Which USRP board on usb (not particularly useful; use 0) + * \param fusb_block_size fast usb xfer block size. Must be a multiple of 512. + * Use zero for a reasonable default. + * \param fusb_nblocks number of fast usb URBs to allocate. Use zero for a reasonable default. + */ + static usrp_standard_rx *make (int which_board, + unsigned int decim_rate, + int nchan = 1, + int mux = -1, + int mode = 0, + int fusb_block_size = 0, + int fusb_nblocks = 0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); + /*! + * \brief Set decimator rate. \p rate MUST BE EVEN and in [8, 256]. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () * nchannels () + */ + bool set_decim_rate (unsigned int rate); + + /*! + * \brief Set number of active channels. \p nchannels must be 1, 2 or 4. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () * nchannels () + */ + bool set_nchannels (int nchannels); + + /*! + * \brief Set input mux configuration. + * + * This determines which ADC (or constant zero) is connected to + * each DDC input. There are 4 DDCs. Each has two inputs. + * + *
+   * Mux value:
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * Each 4-bit I field is either 0,1,2,3
+   * Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
+   * All Q's must be 0xf or none of them may be 0xf
+   * 
+ */ + bool set_mux (int mux); + + /*! + * \brief set the frequency of the digital down converter. + * + * \p channel must be in the range [0,3]. \p freq is the center + * frequency in Hz. \p freq may be either negative or postive. + * The frequency specified is quantized. Use rx_freq to retrieve + * the actual value used. + */ + bool set_rx_freq (int channel, double freq); + + /*! + * \brief set fpga mode + */ + bool set_fpga_mode (int mode); + + /*! + * \brief Set the digital down converter phase register. + * + * \param channel which ddc channel [0, 3] + * \param phase 32-bit integer phase value. + */ + bool set_ddc_phase(int channel, int phase); + + /*! + * \brief Specify Rx data format. + * + * \param format format specifier + * + * Rx data format control register + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------------------------------------+-+-+---------+-------+ + * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | + * +-----------------------------------------+-+-+---------+-------+ + * + * SHIFT specifies arithmetic right shift [0, 15] + * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) + * Q if set deliver both I & Q, else just I + * B if set bypass half-band filter. + * + * Right now the acceptable values are: + * + * B Q WIDTH SHIFT + * 0 1 16 0 + * 0 1 8 8 + * + * More valid combos to come. + * + * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. + */ + bool set_format(unsigned int format); + + static unsigned int make_format(int width=16, int shift=0, + bool want_q=true, bool bypass_halfband=false); + static int format_width(unsigned int format); + static int format_shift(unsigned int format); + static bool format_want_q(unsigned int format); + static bool format_bypass_halfband(unsigned int format); + + // ACCESSORS + unsigned int decim_rate () const; + double rx_freq (int channel) const; + int nchannels () const; + int mux () const; + unsigned int format () const; + + // called in base class to derived class order + bool start (); + bool stop (); +}; + +// ---------------------------------------------------------------- + +/*! + * \brief standard usrp TX class. + * + * Uses digital upconverter (coarse & fine modulators) in AD9862... + */ +class usrp_standard_tx : public usrp_basic_tx, usrp_standard_common +{ + public: + enum coarse_mod_t { + CM_NEG_FDAC_OVER_4, // -32 MHz + CM_NEG_FDAC_OVER_8, // -16 MHz + CM_OFF, + CM_POS_FDAC_OVER_8, // +16 MHz + CM_POS_FDAC_OVER_4 // +32 MHz + }; + + protected: + static const int MAX_CHAN = 2; + unsigned int d_interp_rate; + int d_nchan; + int d_sw_mux; + int d_hw_mux; + double d_tx_freq[MAX_CHAN]; + coarse_mod_t d_coarse_mod[MAX_CHAN]; + unsigned char d_tx_modulator_shadow[MAX_CHAN]; + + virtual bool set_coarse_modulator (int channel, coarse_mod_t cm); + usrp_standard_tx::coarse_mod_t coarse_modulator (int channel) const; + + protected: + usrp_standard_tx (int which_board, + unsigned int interp_rate, + int nchan = 1, + int mux = -1, + int fusb_block_size = 0, + int fusb_nblocks = 0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); // throws if trouble + + bool write_hw_mux_reg (); + + public: + ~usrp_standard_tx (); + + /*! + * \brief invokes constructor, returns instance or 0 if trouble + * + * \param which_board Which USRP board on usb (not particularly useful; use 0) + * \param fusb_block_size fast usb xfer block size. Must be a multiple of 512. + * Use zero for a reasonable default. + * \param fusb_nblocks number of fast usb URBs to allocate. Use zero for a reasonable default. + */ + static usrp_standard_tx *make (int which_board, + unsigned int interp_rate, + int nchan = 1, + int mux = -1, + int fusb_block_size = 0, + int fusb_nblocks = 0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); + + /*! + * \brief Set interpolator rate. \p rate must be in [4, 512] and a multiple of 4. + * + * The final complex sample rate across the USB is + * dac_freq () / interp_rate () * nchannels () + */ + virtual bool set_interp_rate (unsigned int rate); + + /*! + * \brief Set number of active channels. \p nchannels must be 1 or 2. + * + * The final complex sample rate across the USB is + * dac_freq () / decim_rate () * nchannels () + */ + bool set_nchannels (int nchannels); + + /*! + * \brief Set output mux configuration. + * + *
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-------------------------------+-------+-------+-------+-------+
+   *  |                               | DAC3  | DAC2  | DAC1  |  DAC0 |
+   *  +-------------------------------+-------+-------+-------+-------+
+   * 
+   *  There are two interpolators with complex inputs and outputs.
+   *  There are four DACs.
+   * 
+   *  Each 4-bit DACx field specifies the source for the DAC and
+   *  whether or not that DAC is enabled.  Each subfield is coded
+   *  like this: 
+   * 
+   *     3 2 1 0
+   *    +-+-----+
+   *    |E|  N  |
+   *    +-+-----+
+   * 
+   *  Where E is set if the DAC is enabled, and N specifies which
+   *  interpolator output is connected to this DAC.
+   * 
+   *   N   which interp output
+   *  ---  -------------------
+   *   0   chan 0 I
+   *   1   chan 0 Q
+   *   2   chan 1 I
+   *   3   chan 1 Q
+   * 
+ */ + bool set_mux (int mux); + + /*! + * \brief set the frequency of the digital up converter. + * + * \p channel must be in the range [0,1]. \p freq is the center + * frequency in Hz. It must be in the range [-44M, 44M]. + * The frequency specified is quantized. Use tx_freq to retrieve + * the actual value used. + */ + virtual bool set_tx_freq (int channel, double freq); // chan: [0,1] + + // ACCESSORS + unsigned int interp_rate () const; + double tx_freq (int channel) const; + int nchannels () const; + int mux () const; + + // called in base class to derived class order + bool start (); + bool stop (); +}; + +#endif /* INCLUDED_USRP_STANDARD_H */ diff --git a/usrp/host/misc/Makefile.am b/usrp/host/misc/Makefile.am new file mode 100644 index 00000000..08826a0b --- /dev/null +++ b/usrp/host/misc/Makefile.am @@ -0,0 +1,31 @@ +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + getopt.c getopt.h \ + gettimeofday.c \ + tempname.c mkstemp.c \ + usleep.c + +noinst_LTLIBRARIES = libmisc.la + +libmisc_la_SOURCES = bug_work_around_8.cc +libmisc_la_LIBADD = @LTLIBOBJS@ diff --git a/usrp/host/misc/bug_work_around_8.cc b/usrp/host/misc/bug_work_around_8.cc new file mode 100644 index 00000000..41943247 --- /dev/null +++ b/usrp/host/misc/bug_work_around_8.cc @@ -0,0 +1,2 @@ +// if libmisc has no sources, it doesn't get built correctly +int gr_bug_work_around_8; diff --git a/usrp/host/misc/getopt.c b/usrp/host/misc/getopt.c new file mode 100644 index 00000000..93fb6ea5 --- /dev/null +++ b/usrp/host/misc/getopt.c @@ -0,0 +1,733 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* NOTE!!! AIX requires this to be the first thing in the file. + Do not put ANYTHING before it! */ +#if !defined (__GNUC__) && defined (_AIX) + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) +#include +#else +#ifndef _AIX +char *alloca (); +#endif +#endif /* alloca.h */ +#endif /* not __GNUC__ */ + +#if !__STDC__ && !defined(const) && IN_GCC +#define const +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#undef alloca +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#else /* Not GNU C library. */ +#define __alloca alloca +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +static void +my_bcopy (from, to, size) + const char *from; + char *to; + int size; +{ + int i; + for (i = 0; i < size; i++) + to[i] = from[i]; +} +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); + char **temp = (char **) __alloca (nonopts_size); + + /* Interchange the two blocks of data in ARGV. */ + + my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); + my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], + (optind - last_nonopt) * sizeof (char *)); + my_bcopy ((char *) temp, + (char *) &argv[first_nonopt + optind - last_nonopt], + nonopts_size); + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +#ifdef GETOPT +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} +#endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/usrp/host/misc/getopt.h b/usrp/host/misc/getopt.h new file mode 100644 index 00000000..45541f5a --- /dev/null +++ b/usrp/host/misc/getopt.h @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 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 2, 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, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/usrp/host/misc/gettimeofday.c b/usrp/host/misc/gettimeofday.c new file mode 100644 index 00000000..4ed15e21 --- /dev/null +++ b/usrp/host/misc/gettimeofday.c @@ -0,0 +1,50 @@ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#ifdef HAVE_WINDOWS_H +#include +#endif +#ifdef HAVE_WINBASE_H +# include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +/* + * broken implementation for WIN32. + * FIXME: usec precision + */ +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + if (tv) { + time_t tm; + + time(&tm); + tv->tv_sec = tm; + tv->tv_usec = 0; + } + return 0; +} + diff --git a/usrp/host/misc/mkstemp.c b/usrp/host/misc/mkstemp.c new file mode 100644 index 00000000..f6312b64 --- /dev/null +++ b/usrp/host/misc/mkstemp.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is derived from the one in the GNU C Library. + + 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +/* Disable the definition of mkstemp to rpl_mkstemp (from config.h) in this + file. Otherwise, we'd get conflicting prototypes for rpl_mkstemp on + most systems. */ +#undef mkstemp + +#include +#include + +#ifndef __GT_FILE +# define __GT_FILE 0 +#endif + +int __gen_tempname (); + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int +rpl_mkstemp (char *template) +{ + return __gen_tempname (template, __GT_FILE); +} diff --git a/usrp/host/misc/tempname.c b/usrp/host/misc/tempname.c new file mode 100644 index 00000000..2e78dfc1 --- /dev/null +++ b/usrp/host/misc/tempname.c @@ -0,0 +1,352 @@ +/* tempname.c - generate the name of a temporary file. + + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#ifndef P_tmpdir +# define P_tmpdir "/tmp" +#endif +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif +#ifndef __GT_FILE +# define __GT_FILE 0 +# define __GT_BIGFILE 1 +# define __GT_DIR 2 +# define __GT_NOCREATE 3 +#endif + +#include +#include +#include + +#if HAVE_FCNTL_H || _LIBC +# include +#endif + +#if HAVE_SYS_TIME_H || _LIBC +# include +#endif + +#if HAVE_STDINT_H || _LIBC +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif + +#if HAVE_UNISTD_H || _LIBC +# include +#endif + +#include +#if STAT_MACROS_BROKEN +# undef S_ISDIR +#endif +#if !defined S_ISDIR && defined S_IFDIR +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif + +#if _LIBC +# define struct_stat64 struct stat64 +#else +# define struct_stat64 struct stat +# define __getpid getpid +# define __gettimeofday gettimeofday +#ifdef MKDIR_TAKES_ONE_ARG +# define __mkdir(pathname,mode) mkdir((pathname)) +#else +# define __mkdir mkdir +#endif +# define __open open +# define __open64 open +#ifdef HAVE_LSTAT +# define __lxstat64(version, path, buf) lstat (path, buf) +#else +# define __lxstat64(version, path, buf) stat (path, buf) +#endif +# define __xstat64(version, path, buf) stat (path, buf) +#endif + +#if ! (HAVE___SECURE_GETENV || _LIBC) +# define __secure_getenv getenv +#endif + +#ifdef _LIBC +# include +# if HP_TIMING_AVAIL +# define RANDOM_BITS(Var) \ + if (__builtin_expect (value == UINT64_C (0), 0)) \ + { \ + /* If this is the first time this function is used initialize \ + the variable we accumulate the value in to some somewhat \ + random value. If we'd not do this programs at startup time \ + might have a reduced set of possible names, at least on slow \ + machines. */ \ + struct timeval tv; \ + __gettimeofday (&tv, NULL); \ + value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ + } \ + HP_TIMING_NOW (Var) +# endif +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (const char *dir) +{ + struct_stat64 buf; + return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to __gen_tempname. TMPL is + overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + __GT_BIGFILE: same as __GT_FILE but use open64(). + __GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +int +__gen_tempname (char *tmpl, int kind) +{ + int len; + char *XXXXXX; + static uint64_t value; + uint64_t random_time_bits; + unsigned int count; + int fd = -1; + int save_errno = errno; + struct_stat64 st; + + /* A lower bound on the number of temporary files to attempt to + generate. The maximum total number of temporary file names that + can exist for a given template is 62**6. It should never be + necessary to try all these combinations. Instead if a reasonable + number of names is tried (we define reasonable as 62**3) fail to + give the system administrator the chance to remove the problems. */ + unsigned int attempts_min = 62 * 62 * 62; + + /* The number of times to attempt to generate a temporary file. To + conform to POSIX, this must be no smaller than TMP_MAX. */ + unsigned int attempts = attempts_min < TMP_MAX ? TMP_MAX : attempts_min; + + len = strlen (tmpl); + if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6]; + + /* Get some more or less random data. */ +#ifdef RANDOM_BITS + RANDOM_BITS (random_time_bits); +#else +# if HAVE_GETTIMEOFDAY || _LIBC + { + struct timeval tv; + __gettimeofday (&tv, NULL); + random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; + } +# else + random_time_bits = time (NULL); +# endif +#endif + value += random_time_bits ^ __getpid (); + + for (count = 0; count < attempts; value += 7777, ++count) + { + uint64_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + switch (kind) + { + case __GT_FILE: + fd = __open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_BIGFILE: + fd = __open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_DIR: + fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + break; + + case __GT_NOCREATE: + /* This case is backward from the other three. __gen_tempname + succeeds if __xstat fails because the name does not exist. + Note the continue to bypass the common logic at the bottom + of the loop. */ + if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) + { + if (errno == ENOENT) + { + __set_errno (save_errno); + return 0; + } + else + /* Give up now. */ + return -1; + } + continue; + + default: + assert (! "invalid KIND in __gen_tempname"); + } + + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} diff --git a/usrp/host/misc/usleep.c b/usrp/host/misc/usleep.c new file mode 100644 index 00000000..4a0f75ea --- /dev/null +++ b/usrp/host/misc/usleep.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + +#ifndef HAVE_USLEEP + +#include +#include + +#ifdef HAVE_SYS_SELECT_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif +#ifdef HAVE_WINBASE_H +# include +#endif + +#ifdef apollo +# include +# include + static time_$clock_t DomainTime100mS = + { + 0, 100000/4 + }; + static status_$t DomainStatus; +#endif + +/* Sleep USECONDS microseconds, or until a previously set timer goes off. */ +int +usleep (unsigned long useconds) +{ +#ifdef apollo + /* The usleep function does not work under the SYS5.3 environment. + Use the Domain/OS time_$wait call instead. */ + time_$wait (time_$relative, DomainTime100mS, &DomainStatus); +#elif defined(HAVE_SSLEEP) /* Win32 */ + Sleep( useconds/1000 ); +#else + struct timeval delay; + + delay.tv_sec = 0; + delay.tv_usec = useconds; + select (0, 0, 0, 0, &delay); +#endif + return 0; +} + +#endif /* !HAVE_USLEEP */ diff --git a/usrp/host/swig/Makefile.am b/usrp/host/swig/Makefile.am new file mode 100644 index 00000000..469a5d70 --- /dev/null +++ b/usrp/host/swig/Makefile.am @@ -0,0 +1,84 @@ +# +# Copyright 2001,2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/usrp_prims + +ourpythondir = $(pythondir) +ourlibdir = $(pyexecdir) + + +LOCAL_IFILES = \ + prims.i + + +ALL_IFILES = \ + $(LOCAL_IFILES) + + +EXTRA_DIST = \ + $(LOCAL_IFILES) + + +BUILT_SOURCES = \ + prims.cc \ + usrp_prims.py + + +ourpython_PYTHON = \ + __init__.py \ + usrp_fpga_regs.py \ + usrp_prims.py + + +INCLUDES = -I$(top_srcdir)/usrp/firmware/include $(PYTHON_CPPFLAGS) -I$(srcdir) + + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(INCLUDES) + + +ourlib_LTLIBRARIES = \ + _usrp_prims.la + +_usrp_prims_la_SOURCES = \ + prims.cc + + +noinst_HEADERS = + +_usrp_prims_la_LIBADD = $(top_builddir)/usrp/host/lib/libusrp.la -lstdc++ $(PYTHON_LDFLAGS) +_usrp_prims_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + + +prims.cc usrp_prims.py : prims.i ../../firmware/include/fpga_regs_common.h ../../firmware/include/fpga_regs_standard.h + $(SWIG) $(SWIGPYTHONARGS) -module usrp_prims -o prims.cc $< + + +MOSTLYCLEANFILES = \ + prims.cc usrp_prims.py *~ *.pyc + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done + diff --git a/usrp/host/swig/__init__.py b/usrp/host/swig/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/usrp/host/swig/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/usrp/host/swig/prims.i b/usrp/host/swig/prims.i new file mode 100644 index 00000000..bbf960c2 --- /dev/null +++ b/usrp/host/swig/prims.i @@ -0,0 +1,266 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Low level primitives for directly messing with USRP hardware. + * + * If you're trying to use the USRP, you'll probably want to take a + * look at the usrp_standard_rx and usrp_standard_tx classes. They + * hide a bunch of low level details and provide high performance + * streaming i/o. + * + * This interface is built on top of libusb, which allegedly works under + * Linux, *BSD and Mac OS/X. http://libusb.sourceforge.net + */ + +%include // pick up string stuff + + +%{ +#include +%} + + +enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; + +struct usb_dev_handle; +struct usb_device; + +/*! + * \brief initialize libusb; probe busses and devices. + * Safe to call more than once. + */ +void usrp_one_time_init (); + +void usrp_rescan (); + +/*! + * \brief locate Nth (zero based) USRP device in system. + * Return pointer or 0 if not found. + * + * The following kinds of devices are considered USRPs: + * + * unconfigured USRP (no firwmare loaded) + * configured USRP (firmware loaded) + * unconfigured Cypress FX2 (only if fx2_ok_p is true) + */ +struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false); + +bool usrp_usrp_p (struct usb_device *q); //< is this a USRP +bool usrp_usrp0_p (struct usb_device *q); //< is this a USRP Rev 0 +bool usrp_usrp1_p (struct usb_device *q); //< is this a USRP Rev 1 +bool usrp_usrp2_p (struct usb_device *q); //< is this a USRP Rev 2 +int usrp_hw_rev (struct usb_device *q); //< return h/w rev code +bool usrp_fx2_p (struct usb_device *q); //< is this an unconfigured Cypress FX2 + +bool usrp_unconfigured_usrp_p (struct usb_device *q); //< some kind of unconfigured USRP +bool usrp_configured_usrp_p (struct usb_device *q); //< some kind of configured USRP + +/*! + * \brief given a usb_device return an instance of the appropriate usb_dev_handle + * + * These routines claim the specified interface and select the + * correct alternate interface. (USB nomenclature is totally screwed!) + * + * If interface can't be opened, or is already claimed by some other + * process, 0 is returned. + */ +struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev); +struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev); +struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev); + +/*! + * \brief close interface. + */ +bool usrp_close_interface (struct usb_dev_handle *udh); + +/*! + * \brief load intel hex format file into USRP/Cypress FX2 (8051). + * + * The filename extension is typically *.ihx + * + * Note that loading firmware may cause the device to renumerate. I.e., + * change its configuration, invalidating the current device handle. + */ + +usrp_load_status_t +usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force); + +/*! + * \brief load intel hex format file into USRP FX2 (8051). + * + * The filename extension is typically *.ihx + * + * Note that loading firmware may cause the device to renumerate. I.e., + * change its configuration, invalidating the current device handle. + * If the result is ULS_OK, usrp_load_firmware_nth delays 1 second + * then rescans the busses and devices. + */ +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force); + +/*! + * \brief load fpga configuration bitstream + */ +usrp_load_status_t +usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force); + +/*! + * \brief load the regular firmware and fpga bitstream in the Nth USRP. + * + * This is the normal starting point... + */ +bool usrp_load_standard_bits (int nth, bool force); + + +%include +%include + + +bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value); + +%inline %{ + +int +usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg) +{ + int value; + bool ok = usrp_read_fpga_reg (udh, reg, &value); + if (ok) + return value; + else + return -999; +} + +%} + +bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on); + +bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p); +bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p); + +// i2c_read and i2c_write are limited to a maximum len of 64 bytes. + +bool usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr, + void *buf, int len); + +bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, + void *buf, int len); + +// spi_read and spi_write are limited to a maximum of 64 bytes +// See usrp_spi_defs.h for more info + +bool usrp_spi_write (struct usb_dev_handle *udh, + int optional_header, int enables, int format, + unsigned char *buf, int len); + +bool usrp_spi_read (struct usb_dev_handle *udh, + int optional_header, int enables, int format, + unsigned char *buf, int len); + + +bool usrp_9862_write (struct usb_dev_handle *udh, + int which_codec, // [0, 1] + int regno, // [0, 63] + int value); // [0, 255] + +%inline %{ + +int +usrp_9862_read (struct usb_dev_handle *udh, int which_codec, int reg) +{ + unsigned char value; + bool ok = usrp_9862_read (udh, which_codec, reg, &value); + if (ok) + return value; + else + return -999; +} + +%} + +%inline %{ + +bool +usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, + int eeprom_offset, const std::string buf) +{ + return usrp_eeprom_write (udh, i2c_addr, eeprom_offset, + buf.data (), buf.size ()); +} + +std::string +usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, + int eeprom_offset, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_eeprom_read (udh, i2c_addr, eeprom_offset, buf, len)) + return ""; + + return std::string (buf, len); +} + +%} + +bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot, + int which_dac, int value); + +%inline %{ + +int usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, int which_adc) +{ + int value; + bool ok = usrp_read_aux_adc (udh, slot, which_adc, &value); + if (ok) + return value; + else + return -999; +} + +%} + +/*! + * \brief return a usrp's serial number. + * + * Note that this only works on a configured usrp. + * \returns non-zero length string iff successful. + */ +std::string usrp_serial_number(struct usb_dev_handle *udh); + +/*! + * \brief usrp daughterboard id to name mapping + */ +const std::string usrp_dbid_to_string (int dbid); + +%inline %{ +#include "../../firmware/include/fpga_regs_common.h" +#include "../../firmware/include/fpga_regs_standard.h" +%} diff --git a/usrp/host/swig/usrp_fpga_regs.py b/usrp/host/swig/usrp_fpga_regs.py new file mode 100644 index 00000000..9fdf62ca --- /dev/null +++ b/usrp/host/swig/usrp_fpga_regs.py @@ -0,0 +1,30 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +import usrp_prims + +# Copy everything that starts with FR_ or bmFR_ from the usrp_prims +# name space into our name space. This is effectively a python binding for +# the contents of firmware/include/fpga_regs_common.h and fpga_regs_standard.h + +for name in dir(usrp_prims): + if name.startswith("FR_") or name.startswith("bmFR_"): + globals()[name] = usrp_prims.__dict__[name] diff --git a/usrp/host/swig/util.py b/usrp/host/swig/util.py new file mode 100644 index 00000000..089bcaaa --- /dev/null +++ b/usrp/host/swig/util.py @@ -0,0 +1,95 @@ +# utilities + +from usrp_prims import * + +def setup (which_board = 0): + if not usrp_load_standard_bits (which_board, False): + raise RuntimeError, "usrp_load_standard_bits" + dev = usrp_find_device (which_board) + if not dev: + raise RuntimeError, "usrp_find_device" + u = usrp_open_cmd_interface (dev) + if not u: + raise RuntimeError, "usrp_open_cmd_interface" + + # FIXME setup high speed paths, Aux ADC Clock, ... + + # usrp_9862_write (u, 0, 35, 0x1) # aux ADC clock = CLK/4 + # usrp_9862_write (u, 1, 35, 0x1) + + return u + +def write_slot_oe (u, slot, value, mask): + assert 0 <= slot and slot < 4 + return usrp_write_fpga_reg (u, slot + FR_OE_0, + ((mask & 0xffff) << 16) | (value & 0xffff)) + +def write_slot_io (u, slot, value, mask): + assert 0 <= slot and slot < 4 + return usrp_write_fpga_reg (u, slot + FR_IO_0, + ((mask & 0xffff) << 16) | (value & 0xffff)) + + +# ---------------------------------------------------------------- + + +def ramp_aux_dac (u, which_codec, which_dac): + if not (which_codec == 0 or which_codec == 1): + raise AssertionError + if not (which_dac >= 0 and which_dac < 4): + raise AssertionError + try: + if which_dac == 3: # sigma delta output + sigma_delta_loop (u, which_codec) + else: + aux_dac_loop (u, which_codec, which_dac) + except KeyboardInterrupt: + return + +def sigma_delta_loop (u, which_codec): + counter = 0 + while True: + usrp_9862_write (u, which_codec, 43, counter >> 4) + usrp_9862_write (u, which_codec, 42, (counter & 0xf) << 4) + # counter += 1 FIXME + counter += 4 + if counter > 0xfff: + counter = 0 + +def aux_dac_loop (u, which_codec, which_dac): + reg = 36 + which_dac # Aux DAC A,B,C + counter = 0 + while True: + usrp_9862_write (u, which_codec, reg, counter) + counter += 1 + if counter > 0xff: + counter = 0 + + +def read_aux_adc_loop (u, slot, which_adc): + while True: + v = usrp_read_aux_adc (u, slot, which_adc) + print "%3d %5.3f" % (v, v * 3.3 / 1024) + +def ramp_io_port (u, slot): + counter = 0 + try: + while True: + write_slot_io (u, slot, counter, 0xffff) + counter += 1 + if counter > 0xffff: + counter = 0 + except KeyboardInterrupt: + return + +def walk_io_port (u, slot): + bit = 1 + try: + while True: + write_slot_io (u, slot, bit, 0xffff) + bit = (bit << 1) & 0xffff + if bit == 0: + bit = 1 + except KeyboardInterrupt: + return + diff --git a/usrp/usrp.inf b/usrp/usrp.inf new file mode 100644 index 00000000..b612d1e3 --- /dev/null +++ b/usrp/usrp.inf @@ -0,0 +1,91 @@ +[Version] +Signature = "$Chicago$" +provider = %manufacturer% +DriverVer = 03/09/2005,0.1.10.1 +CatalogFile = usrp.cat + +Class = LibUsbDevices +ClassGUID = {EB781AAF-9C70-4523-A5DF-642A87ECA567} + +[ClassInstall] +AddReg=ClassInstall.AddReg + +[ClassInstall32] +AddReg=ClassInstall.AddReg + +[ClassInstall.AddReg] +HKR,,,,"LibUSB-Win32 Devices" +HKR,,Icon,,"-20" + +[Manufacturer] +%manufacturer%=Devices + +;-------------------------------------------------------------------------- +; Files +;-------------------------------------------------------------------------- + +[SourceDisksNames] +1 = "Libusb-Win32 Driver Installation Disk",, + +[SourceDisksFiles] +libusb0.sys = 1,, +libusb0.dll = 1,, + +[DestinationDirs] +LIBUSB.Files.Sys = 10,System32\Drivers +LIBUSB.Files.Dll = 10,System32 + +[LIBUSB.Files.Sys] +libusb0.sys + +[LIBUSB.Files.Dll] +libusb0.dll + +;-------------------------------------------------------------------------- +; Device driver +;-------------------------------------------------------------------------- + +[LIBUSB_DEV] +CopyFiles = LIBUSB.Files.Sys, LIBUSB.Files.Dll +AddReg = LIBUSB_DEV.AddReg + +[LIBUSB_DEV.NT] +CopyFiles = LIBUSB.Files.Sys, LIBUSB.Files.Dll + +[LIBUSB_DEV.HW] +DelReg = LIBUSB_DEV.DelReg.HW + +[LIBUSB_DEV.NT.HW] +DelReg = LIBUSB_DEV.DelReg.HW + +[LIBUSB_DEV.NT.Services] +AddService = libusb0, 0x00000002, LIBUSB.AddService + +[LIBUSB_DEV.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,libusb0.sys + +[LIBUSB_DEV.DelReg.HW] +HKR,,"LowerFilters" + +;-------------------------------------------------------------------------- +; Services +;-------------------------------------------------------------------------- + +[LIBUSB.AddService] +DisplayName = "LibUsb-Win32 - Kernel Driver 03/09/2005, 0.1.10.1" +ServiceType = 1 +StartType = 3 +ErrorControl = 0 +ServiceBinary = %12%\libusb0.sys + +;-------------------------------------------------------------------------- +; Devices +;-------------------------------------------------------------------------- + +[Devices] +"USRP filter"=LIBUSB_DEV, USB\VID_fffe&PID_0002 + +[Strings] +manufacturer = "GNU Radio folks" + diff --git a/usrp/usrp.iss.in b/usrp/usrp.iss.in new file mode 100644 index 00000000..b9a4f75a --- /dev/null +++ b/usrp/usrp.iss.in @@ -0,0 +1,69 @@ +; +; Copyright 2003 Free Software Foundation, Inc. +; +; This file is part of GNU Radio +; +; GNU Radio is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. +; +; GNU Radio is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GNU Radio; see the file COPYING. If not, write to +; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +; Boston, MA 02111-1307, USA. +; + +; Requirements: Inno Setup (http://www.jrsoftware.org/isdl.php) +; +; To compile this script do the following: +; - copy libusb's driver (libusb0.sys, libusb0.dll) to this folder +; - copy the USRP filter .inf file to this folder +; - copy the USRP .exe and .dll files to this folder +; - open this scipt with Inno Setup +; - compile and run + +[Setup] +AppName=USRP +AppVerName=USRP @VERSION@ +AppPublisher=GNU Radio folks +AppPublisherURL=http://www.gnu.org/software/gnuradio/ +AppVersion=@VERSION@ +DefaultDirName={pf}\Usrp +DefaultGroupName=Usrp +Compression=lzma +SolidCompression=yes +; Win98 or higher +MinVersion=4,5 +PrivilegesRequired=admin +LicenseFile="COPYING_GPL.txt" + +[Files] +; copy the file to the App folder +Source: "*.sys"; DestDir: "{app}\driver" +;Source: "*.cat"; DestDir: "{app}\driver" +Source: "*.dll"; DestDir: "{app}\driver" +Source: "usrp.inf"; DestDir: "{app}\driver" + +; also copy the DLL to the system folders so that rundll32.exe will find it +Source: "*.dll"; DestDir: "{win}\system32"; FLags: replacesameversion restartreplace + +Source: "COPYING_GPL.txt"; DestDir: "{app}" +Source: "README.txt"; DestDir: "{app}"; Flags: isreadme + +Source: "*.exe"; DestDir: "{app}" +Source: "*.ihx"; DestDir: "{app}\rev2" +Source: "*.rbf"; DestDir: "{app}\rev2" + +[Icons] +Name: "{group}\Uninstall TestDrivers"; Filename: "{uninstallexe}" + +[Run] +; invoke libusb's DLL to install the .inf file +Filename: "rundll32"; Parameters: "libusb0.dll,usb_install_driver_np_rundll {app}\driver\usrp.inf"; StatusMsg: "Installing driver (this may take a few seconds) ..." + diff --git a/usrp/usrp.pc.in b/usrp/usrp.pc.in new file mode 100644 index 00000000..49d27e7d --- /dev/null +++ b/usrp/usrp.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: usrp +Description: Universal Software Radio Peripheral +Requires: +Version: @VERSION@ +Libs: -L${libdir} -lusrp -lusb +Cflags: -I${includedir} @DEFINES@